Version 2.14.0-377.1.beta
Merge '2.14.0-377.0.dev' into beta
diff --git a/.dart_tool/package_config.json b/.dart_tool/package_config.json
index 204df98..faad814 100644
--- a/.dart_tool/package_config.json
+++ b/.dart_tool/package_config.json
@@ -11,7 +11,7 @@
"constraint, update this by running tools/generate_package_config.dart."
],
"configVersion": 2,
- "generated": "2021-07-02T15:48:57.033703",
+ "generated": "2021-07-27T19:27:52.638315",
"generator": "tools/generate_package_config.dart",
"packages": [
{
@@ -64,7 +64,7 @@
"name": "_js_interop_checks",
"rootUri": "../pkg/_js_interop_checks",
"packageUri": "lib/",
- "languageVersion": "2.7"
+ "languageVersion": "2.12"
},
{
"name": "analysis_server",
@@ -142,13 +142,13 @@
"name": "browser_launcher",
"rootUri": "../third_party/pkg/browser_launcher",
"packageUri": "lib/",
- "languageVersion": "2.2"
+ "languageVersion": "2.12"
},
{
"name": "build_integration",
"rootUri": "../pkg/build_integration",
"packageUri": "lib/",
- "languageVersion": "2.1"
+ "languageVersion": "2.12"
},
{
"name": "charcode",
@@ -250,7 +250,7 @@
"name": "dev_compiler",
"rootUri": "../pkg/dev_compiler",
"packageUri": "lib/",
- "languageVersion": "2.3"
+ "languageVersion": "2.12"
},
{
"name": "devtools_shared",
@@ -354,12 +354,6 @@
"languageVersion": "2.12"
},
{
- "name": "http_retry",
- "rootUri": "../third_party/pkg/http_retry",
- "packageUri": "lib/",
- "languageVersion": "2.12"
- },
- {
"name": "http_throttle",
"rootUri": "../third_party/pkg/http_throttle",
"packageUri": "lib/",
@@ -731,13 +725,13 @@
"name": "testing",
"rootUri": "../pkg/testing",
"packageUri": "lib/",
- "languageVersion": "2.0"
+ "languageVersion": "2.12"
},
{
"name": "typed_data",
"rootUri": "../third_party/pkg/typed_data",
"packageUri": "lib/",
- "languageVersion": "2.10"
+ "languageVersion": "2.12"
},
{
"name": "usage",
@@ -755,7 +749,7 @@
"name": "vm",
"rootUri": "../pkg/vm",
"packageUri": "lib/",
- "languageVersion": "2.7"
+ "languageVersion": "2.12"
},
{
"name": "vm_service",
@@ -797,7 +791,7 @@
"name": "webkit_inspection_protocol",
"rootUri": "../third_party/pkg/webkit_inspection_protocol",
"packageUri": "lib/",
- "languageVersion": "2.0"
+ "languageVersion": "2.12"
},
{
"name": "yaml",
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ed07841..b1dcdb8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -159,8 +159,26 @@
#### Linter
-Updated the Linter to `1.7.0`, which includes changes that
+Updated the Linter to `1.8.0`, which includes changes that
+
+- improve performance for `prefer_is_not_empty`.
+- fix false positives in `no_logic_in_create_state`.
+- improve `package_names` to allow dart identifiers as package names.
+- fix a false-positive in `package_names` (causing keywords to wrongly get flagged).
+- fix `avoid_classes_with_only_static_member` to check for inherited members and also
+ flag classes with only methods.
+- fix `curly_braces_in_flow_control_structures` to properly flag terminating `else-if`
+ blocks.
+- improve `always_specify_types` to support type aliases.
+- fix a false positive in `unnecessary_string_interpolations` w/ nullable interpolated
+ strings
+- fix a false positive in `avoid_function_literals_in_foreach_calls` for nullable
+ iterables.
+- fix false positives in `avoid_returning_null` w/ NNBD
+- fix false positives in `use_late_for_private_fields_and_variables` in the presence
+ of const constructors.
+- adds a new lint: `eol_at_end_of_file`.
- fix case-sensitive false positive in `use_full_hex_values_for_flutter_colors`.
- improve try-block and switch statement flow analysis for
`use_build_context_synchronously`.
@@ -246,50 +264,15 @@
[#46545]: https://github.com/dart-lang/sdk/issues/46545
[1]: https://dart.dev/faq#q-what-browsers-do-you-support-as-javascript-compilation-targets
-### Language
+#### Dart Dev Compiler (DDC)
-* Add an unsigned shift right operator `>>>`. Pad with zeroes, ignoring the
- sign bit. On the web platform `int.>>>` shifts the low 32 bits interpreted
- as an unsigned integer, so `a >>> b` gives the same result as
- `a.toUnsigned(32) >>> b` on the VM.
+- **Breaking Change** [#44154][]: Subtyping relations of `package:js` classes
+ have been changed to be more correct and consistent with Dart2JS.
+ Like `anonymous` classes, non-`anonymous` classes will no longer check the
+ underlying type in DDC. The internal type representation of these objects have
+ changed as well, which will affect the `toString` value of these types.
-* Prior to Dart 2.14, metadata (annotations) were not permitted to be
- specified with generic type arguments. This restriction is lifted in Dart
- Dart 2.14.
-
- ```dart
- class C<T> {
- const C();
- }
- @C(); // Previously permitted.
- @C<int>(); // Previously an error, now permitted.
- ```
-
-* Prior to Dart 2.14, generic function types were not permitted as arguments
- to generic classes or functions, nor to be used as generic bounds. This
- restriction is lifted in Dart 2.14.
-
- ```dart
- T wrapWithLogging<T>(T f) {
- if (f is void Function<T>(T x)) {
- return <S>(S x) {
- print("Call: f<$S>($x)");
- var r = f<S>(x);
- print("Return: $x");
- return r;
- } as T;
- } // More cases here
- return f;
- }
- void foo<T>(T x) {
- print("Foo!");
- }
- void main() {
- // Previously an error, now permitted.
- var f = wrapWithLogging<void Function<T>(T)>(foo);
- f<int>(3);
- }
- ```
+[#44154]: https://github.com/dart-lang/sdk/issues/44154
## 2.13.4 - 2021-06-28
diff --git a/DEPS b/DEPS
index ac49b8f..613addf 100644
--- a/DEPS
+++ b/DEPS
@@ -39,7 +39,7 @@
# Checked-in SDK version. The checked-in SDK is a Dart SDK distribution in a
# cipd package used to run Dart scripts in the build and test infrastructure.
- "sdk_tag": "version:2.13.1",
+ "sdk_tag": "version:2.14.0-293.0.dev",
# co19 is a cipd package. Use update.sh in tests/co19[_2] to update these
# hashes. It requires access to the dart-build-access group, which EngProd
@@ -72,22 +72,22 @@
"gperftools_revision": "180bfa10d7cb38e8b3784d60943d50e8fcef0dcb",
# Revisions of /third_party/* dependencies.
- "args_rev": "d8fea36c10ef96797be02e3d132d572445cd86f4",
- "async_rev": "8193eac211905cf33ae1f514022fdbd843836be5",
+ "args_rev": "bf4c8796881b62fd5d3f6d86ab43014f9651eb20",
+ "async_rev": "25a7e2ec39c03622b86918cb9ce3e7d00dd283d1",
"bazel_worker_rev": "0885637b037979afbf5bcd05fd748b309fd669c0",
"benchmark_harness_rev": "c546dbd9f639f75cd2f75de8df2eb9f8ea15e8e7",
"boolean_selector_rev": "665e6921ab246569420376f827bff4585dff0b14",
"boringssl_gen_rev": "7322fc15cc065d8d2957fccce6b62a509dc4d641",
"boringssl_rev" : "1607f54fed72c6589d560254626909a64124f091",
"browser-compat-data_tag": "v1.0.22",
- "browser_launcher_rev": "12ab9f351a44ac803de9bc17bb2180bb312a9dd7",
+ "browser_launcher_rev": "c6cc1025d6901926cf022e144ba109677e3548f1",
"charcode_rev": "84ea427711e24abf3b832923959caa7dd9a8514b",
"chrome_rev" : "19997",
"cli_util_rev" : "8c504de5deb08fe32ecf51f9662bb37d8c708e57",
"clock_rev" : "a494269254ba978e7ef8f192c5f7fec3fc05b9d3",
"collection_rev": "75a7a5510979a3cd70143af85bcc1667ee233674",
- "convert_rev": "413f591577419d8a8b95d445094a82c926650bd1",
- "crypto_rev": "1c8ccc07b83b100216dc6dede767371043385648",
+ "convert_rev": "e063fdca4bebffecbb5e6aa5525995120982d9ce",
+ "crypto_rev": "b5024e4de2b1c474dd558bef593ddbf0bfade152",
"csslib_rev": "e411d862fd8cc50415c1badf2632e017373b3f47",
"dart2js_info_rev" : "e0acfeb5affdf94c53067e68bd836adf589628fd",
@@ -103,7 +103,7 @@
# and land the review.
#
# For more details, see https://github.com/dart-lang/sdk/issues/30164
- "dart_style_rev": "9d9dff90d9a2e0793ad2f795f36c2777f720eda0",
+ "dart_style_rev": "06bfd19593ed84dd288f67e02c6a753e6516288a",
"dartdoc_rev" : "c9621b92c738ec21a348cc2de032858276e9c774",
"devtools_rev" : "64cffbed6366329ad05e44d48fa2298367643bb6",
@@ -115,38 +115,37 @@
"html_rev": "00cd3c22dac0e68e6ed9e7e4945101aedb1b3109",
"http_io_rev": "2fa188caf7937e313026557713f7feffedd4978b",
"http_multi_server_rev": "de1b312164c24a1690b46c6e97bd47eff40c4649",
- "http_parser_rev": "7720bfd42a0c096734c5213478fdce92c62f0293",
- "http_retry_rev": "845771af7bb5ab38ab740ce4a31f3b0c7680302b",
- "http_rev": "f93c76fabdb03963303762e3fe16cbdf60799cff",
+ "http_parser_rev": "202391286ddc13c4c3c284ac5b511f04697250ed",
+ "http_rev": "778174bca2c13becd88ef3353309190b1e8b9479",
"http_throttle_tag" : "1.0.2",
"icu_rev" : "81d656878ec611cb0b42d52c82e9dae93920d9ba",
"idl_parser_rev": "5fb1ebf49d235b5a70c9f49047e83b0654031eb7",
"intl_tag": "0.17.0-nullsafety",
"jinja2_rev": "2222b31554f03e62600cd7e383376a7c187967a1",
"json_rpc_2_rev": "7e00f893440a72de0637970325e4ea44bd1e8c8e",
- "linter_tag": "422981ffb2fbd4010aa52381676cf745e2844dd9",
+ "linter_tag": "1.8.0",
"lints_tag": "f9670df2a66e0ec12eb51554e70c1cbf56c8f5d0",
- "logging_rev": "e2f633b543ef89c54688554b15ca3d7e425b86a2",
+ "logging_rev": "575781ef196e4fed4fb737e38fb4b73d62727187",
"markupsafe_rev": "8f45f5cfa0009d2a70589bcda0349b8cb2b72783",
"markdown_rev": "9c4beaac96d8f008078e00b027915f81b665d2de",
- "matcher_rev": "1f7b6f0cb15eb6659a1de0513571575a5c8a51d0",
+ "matcher_rev": "b411b22ec2437ba206c7a3006bbaeb519bd343d1",
"mime_rev": "c931f4bed87221beaece356494b43731445ce7b8",
"mockito_rev": "d39ac507483b9891165e422ec98d9fb480037c8b",
"oauth2_rev": "7cd3284049fe5badbec9f2bea2afc41d14c01057",
"package_config_rev": "a84c0d45401f215fbe9384df923a38f4022a3c45",
- "path_rev": "407ab76187fade41c31e39c745b39661b710106c",
+ "path_rev": "c20d73c3516d3a0061c90f14b761ff532b9bf707",
"pedantic_rev": "66f2f6c27581c7936482e83be80b27be2719901c",
"platform_rev": "c20e6fa315e9f8820e51c0ae721f63aff33b8e17",
"ply_rev": "604b32590ffad5cbb82e4afef1d305512d06ae93",
"pool_rev": "7abe634002a1ba8a0928eded086062f1307ccfae",
"process_rev": "56ece43b53b64c63ae51ec184b76bd5360c28d0b",
- "protobuf_rev": "0d03fd588df69e9863e2a2efc0059dee8f18d5b2",
- "pub_rev": "d159e5b9f04a7e4826b6afea7b3364d48aa0dad8",
+ "protobuf_rev": "c1eb6cb51af39ccbaa1a8e19349546586a5c8e31",
+ "pub_rev": "70b1a4f9229a36bac6340ec7eae2b2068baac96c",
"pub_semver_rev": "f50d80ef10c4b2fa5f4c8878036a4d9342c0cc82",
"resource_rev": "6b79867d0becf5395e5819a75720963b8298e9a7",
"root_certificates_rev": "692f6d6488af68e0121317a9c2c9eb393eb0ee50",
"rust_revision": "b7856f695d65a8ebc846754f97d15814bcb1c244",
- "shelf_static_rev": "fb6b7d0ee4ad936a84e503ae6b3703cc99e61d52",
+ "shelf_static_rev": "202ec1a53c9a830c17cf3b718d089cf7eba568ad",
"shelf_packages_handler_rev": "78302e67c035047e6348e692b0c1182131f0fe35",
"shelf_proxy_tag": "v1.0.0",
"shelf_rev": "46483f896cc4308ee3d8e997030ae799b72aa16a",
@@ -164,8 +163,8 @@
"test_process_tag": "2.0.0",
"term_glyph_rev": "6a0f9b6fb645ba75e7a00a4e20072678327a0347",
"test_reflective_loader_rev": "54e930a11c372683792e22bddad79197728c91ce",
- "test_rev": "030816c32b6fe78d5fb7653afbd9f63cca18bacf",
- "typed_data_tag": "f94fc57b8e8c0e4fe4ff6cfd8290b94af52d3719",
+ "test_rev": "099dcc4d052a30c6921489cfbefa1c8531d12975",
+ "typed_data_rev": "29ce5a92b03326d0b8035916ac04f528874994bd",
"usage_rev": "e0780cd8b2f8af69a28dc52678ffe8492da27d06",
"vector_math_rev": "0c9f5d68c047813a6dcdeb88ba7a42daddf25025",
"watcher_rev": "3924194385fb215cef483193ed2879a618a3d69c",
@@ -174,7 +173,7 @@
"web_socket_channel_rev": "6448ce532445a8a458fa191d9346df071ae0acad",
"WebCore_rev": "fb11e887f77919450e497344da570d780e078bc8",
"webdev_rev": "b0aae7b6944d484722e6af164abedd864a2a0afa",
- "webkit_inspection_protocol_rev": "6b15729292d030f2e5c5861022da4c5a4c11961c",
+ "webkit_inspection_protocol_rev": "dd6fb5d8b536e19cedb384d0bbf1f5631923f1e8",
"yaml_rev": "b4c4411631bda556ce9a45af1ab0eecaf9f3ac53",
"zlib_rev": "bf44340d1b6be1af8950bbdf664fec0cf5a831cc",
"crashpad_rev": "bf327d8ceb6a669607b0dbab5a83a275d03f99ed",
@@ -370,9 +369,6 @@
"@" + Var("http_multi_server_rev"),
Var("dart_root") + "/third_party/pkg/http_parser":
Var("dart_git") + "http_parser.git" + "@" + Var("http_parser_rev"),
- Var("dart_root") + "/third_party/pkg/http_retry":
- Var("dart_git") + "http_retry.git" +
- "@" + Var("http_retry_rev"),
Var("dart_root") + "/third_party/pkg/http_throttle":
Var("dart_git") + "http_throttle.git" +
"@" + Var("http_throttle_tag"),
@@ -460,7 +456,7 @@
Var("dart_git") + "test_reflective_loader.git" +
"@" + Var("test_reflective_loader_rev"),
Var("dart_root") + "/third_party/pkg/typed_data":
- Var("dart_git") + "typed_data.git" + "@" + Var("typed_data_tag"),
+ Var("dart_git") + "typed_data.git" + "@" + Var("typed_data_rev"),
Var("dart_root") + "/third_party/pkg/usage":
Var("dart_git") + "usage.git" + "@" + Var("usage_rev"),
Var("dart_root") + "/third_party/pkg/vector_math":
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index 7687b1d..ec4e5d2 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -109,14 +109,14 @@
utils = imp.load_source('utils',
os.path.join(local_root, 'tools', 'utils.py'))
- prebuilt_dartfmt = os.path.join(utils.CheckedInSdkPath(), 'bin', 'dartfmt')
+ dart = os.path.join(utils.CheckedInSdkPath(), 'bin', 'dart')
windows = utils.GuessOS() == 'win32'
if windows:
- prebuilt_dartfmt += '.bat'
+ dart += '.exe'
- if not os.path.isfile(prebuilt_dartfmt):
- print('WARNING: dartfmt not found: %s' % (prebuilt_dartfmt))
+ if not os.path.isfile(dart):
+ print('WARNING: dart not found: %s' % (dart))
return []
def HasFormatErrors(filename=None, contents=None):
@@ -129,13 +129,17 @@
if '//#' in contents:
return False
- args = [prebuilt_dartfmt, '--set-exit-if-changed']
- if not contents:
- args += [filename, '-n']
+ args = [
+ dart,
+ 'format',
+ '--set-exit-if-changed',
+ '--output=none',
+ '--summary=none',
+ filename,
+ ]
process = subprocess.Popen(
args, stdout=subprocess.PIPE, stdin=subprocess.PIPE)
- process.communicate(input=contents)
# Check for exit code 1 explicitly to distinguish it from a syntax error
# in the file (exit code 65). The repo contains many Dart files that are
@@ -143,7 +147,7 @@
# parsed and formatted. Don't treat those as errors.
return process.returncode == 1
- unformatted_files = _CheckFormat(input_api, "dartfmt", ".dart", windows,
+ unformatted_files = _CheckFormat(input_api, "dart format", ".dart", windows,
HasFormatErrors)
if unformatted_files:
diff --git a/benchmarks/SDKArtifactSizes/dart/SDKArtifactSizes.dart b/benchmarks/SDKArtifactSizes/dart/SDKArtifactSizes.dart
index 1130ac6..ece1bcc 100644
--- a/benchmarks/SDKArtifactSizes/dart/SDKArtifactSizes.dart
+++ b/benchmarks/SDKArtifactSizes/dart/SDKArtifactSizes.dart
@@ -34,8 +34,13 @@
];
Future<void> reportArtifactSize(String path, String name) async {
- final size = await File(path).length();
- print('SDKArtifactSizes.$name(CodeSize): $size');
+ try {
+ final size = await File(path).length();
+ print('SDKArtifactSizes.$name(CodeSize): $size');
+ } on FileSystemException {
+ // Report dummy data for artifacts that don't exist for specific platforms.
+ print('SDKArtifactSizes.$name(CodeSize): 0');
+ }
}
Future<void> main() async {
diff --git a/benchmarks/SDKArtifactSizes/dart2/SDKArtifactSizes.dart b/benchmarks/SDKArtifactSizes/dart2/SDKArtifactSizes.dart
index 1130ac6..ece1bcc 100644
--- a/benchmarks/SDKArtifactSizes/dart2/SDKArtifactSizes.dart
+++ b/benchmarks/SDKArtifactSizes/dart2/SDKArtifactSizes.dart
@@ -34,8 +34,13 @@
];
Future<void> reportArtifactSize(String path, String name) async {
- final size = await File(path).length();
- print('SDKArtifactSizes.$name(CodeSize): $size');
+ try {
+ final size = await File(path).length();
+ print('SDKArtifactSizes.$name(CodeSize): $size');
+ } on FileSystemException {
+ // Report dummy data for artifacts that don't exist for specific platforms.
+ print('SDKArtifactSizes.$name(CodeSize): 0');
+ }
}
Future<void> main() async {
diff --git a/benchmarks/SendPort/dart/SendPort.dart b/benchmarks/SendPort/dart/SendPort.dart
index a6e6044..fb950b5 100644
--- a/benchmarks/SendPort/dart/SendPort.dart
+++ b/benchmarks/SendPort/dart/SendPort.dart
@@ -175,8 +175,11 @@
}
class TreeNode {
+ @pragma('vm:entry-point') // Prevent tree shaking of this field.
final TreeNode? left;
+ @pragma('vm:entry-point') // Prevent tree shaking of this field.
final TreeNode? right;
+ @pragma('vm:entry-point') // Prevent tree shaking of this field.
final int value;
TreeNode(this.left, this.right, this.value);
diff --git a/benchmarks/SendPort/dart2/SendPort.dart b/benchmarks/SendPort/dart2/SendPort.dart
index 01d4042..a97acf3 100644
--- a/benchmarks/SendPort/dart2/SendPort.dart
+++ b/benchmarks/SendPort/dart2/SendPort.dart
@@ -177,8 +177,11 @@
}
class TreeNode {
+ @pragma('vm:entry-point') // Prevent tree shaking of this field.
final TreeNode left;
+ @pragma('vm:entry-point') // Prevent tree shaking of this field.
final TreeNode right;
+ @pragma('vm:entry-point') // Prevent tree shaking of this field.
final int value;
TreeNode(this.left, this.right, this.value);
diff --git a/build/dart/dart_action.gni b/build/dart/dart_action.gni
index c357aad..334a09a 100644
--- a/build/dart/dart_action.gni
+++ b/build/dart/dart_action.gni
@@ -51,6 +51,10 @@
testonly = invoker.testonly
}
+ if (defined(invoker.pool)) {
+ pool = invoker.pool
+ }
+
script = "$_dart_root/build/gn_run_binary.py"
if (defined(invoker.inputs)) {
@@ -109,6 +113,7 @@
"depfile",
"deps",
"outputs",
+ "pool",
"testonly",
"visibility",
])
@@ -256,6 +261,7 @@
"deps",
"inputs",
"outputs",
+ "pool",
"tool",
"testonly",
"visibility",
@@ -321,6 +327,7 @@
"inputs",
"outputs",
"packages",
+ "pool",
"script",
"testonly",
"tool",
@@ -380,6 +387,7 @@
"inputs",
"outputs",
"packages",
+ "pool",
"testonly",
"tool",
"visibility",
diff --git a/build/fuchsia/dart.cmx b/build/fuchsia/dart.cmx
index d57d9ac..0bd0e668 100644
--- a/build/fuchsia/dart.cmx
+++ b/build/fuchsia/dart.cmx
@@ -1,27 +1,28 @@
{
- "program": {
- "binary": "exe.stripped/dart"
- },
- "sandbox": {
- "features": [
- "config-data",
- "deprecated-ambient-replace-as-executable",
- "root-ssl-certificates",
- "isolated-cache-storage",
- "isolated-persistent-storage",
- "isolated-temp"
- ],
- "services": [
- "fuchsia.deprecatedtimezone.Timezone",
- "fuchsia.device.NameProvider",
- "fuchsia.feedback.CrashReporter",
- "fuchsia.intl.PropertyProvider",
- "fuchsia.logger.LogSink",
- "fuchsia.net.NameLookup",
- "fuchsia.posix.socket.Provider",
- "fuchsia.sysmem.Allocator",
- "fuchsia.timezone.Timezone",
- "fuchsia.tracing.provider.Registry"
- ]
- }
+ "program": {
+ "binary": "exe.stripped/dart"
+ },
+ "sandbox": {
+ "features": [
+ "config-data",
+ "deprecated-ambient-replace-as-executable",
+ "isolated-cache-storage",
+ "isolated-persistent-storage",
+ "isolated-temp",
+ "root-ssl-certificates"
+ ],
+ "services": [
+ "fuchsia.deprecatedtimezone.Timezone",
+ "fuchsia.device.NameProvider",
+ "fuchsia.feedback.CrashReporter",
+ "fuchsia.intl.PropertyProvider",
+ "fuchsia.logger.LogSink",
+ "fuchsia.net.NameLookup",
+ "fuchsia.net.name.Lookup",
+ "fuchsia.posix.socket.Provider",
+ "fuchsia.sysmem.Allocator",
+ "fuchsia.timezone.Timezone",
+ "fuchsia.tracing.provider.Registry"
+ ]
+ }
}
diff --git a/pkg/_fe_analyzer_shared/lib/src/messages/codes.dart b/pkg/_fe_analyzer_shared/lib/src/messages/codes.dart
index 7299a94..ca0f816 100644
--- a/pkg/_fe_analyzer_shared/lib/src/messages/codes.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/messages/codes.dart
@@ -279,7 +279,7 @@
this.severity, this.uri, this.involvedFiles, this.codeName);
factory DiagnosticMessageFromJson.fromJson(String jsonString) {
- Map<String, Object> decoded = json.decode(jsonString);
+ Map<String, Object?> decoded = json.decode(jsonString);
List<String> ansiFormatted =
new List<String>.from(_asListOfString(decoded["ansiFormatted"]));
List<String> plainTextFormatted =
diff --git a/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart b/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
index 289ec96..01dd119 100644
--- a/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
@@ -1328,6 +1328,25 @@
r"""Extension operations can't be used in constant expressions.""");
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeConstEvalExternalConstructor =
+ messageConstEvalExternalConstructor;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageConstEvalExternalConstructor = const MessageCode(
+ "ConstEvalExternalConstructor",
+ message:
+ r"""External constructors can't be evaluated in constant expressions.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeConstEvalExternalFactory = messageConstEvalExternalFactory;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageConstEvalExternalFactory = const MessageCode(
+ "ConstEvalExternalFactory",
+ message:
+ r"""External factory constructors can't be evaluated in constant expressions.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Null> codeConstEvalFailedAssertion = messageConstEvalFailedAssertion;
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3992,6 +4011,16 @@
message: r"""FFI leaf call must not have Handle argument types.""");
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeFfiNativeAnnotationMustAnnotateStatic =
+ messageFfiNativeAnnotationMustAnnotateStatic;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageFfiNativeAnnotationMustAnnotateStatic =
+ const MessageCode("FfiNativeAnnotationMustAnnotateStatic",
+ message:
+ r"""FfiNative annotations can only be used on static functions.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<
Message Function(String name)> templateFfiNotStatic = const Template<
Message Function(String name)>(
@@ -6208,6 +6237,18 @@
message: r"""This is the enclosing class.""");
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeJsInteropExternalExtensionMemberOnTypeInvalid =
+ messageJsInteropExternalExtensionMemberOnTypeInvalid;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageJsInteropExternalExtensionMemberOnTypeInvalid =
+ const MessageCode("JsInteropExternalExtensionMemberOnTypeInvalid",
+ message:
+ r"""JS interop or Native class required for 'external' extension members.""",
+ tip:
+ r"""Try adding a JS interop annotation to the on type class of the extension.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Null> codeJsInteropExternalMemberNotJSAnnotated =
messageJsInteropExternalMemberNotJSAnnotated;
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart b/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
index 0688ab2..71472cc 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
@@ -5160,7 +5160,10 @@
// For example a(b)..<T>(c), where token is '<'.
token = typeArg.parseArguments(token, this);
next = token.next!;
- assert(optional('(', next));
+ if (!optional('(', next)) {
+ listener.handleTypeArgumentApplication(token.next!);
+ typeArg = noTypeParamOrArg;
+ }
}
TokenType nextType = next.type;
if (identical(nextType, TokenType.INDEX)) {
@@ -5307,7 +5310,10 @@
listener.handleNonNullAssertExpression(bangToken);
}
token = typeArg.parseArguments(bangToken, this);
- assert(optional('(', token.next!));
+ if (!optional('(', token.next!)) {
+ listener.handleTypeArgumentApplication(bangToken.next!);
+ typeArg = noTypeParamOrArg;
+ }
}
next = token.next!;
} else if (optional('(', next)) {
@@ -5327,7 +5333,10 @@
listener.handleNonNullAssertExpression(bangToken);
}
token = typeArg.parseArguments(bangToken, this);
- assert(optional('(', token.next!));
+ if (!optional('(', token.next!)) {
+ listener.handleTypeArgumentApplication(bangToken.next!);
+ typeArg = noTypeParamOrArg;
+ }
}
next = token.next!;
} else {
diff --git a/pkg/_js_interop_checks/lib/js_interop_checks.dart b/pkg/_js_interop_checks/lib/js_interop_checks.dart
index 4f3ba97..975fca7 100644
--- a/pkg/_js_interop_checks/lib/js_interop_checks.dart
+++ b/pkg/_js_interop_checks/lib/js_interop_checks.dart
@@ -12,6 +12,7 @@
messageJsInteropAnonymousFactoryPositionalParameters,
messageJsInteropEnclosingClassJSAnnotation,
messageJsInteropEnclosingClassJSAnnotationContext,
+ messageJsInteropExternalExtensionMemberOnTypeInvalid,
messageJsInteropExternalMemberNotJSAnnotated,
messageJsInteropIndexNotSupported,
messageJsInteropNamedParameters,
@@ -30,6 +31,7 @@
bool _classHasJSAnnotation = false;
bool _classHasAnonymousAnnotation = false;
bool _libraryHasJSAnnotation = false;
+ Map<Reference, Extension>? _libraryExtensionsIndex;
/// Libraries that use `external` to exclude from checks on external.
static final Iterable<String> _pathsWithAllowedDartExternalUsage = <String>[
@@ -86,7 +88,8 @@
@override
void defaultMember(Member member) {
- _checkJSInteropAnnotation(member);
+ _checkInstanceMemberJSAnnotation(member);
+ if (!_isJSInteropMember(member)) _checkDisallowedExternal(member);
// TODO(43530): Disallow having JS interop annotations on non-external
// members (class members or otherwise). Currently, they're being ignored.
super.defaultMember(member);
@@ -105,14 +108,14 @@
cls.name, superclass.name),
cls.fileOffset,
cls.name.length,
- cls.location.file);
+ cls.fileUri);
} else if (!_classHasJSAnnotation && superHasJSAnnotation) {
_diagnosticsReporter.report(
templateJsInteropDartClassExtendsJSClass.withArguments(
cls.name, superclass.name),
cls.fileOffset,
cls.name.length,
- cls.location.file);
+ cls.fileUri);
}
}
// Since this is a breaking check, it is language-versioned.
@@ -129,10 +132,10 @@
// a value for `className` that doesn't start with 'self.' or 'window.'.
var classRegexp = new RegExp(r'^((self|window)\.)*(?<className>.*)$');
var matches = classRegexp.allMatches(jsClass);
- jsClass = matches.first.namedGroup('className');
+ jsClass = matches.first.namedGroup('className')!;
}
- if (_nativeClasses.containsKey(jsClass)) {
- var nativeClass = _nativeClasses[jsClass];
+ var nativeClass = _nativeClasses[jsClass];
+ if (nativeClass != null) {
_diagnosticsReporter.report(
templateJsInteropNativeClassInAnnotation.withArguments(
cls.name,
@@ -140,7 +143,7 @@
nativeClass.enclosingLibrary.importUri.toString()),
cls.fileOffset,
cls.name.length,
- cls.location.file);
+ cls.fileUri);
}
}
super.visitClass(cls);
@@ -165,11 +168,12 @@
super.visitLibrary(lib);
_libraryIsGlobalNamespace = false;
_libraryHasJSAnnotation = false;
+ _libraryExtensionsIndex = null;
}
@override
void visitProcedure(Procedure procedure) {
- _checkJSInteropAnnotation(procedure);
+ _checkInstanceMemberJSAnnotation(procedure);
if (_classHasJSAnnotation && !procedure.isExternal) {
// If not one of few exceptions, member is not allowed to exclude
// `external` inside of a JS interop class.
@@ -180,43 +184,48 @@
messageJsInteropNonExternalMember,
procedure.fileOffset,
procedure.name.text.length,
- procedure.location.file);
+ procedure.fileUri);
}
}
- if (!_isJSInteropMember(procedure)) return;
- if (!procedure.isStatic &&
- (procedure.name.text == '[]=' || procedure.name.text == '[]')) {
- _diagnosticsReporter.report(
- messageJsInteropIndexNotSupported,
- procedure.fileOffset,
- procedure.name.text.length,
- procedure.location.file);
- }
-
- var isAnonymousFactory =
- _classHasAnonymousAnnotation && procedure.isFactory;
-
- if (isAnonymousFactory) {
- if (procedure.function != null &&
- !procedure.function.positionalParameters.isEmpty) {
- var firstPositionalParam = procedure.function.positionalParameters[0];
- _diagnosticsReporter.report(
- messageJsInteropAnonymousFactoryPositionalParameters,
- firstPositionalParam.fileOffset,
- firstPositionalParam.name.length,
- firstPositionalParam.location.file);
- }
+ if (!_isJSInteropMember(procedure)) {
+ _checkDisallowedExternal(procedure);
} else {
- // Only factory constructors for anonymous classes are allowed to have
- // named parameters.
- _checkNoNamedParameters(procedure.function);
+ // Check JS interop indexing.
+ if (!procedure.isStatic &&
+ (procedure.name.text == '[]=' || procedure.name.text == '[]')) {
+ _diagnosticsReporter.report(
+ messageJsInteropIndexNotSupported,
+ procedure.fileOffset,
+ procedure.name.text.length,
+ procedure.fileUri);
+ }
+
+ // Check JS Interop positional and named parameters.
+ var isAnonymousFactory =
+ _classHasAnonymousAnnotation && procedure.isFactory;
+ if (isAnonymousFactory) {
+ // ignore: unnecessary_null_comparison
+ if (procedure.function != null &&
+ !procedure.function.positionalParameters.isEmpty) {
+ var firstPositionalParam = procedure.function.positionalParameters[0];
+ _diagnosticsReporter.report(
+ messageJsInteropAnonymousFactoryPositionalParameters,
+ firstPositionalParam.fileOffset,
+ firstPositionalParam.name!.length,
+ firstPositionalParam.location!.file);
+ }
+ } else {
+ // Only factory constructors for anonymous classes are allowed to have
+ // named parameters.
+ _checkNoNamedParameters(procedure.function);
+ }
}
}
@override
void visitConstructor(Constructor constructor) {
- _checkJSInteropAnnotation(constructor);
+ _checkInstanceMemberJSAnnotation(constructor);
if (_classHasJSAnnotation &&
!constructor.isExternal &&
!constructor.isSynthetic) {
@@ -225,28 +234,32 @@
messageJsInteropNonExternalConstructor,
constructor.fileOffset,
constructor.name.text.length,
- constructor.location.file);
+ constructor.fileUri);
}
- if (!_isJSInteropMember(constructor)) return;
- _checkNoNamedParameters(constructor.function);
+ if (!_isJSInteropMember(constructor)) {
+ _checkDisallowedExternal(constructor);
+ } else {
+ _checkNoNamedParameters(constructor.function);
+ }
}
/// Reports an error if [functionNode] has named parameters.
void _checkNoNamedParameters(FunctionNode functionNode) {
+ // ignore: unnecessary_null_comparison
if (functionNode != null && !functionNode.namedParameters.isEmpty) {
var firstNamedParam = functionNode.namedParameters[0];
_diagnosticsReporter.report(
messageJsInteropNamedParameters,
firstNamedParam.fileOffset,
- firstNamedParam.name.length,
- firstNamedParam.location.file);
+ firstNamedParam.name!.length,
+ firstNamedParam.location!.file);
}
}
- /// Reports an error if [member] does not correctly use the JS interop
- /// annotation or the keyword `external`.
- void _checkJSInteropAnnotation(Member member) {
+ /// Reports an error if given instance [member] is JS interop, but inside a
+ /// non JS interop class.
+ void _checkInstanceMemberJSAnnotation(Member member) {
var enclosingClass = member.enclosingClass;
if (!_classHasJSAnnotation &&
@@ -255,26 +268,38 @@
// If in a class that is not JS interop, this member is not allowed to be
// JS interop.
_diagnosticsReporter.report(messageJsInteropEnclosingClassJSAnnotation,
- member.fileOffset, member.name.text.length, member.location.file,
+ member.fileOffset, member.name.text.length, member.fileUri,
context: <LocatedMessage>[
messageJsInteropEnclosingClassJSAnnotationContext.withLocation(
- enclosingClass.location.file,
+ enclosingClass.fileUri,
enclosingClass.fileOffset,
enclosingClass.name.length)
]);
}
+ }
- // Check for correct `external` usage.
- if (member.isExternal &&
- !_isAllowedExternalUsage(member) &&
- !hasJSInteropAnnotation(member)) {
- if (member.enclosingClass != null && !_classHasJSAnnotation ||
- member.enclosingClass == null && !_libraryHasJSAnnotation) {
+ /// Assumes given [member] is not JS interop, and reports an error if
+ /// [member] is `external` and not an allowed `external` usage.
+ void _checkDisallowedExternal(Member member) {
+ if (member.isExternal) {
+ if (member.isExtensionMember) {
+ if (!_isNativeExtensionMember(member)) {
+ _diagnosticsReporter.report(
+ messageJsInteropExternalExtensionMemberOnTypeInvalid,
+ member.fileOffset,
+ member.name.text.length,
+ member.fileUri);
+ }
+ } else if (!hasJSInteropAnnotation(member) &&
+ !_isAllowedExternalUsage(member)) {
+ // Member could be JS annotated and not considered a JS interop member
+ // if inside a non-JS interop class. Should not report an error in this
+ // case, since a different error will already be produced.
_diagnosticsReporter.report(
messageJsInteropExternalMemberNotJSAnnotated,
member.fileOffset,
member.name.text.length,
- member.location.file);
+ member.fileUri);
}
}
}
@@ -290,13 +315,19 @@
}
/// Returns whether [member] is considered to be a JS interop member.
+ ///
+ /// A JS interop member is `external`, and is in a valid JS interop context,
+ /// which can be:
+ /// - inside a JS interop class
+ /// - inside an extension on a JS interop class
+ /// - a top level member that is JS interop annotated or in a JS interop
+ /// library
+ /// If a member belongs to a class, the class must be JS interop annotated.
bool _isJSInteropMember(Member member) {
if (member.isExternal) {
if (_classHasJSAnnotation) return true;
+ if (member.isExtensionMember) return _isJSExtensionMember(member);
if (member.enclosingClass == null) {
- // In the case where the member does not belong to any class, a JS
- // annotation is not needed on the library to be considered JS interop
- // as long as the member has an annotation.
return hasJSInteropAnnotation(member) || _libraryHasJSAnnotation;
}
}
@@ -304,4 +335,31 @@
// Otherwise, not JS interop.
return false;
}
+
+ /// Returns whether given extension [member] is in an extension that is on a
+ /// JS interop class.
+ bool _isJSExtensionMember(Member member) {
+ return _checkExtensionMember(member, hasJSInteropAnnotation);
+ }
+
+ /// Returns whether given extension [member] is in an extension on a Native
+ /// class.
+ bool _isNativeExtensionMember(Member member) {
+ return _checkExtensionMember(member, _nativeClasses.containsValue);
+ }
+
+ /// Returns whether given extension [member] is on a class that passses the
+ /// given [validateExtensionClass].
+ bool _checkExtensionMember(Member member, Function validateExtensionClass) {
+ assert(member.isExtensionMember);
+ if (_libraryExtensionsIndex == null) {
+ _libraryExtensionsIndex = {};
+ member.enclosingLibrary.extensions.forEach((extension) =>
+ extension.members.forEach((memberDescriptor) =>
+ _libraryExtensionsIndex![memberDescriptor.member] = extension));
+ }
+
+ var onType = _libraryExtensionsIndex![member.reference]!.onType;
+ return onType is InterfaceType && validateExtensionClass(onType.classNode);
+ }
}
diff --git a/pkg/_js_interop_checks/lib/src/js_interop.dart b/pkg/_js_interop_checks/lib/src/js_interop.dart
index 7831f2d..60a8dfd 100644
--- a/pkg/_js_interop_checks/lib/src/js_interop.dart
+++ b/pkg/_js_interop_checks/lib/src/js_interop.dart
@@ -89,7 +89,7 @@
///
/// This function works regardless of whether the CFE is evaluating constants,
/// or whether the constant is a field reference (such as "anonymous" above).
-Class _annotationClass(Expression node) {
+Class? _annotationClass(Expression node) {
if (node is ConstantExpression) {
var constant = node.constant;
if (constant is InstanceConstant) return constant.classNode;
diff --git a/pkg/_js_interop_checks/lib/src/transformations/js_util_optimizer.dart b/pkg/_js_interop_checks/lib/src/transformations/js_util_optimizer.dart
index b29d418..4159999 100644
--- a/pkg/_js_interop_checks/lib/src/transformations/js_util_optimizer.dart
+++ b/pkg/_js_interop_checks/lib/src/transformations/js_util_optimizer.dart
@@ -36,26 +36,26 @@
JsUtilOptimizer(this._coreTypes, ClassHierarchy hierarchy)
: _jsTarget =
- _coreTypes.index.getTopLevelMember('dart:_foreign_helper', 'JS'),
+ _coreTypes.index.getTopLevelProcedure('dart:_foreign_helper', 'JS'),
_callMethodTarget =
- _coreTypes.index.getTopLevelMember('dart:js_util', 'callMethod'),
+ _coreTypes.index.getTopLevelProcedure('dart:js_util', 'callMethod'),
_callMethodUncheckedTargets = List<Procedure>.generate(
5,
- (i) => _coreTypes.index
- .getTopLevelMember('dart:js_util', '_callMethodUnchecked$i')),
- _getPropertyTarget =
- _coreTypes.index.getTopLevelMember('dart:js_util', 'getProperty'),
- _setPropertyTarget =
- _coreTypes.index.getTopLevelMember('dart:js_util', 'setProperty'),
+ (i) => _coreTypes.index.getTopLevelProcedure(
+ 'dart:js_util', '_callMethodUnchecked$i')),
+ _getPropertyTarget = _coreTypes.index
+ .getTopLevelProcedure('dart:js_util', 'getProperty'),
+ _setPropertyTarget = _coreTypes.index
+ .getTopLevelProcedure('dart:js_util', 'setProperty'),
_setPropertyUncheckedTarget = _coreTypes.index
- .getTopLevelMember('dart:js_util', '_setPropertyUnchecked'),
+ .getTopLevelProcedure('dart:js_util', '_setPropertyUnchecked'),
_allowInteropTarget =
- _coreTypes.index.getTopLevelMember('dart:js', 'allowInterop'),
+ _coreTypes.index.getTopLevelProcedure('dart:js', 'allowInterop'),
_allowedInteropJsUtilTargets = _allowedInteropJsUtilMembers.map(
(member) =>
- _coreTypes.index.getTopLevelMember('dart:js_util', member)),
+ _coreTypes.index.getTopLevelProcedure('dart:js_util', member)),
_listEmptyFactory =
- _coreTypes.index.getMember('dart:core', 'List', 'empty'),
+ _coreTypes.index.getProcedure('dart:core', 'List', 'empty'),
_staticTypeContext = StatefulStaticTypeContext.stacked(
TypeEnvironment(_coreTypes, hierarchy)) {}
diff --git a/pkg/_js_interop_checks/pubspec.yaml b/pkg/_js_interop_checks/pubspec.yaml
index 1463e1d..bae1992 100644
--- a/pkg/_js_interop_checks/pubspec.yaml
+++ b/pkg/_js_interop_checks/pubspec.yaml
@@ -3,7 +3,7 @@
publish_to: none
environment:
- sdk: '>=2.7.0 <3.0.0'
+ sdk: '>=2.12.0 <3.0.0'
dependencies:
_fe_analyzer_shared:
diff --git a/pkg/analysis_server/doc/api.html b/pkg/analysis_server/doc/api.html
index f63580d..2e13ba2 100644
--- a/pkg/analysis_server/doc/api.html
+++ b/pkg/analysis_server/doc/api.html
@@ -4770,13 +4770,13 @@
The one-based index of the column containing the first character of
the range.
</p>
- </dd><dt class="field"><b>endLine: int</b></dt><dd>
+ </dd><dt class="field"><b>endLine: int<span style="color:#999999"> (optional)</span></b></dt><dd>
<p>
The one-based index of the line containing the character immediately
following the range.
</p>
- </dd><dt class="field"><b>endColumn: int</b></dt><dd>
+ </dd><dt class="field"><b>endColumn: int<span style="color:#999999"> (optional)</span></b></dt><dd>
<p>
The one-based index of the column containing the character immediately
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index db83350..3896905 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -40,6 +40,7 @@
import 'package:analysis_server/src/server/features.dart';
import 'package:analysis_server/src/server/sdk_configuration.dart';
import 'package:analysis_server/src/services/flutter/widget_descriptions.dart';
+import 'package:analysis_server/src/utilities/process.dart';
import 'package:analysis_server/src/utilities/request_statistics.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/ast/ast.dart';
@@ -130,6 +131,7 @@
CrashReportingAttachmentsBuilder crashReportingAttachmentsBuilder,
InstrumentationService instrumentationService, {
http.Client? httpClient,
+ ProcessRunner? processRunner,
RequestStatisticsHelper? requestStatistics,
DiagnosticServer? diagnosticServer,
this.detachableFileSystemManager,
@@ -143,6 +145,7 @@
baseResourceProvider,
instrumentationService,
httpClient,
+ processRunner,
NotificationManager(channel, baseResourceProvider.pathContext),
requestStatistics: requestStatistics,
enableBazelWatcher: enableBazelWatcher,
@@ -429,9 +432,11 @@
bool isPubspec(String filePath) =>
file_paths.isPubspecYaml(resourceProvider.pathContext, filePath);
- // When a pubspec is opened, trigger package name caching for completion.
- if (!pubPackageService.isRunning && files.any(isPubspec)) {
- pubPackageService.beginPackageNamePreload();
+ // When pubspecs are opened, trigger pre-loading of pub package names and
+ // versions.
+ final pubspecs = files.where(isPubspec).toList();
+ if (pubspecs.isNotEmpty) {
+ pubPackageService.beginCachePreloads(pubspecs);
}
priorityFiles.clear();
@@ -679,83 +684,8 @@
@override
void listenAnalysisDriver(analysis.AnalysisDriver analysisDriver) {
analysisDriver.results.listen((result) {
- var path = result.path!;
- filesToFlush.add(path);
- if (analysisServer.isAnalyzed(path)) {
- _notificationManager.recordAnalysisErrors(NotificationManager.serverId,
- path, server.doAnalysisError_listFromEngine(result));
- }
- analysisServer.getDocumentationCacheFor(result)?.cacheFromResult(result);
- analysisServer.getExtensionCacheFor(result)?.cacheFromResult(result);
- var unit = result.unit;
- if (unit != null) {
- if (analysisServer._hasAnalysisServiceSubscription(
- AnalysisService.HIGHLIGHTS, path)) {
- _runDelayed(() {
- _notificationManager.recordHighlightRegions(
- NotificationManager.serverId,
- path,
- _computeHighlightRegions(unit));
- });
- }
- if (analysisServer._hasAnalysisServiceSubscription(
- AnalysisService.NAVIGATION, path)) {
- _runDelayed(() {
- _notificationManager.recordNavigationParams(
- NotificationManager.serverId,
- path,
- _computeNavigationParams(path, unit));
- });
- }
- if (analysisServer._hasAnalysisServiceSubscription(
- AnalysisService.OCCURRENCES, path)) {
- _runDelayed(() {
- _notificationManager.recordOccurrences(
- NotificationManager.serverId, path, _computeOccurrences(unit));
- });
- }
-// if (analysisServer._hasAnalysisServiceSubscription(
-// AnalysisService.OUTLINE, path)) {
-// _runDelayed(() {
-// // TODO(brianwilkerson) Change NotificationManager to store params
-// // so that fileKind and libraryName can be recorded / passed along.
-// notificationManager.recordOutlines(NotificationManager.serverId,
-// path, _computeOutlineParams(path, unit, result.lineInfo));
-// });
-// }
- if (analysisServer._hasAnalysisServiceSubscription(
- AnalysisService.CLOSING_LABELS, path)) {
- _runDelayed(() {
- sendAnalysisNotificationClosingLabels(
- analysisServer, path, result.lineInfo, unit);
- });
- }
- if (analysisServer._hasAnalysisServiceSubscription(
- AnalysisService.FOLDING, path)) {
- _runDelayed(() {
- sendAnalysisNotificationFolding(
- analysisServer, path, result.lineInfo, unit);
- });
- }
- if (analysisServer._hasAnalysisServiceSubscription(
- AnalysisService.OUTLINE, path)) {
- _runDelayed(() {
- sendAnalysisNotificationOutline(analysisServer, result);
- });
- }
- if (analysisServer._hasAnalysisServiceSubscription(
- AnalysisService.OVERRIDES, path)) {
- _runDelayed(() {
- sendAnalysisNotificationOverrides(analysisServer, path, unit);
- });
- }
- if (analysisServer._hasFlutterServiceSubscription(
- FlutterService.OUTLINE, path)) {
- _runDelayed(() {
- sendFlutterNotificationOutline(analysisServer, result);
- });
- }
- // TODO(scheglov) Implement notifications for AnalysisService.IMPLEMENTED.
+ if (result is FileResult) {
+ _handleFileResult(result);
}
});
analysisDriver.exceptions.listen(analysisServer.logExceptionResult);
@@ -763,6 +693,18 @@
}
@override
+ void pubspecChanged(String pubspecPath) {
+ analysisServer.pubPackageService.fetchPackageVersionsViaPubOutdated(
+ pubspecPath,
+ pubspecWasModified: true);
+ }
+
+ @override
+ void pubspecRemoved(String pubspecPath) {
+ analysisServer.pubPackageService.flushPackageCaches(pubspecPath);
+ }
+
+ @override
void recordAnalysisErrors(String path, List<AnalysisError> errors) {
filesToFlush.add(path);
_notificationManager.recordAnalysisErrors(
@@ -788,6 +730,95 @@
return collector.allOccurrences;
}
+ void _handleFileResult(FileResult result) {
+ var path = result.path;
+ filesToFlush.add(path);
+
+ if (result is AnalysisResultWithErrors) {
+ if (analysisServer.isAnalyzed(path)) {
+ _notificationManager.recordAnalysisErrors(NotificationManager.serverId,
+ path, server.doAnalysisError_listFromEngine(result));
+ }
+ }
+
+ if (result is ResolvedUnitResult) {
+ _handleResolvedUnitResult(result);
+ }
+ }
+
+ void _handleResolvedUnitResult(ResolvedUnitResult result) {
+ var path = result.path;
+
+ analysisServer.getDocumentationCacheFor(result)?.cacheFromResult(result);
+ analysisServer.getExtensionCacheFor(result)?.cacheFromResult(result);
+
+ var unit = result.unit;
+ if (analysisServer._hasAnalysisServiceSubscription(
+ AnalysisService.HIGHLIGHTS, path)) {
+ _runDelayed(() {
+ _notificationManager.recordHighlightRegions(
+ NotificationManager.serverId, path, _computeHighlightRegions(unit));
+ });
+ }
+ if (analysisServer._hasAnalysisServiceSubscription(
+ AnalysisService.NAVIGATION, path)) {
+ _runDelayed(() {
+ _notificationManager.recordNavigationParams(
+ NotificationManager.serverId,
+ path,
+ _computeNavigationParams(path, unit));
+ });
+ }
+ if (analysisServer._hasAnalysisServiceSubscription(
+ AnalysisService.OCCURRENCES, path)) {
+ _runDelayed(() {
+ _notificationManager.recordOccurrences(
+ NotificationManager.serverId, path, _computeOccurrences(unit));
+ });
+ }
+ // if (analysisServer._hasAnalysisServiceSubscription(
+ // AnalysisService.OUTLINE, path)) {
+ // _runDelayed(() {
+ // // TODO(brianwilkerson) Change NotificationManager to store params
+ // // so that fileKind and libraryName can be recorded / passed along.
+ // notificationManager.recordOutlines(NotificationManager.serverId, path,
+ // _computeOutlineParams(path, unit, result.lineInfo));
+ // });
+ // }
+ if (analysisServer._hasAnalysisServiceSubscription(
+ AnalysisService.CLOSING_LABELS, path)) {
+ _runDelayed(() {
+ sendAnalysisNotificationClosingLabels(
+ analysisServer, path, result.lineInfo, unit);
+ });
+ }
+ if (analysisServer._hasAnalysisServiceSubscription(
+ AnalysisService.FOLDING, path)) {
+ _runDelayed(() {
+ sendAnalysisNotificationFolding(
+ analysisServer, path, result.lineInfo, unit);
+ });
+ }
+ if (analysisServer._hasAnalysisServiceSubscription(
+ AnalysisService.OUTLINE, path)) {
+ _runDelayed(() {
+ sendAnalysisNotificationOutline(analysisServer, result);
+ });
+ }
+ if (analysisServer._hasAnalysisServiceSubscription(
+ AnalysisService.OVERRIDES, path)) {
+ _runDelayed(() {
+ sendAnalysisNotificationOverrides(analysisServer, path, unit);
+ });
+ }
+ if (analysisServer._hasFlutterServiceSubscription(
+ FlutterService.OUTLINE, path)) {
+ _runDelayed(() {
+ sendFlutterNotificationOutline(analysisServer, result);
+ });
+ }
+ }
+
/// Run [f] in a new [Future].
///
/// This method is used to delay sending notifications. If there is a more
diff --git a/pkg/analysis_server/lib/src/analysis_server_abstract.dart b/pkg/analysis_server/lib/src/analysis_server_abstract.dart
index 616bf9d..4b28f5c 100644
--- a/pkg/analysis_server/lib/src/analysis_server_abstract.dart
+++ b/pkg/analysis_server/lib/src/analysis_server_abstract.dart
@@ -19,12 +19,14 @@
import 'package:analysis_server/src/services/completion/dart/extension_cache.dart';
import 'package:analysis_server/src/services/correction/namespace.dart';
import 'package:analysis_server/src/services/pub/pub_api.dart';
+import 'package:analysis_server/src/services/pub/pub_command.dart';
import 'package:analysis_server/src/services/pub/pub_package_service.dart';
import 'package:analysis_server/src/services/search/element_visitors.dart';
import 'package:analysis_server/src/services/search/search_engine.dart';
import 'package:analysis_server/src/services/search/search_engine_internal.dart';
import 'package:analysis_server/src/utilities/file_string_sink.dart';
import 'package:analysis_server/src/utilities/null_string_sink.dart';
+import 'package:analysis_server/src/utilities/process.dart';
import 'package:analysis_server/src/utilities/request_statistics.dart';
import 'package:analysis_server/src/utilities/tee_string_sink.dart';
import 'package:analyzer/dart/analysis/analysis_context.dart';
@@ -152,14 +154,26 @@
ResourceProvider baseResourceProvider,
this.instrumentationService,
http.Client? httpClient,
+ ProcessRunner? processRunner,
this.notificationManager, {
this.requestStatistics,
bool enableBazelWatcher = false,
}) : resourceProvider = OverlayResourceProvider(baseResourceProvider),
pubApi = PubApi(instrumentationService, httpClient,
Platform.environment['PUB_HOSTED_URL']) {
- pubPackageService =
- PubPackageService(instrumentationService, baseResourceProvider, pubApi);
+ // We can only spawn processes (eg. to run pub commands) when backed by
+ // a real file system, otherwise we may try to run commands in folders that
+ // don't really exist. If processRunner was supplied, it's likely a mock
+ // from a test in which case the pub command should still be created.
+ if (baseResourceProvider is PhysicalResourceProvider) {
+ processRunner ??= ProcessRunner();
+ }
+ final pubCommand = processRunner != null
+ ? PubCommand(instrumentationService, processRunner)
+ : null;
+
+ pubPackageService = PubPackageService(
+ instrumentationService, baseResourceProvider, pubApi, pubCommand);
performance = performanceDuringStartup;
pluginManager = PluginManager(
@@ -380,7 +394,7 @@
}
var session = getAnalysisDriver(path)?.currentSession;
- var result = session?.getParsedUnit2(path);
+ var result = session?.getParsedUnit(path);
return result is ParsedUnitResult ? result : null;
}
diff --git a/pkg/analysis_server/lib/src/cider/rename.dart b/pkg/analysis_server/lib/src/cider/rename.dart
index 6ea1b32..71e8148 100644
--- a/pkg/analysis_server/lib/src/cider/rename.dart
+++ b/pkg/analysis_server/lib/src/cider/rename.dart
@@ -2,6 +2,8 @@
// 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.
+import 'package:analysis_server/src/services/correction/status.dart';
+import 'package:analysis_server/src/services/refactoring/naming_conventions.dart';
import 'package:analysis_server/src/services/refactoring/refactoring.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/source/line_info.dart';
@@ -17,6 +19,14 @@
CanRenameResponse(this.lineInfo, this.refactoringElement, this.oldName);
}
+class CheckNameResponse {
+ final LineInfo lineInfo;
+ final RefactoringStatus status;
+ final String oldName;
+
+ CheckNameResponse(this.lineInfo, this.status, this.oldName);
+}
+
class CiderRenameComputer {
final FileResolver _fileResolver;
@@ -51,6 +61,32 @@
return null;
}
+ CheckNameResponse? checkNewName(String filePath, int line, int column, String name) {
+ var resolvedUnit = _fileResolver.resolve(path: filePath);
+ var lineInfo = resolvedUnit.lineInfo;
+ var offset = lineInfo.getOffsetOfLine(line) + column;
+
+ var node = NodeLocator(offset).searchWithin(resolvedUnit.unit);
+ var element = getElementOfNode(node);
+
+ if (node == null || element == null) {
+ return null;
+ }
+
+ RefactoringStatus? status;
+ if (element is LocalVariableElement) {
+ status = validateVariableName(name);
+ } else if (element is ParameterElement) {
+ status = validateParameterName(name);
+ } else if (element is FunctionElement) {
+ status = validateFunctionName(name);
+ }
+ if (status == null){
+ return null;
+ }
+ return CheckNameResponse(lineInfo, status, element.displayName);
+ }
+
bool _canRenameElement(Element element) {
if (element is PropertyAccessorElement) {
element = element.variable;
diff --git a/pkg/analysis_server/lib/src/computer/computer_outline.dart b/pkg/analysis_server/lib/src/computer/computer_outline.dart
index fedd848..c4247be 100644
--- a/pkg/analysis_server/lib/src/computer/computer_outline.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_outline.dart
@@ -17,17 +17,9 @@
DartUnitOutlineComputer(this.resolvedUnit, {this.withBasicFlutter = false});
- CompilationUnit get _unit {
- var unit = resolvedUnit.unit;
- if (unit == null) {
- throw StateError('DartUnitOutlineComputer created with invalid result');
- }
- return unit;
- }
-
/// Returns the computed outline, not `null`.
Outline compute() {
- var unit = _unit;
+ var unit = resolvedUnit.unit;
var unitContents = <Outline>[];
for (var unitMember in unit.declarations) {
if (unitMember is ClassDeclaration) {
@@ -87,17 +79,14 @@
Location _getLocationOffsetLength(int offset, int length) {
var path = resolvedUnit.path;
- if (path == null) {
- throw StateError('DartUnitOutlineComputer called with invalid result');
- }
var startLocation = resolvedUnit.lineInfo.getLocation(offset);
var startLine = startLocation.lineNumber;
var startColumn = startLocation.columnNumber;
var endLocation = resolvedUnit.lineInfo.getLocation(offset + length);
var endLine = endLocation.lineNumber;
var endColumn = endLocation.columnNumber;
- return Location(
- path, offset, length, startLine, startColumn, endLine, endColumn);
+ return Location(path, offset, length, startLine, startColumn,
+ endLine: endLine, endColumn: endColumn);
}
Outline _newClassOutline(ClassDeclaration node, List<Outline> classContents) {
@@ -328,7 +317,7 @@
}
Outline _newUnitOutline(List<Outline> unitContents) {
- var unit = _unit;
+ var unit = resolvedUnit.unit;
var element = Element(
ElementKind.COMPILATION_UNIT, '<unit>', Element.makeFlags(),
location: _getLocationNode(unit));
diff --git a/pkg/analysis_server/lib/src/computer/import_elements_computer.dart b/pkg/analysis_server/lib/src/computer/import_elements_computer.dart
index 3a2ec51..a29230f 100644
--- a/pkg/analysis_server/lib/src/computer/import_elements_computer.dart
+++ b/pkg/analysis_server/lib/src/computer/import_elements_computer.dart
@@ -32,12 +32,6 @@
Future<SourceChange> createEdits(
List<ImportedElements> importedElementsList) async {
var unit = libraryResult.unit;
- var path = libraryResult.path;
- if (unit == null || path == null) {
- // We should never reach this point because the libraryResult should be
- // valid.
- return SourceChange('');
- }
var filteredImportedElements =
_filterImportedElements(importedElementsList);
var libraryElement = libraryResult.libraryElement;
@@ -50,7 +44,7 @@
}
var builder = ChangeBuilder(session: libraryResult.session);
- await builder.addDartFileEdit(path, (builder) {
+ await builder.addDartFileEdit(libraryResult.path, (builder) {
for (var importedElements in filteredImportedElements) {
var matchingImports =
_findMatchingImports(existingImports, importedElements);
@@ -280,11 +274,6 @@
/// Partially copied from DartFileEditBuilderImpl.
_InsertionDescription _getInsertionDescription(String importUri) {
var unit = libraryResult.unit;
- if (unit == null) {
- // We should never reach this point because the libraryResult should be
- // valid.
- return _InsertionDescription(0, after: 2);
- }
LibraryDirective? libraryDirective;
var importDirectives = <ImportDirective>[];
var otherDirectives = <Directive>[];
diff --git a/pkg/analysis_server/lib/src/context_manager.dart b/pkg/analysis_server/lib/src/context_manager.dart
index 721f37c..28509f0 100644
--- a/pkg/analysis_server/lib/src/context_manager.dart
+++ b/pkg/analysis_server/lib/src/context_manager.dart
@@ -122,6 +122,12 @@
/// TODO(scheglov) Just pass results in here?
void listenAnalysisDriver(AnalysisDriver driver);
+ /// The `pubspec.yaml` at [path] was added/modified.
+ void pubspecChanged(String path);
+
+ /// The `pubspec.yaml` at [path] was removed.
+ void pubspecRemoved(String path);
+
/// Record error information for the file with the given [path].
void recordAnalysisErrors(String path, List<protocol.AnalysisError> errors);
}
@@ -566,12 +572,21 @@
_instrumentationService.logWatchEvent('<unknown>', path, type.toString());
+ final isPubpsec = file_paths.isPubspecYaml(pathContext, path);
if (file_paths.isAnalysisOptionsYaml(pathContext, path) ||
file_paths.isDotPackages(pathContext, path) ||
file_paths.isPackageConfigJson(pathContext, path) ||
- file_paths.isPubspecYaml(pathContext, path) ||
+ isPubpsec ||
false) {
_createAnalysisContexts();
+
+ if (isPubpsec) {
+ if (type == ChangeType.REMOVE) {
+ callbacks.pubspecRemoved(path);
+ } else {
+ callbacks.pubspecChanged(path);
+ }
+ }
return;
}
@@ -727,6 +742,12 @@
void listenAnalysisDriver(AnalysisDriver driver) {}
@override
+ void pubspecChanged(String pubspecPath) {}
+
+ @override
+ void pubspecRemoved(String pubspecPath) {}
+
+ @override
void recordAnalysisErrors(String path, List<protocol.AnalysisError> errors) {}
}
diff --git a/pkg/analysis_server/lib/src/domain_analysis.dart b/pkg/analysis_server/lib/src/domain_analysis.dart
index 2e2bc5d..df5d9f6 100644
--- a/pkg/analysis_server/lib/src/domain_analysis.dart
+++ b/pkg/analysis_server/lib/src/domain_analysis.dart
@@ -63,7 +63,7 @@
server.sendResponse(Response.fileNotAnalyzed(request, file));
return;
}
- var unit = result.unit!;
+ var unit = result.unit;
// Prepare the hovers.
var hovers = <HoverInformation>[];
@@ -105,7 +105,7 @@
elements = <ImportedElements>[];
} else {
elements =
- ImportedElementsComputer(result.unit!, params.offset, params.length)
+ ImportedElementsComputer(result.unit, params.offset, params.length)
.compute();
}
@@ -166,7 +166,7 @@
var allResults = <AnalysisNavigationParams>[];
var result = await server.getResolvedUnit(file);
if (result != null && result.state == ResultState.VALID) {
- var unit = result.unit!;
+ var unit = result.unit;
var collector = NavigationCollectorImpl();
computeDartNavigation(
server.resourceProvider, collector, unit, offset, length);
@@ -237,7 +237,7 @@
}
// Ensure the offset provided is a valid location in the file.
- final unit = result.unit!;
+ final unit = result.unit;
final computer = DartUnitSignatureComputer(
server.getDartdocDirectiveInfoFor(result), unit, params.offset);
if (!computer.offsetIsValid) {
diff --git a/pkg/analysis_server/lib/src/domain_completion.dart b/pkg/analysis_server/lib/src/domain_completion.dart
index 78db63a..9a10237 100644
--- a/pkg/analysis_server/lib/src/domain_completion.dart
+++ b/pkg/analysis_server/lib/src/domain_completion.dart
@@ -330,7 +330,7 @@
}
server.requestStatistics?.addItemTimeNow(request, 'resolvedUnit');
if (resolvedUnit.state == ResultState.VALID) {
- if (offset < 0 || offset > resolvedUnit.content!.length) {
+ if (offset < 0 || offset > resolvedUnit.content.length) {
server.sendResponse(Response.invalidParameter(
request,
'params.offset',
@@ -339,7 +339,7 @@
return;
}
- recordRequest(performance, file, resolvedUnit.content!, offset);
+ recordRequest(performance, file, resolvedUnit.content, offset);
}
var declarationsTracker = server.declarationsTracker;
if (declarationsTracker == null) {
diff --git a/pkg/analysis_server/lib/src/domain_kythe.dart b/pkg/analysis_server/lib/src/domain_kythe.dart
index b03acbb..990588e 100644
--- a/pkg/analysis_server/lib/src/domain_kythe.dart
+++ b/pkg/analysis_server/lib/src/domain_kythe.dart
@@ -47,8 +47,8 @@
var entries = <KytheEntry>[];
// TODO(brianwilkerson) Figure out how to get the list of files.
var files = <String>[];
- result.unit!.accept(KytheDartVisitor(server.resourceProvider, entries,
- file, InheritanceManager3(), result.content!));
+ result.unit.accept(KytheDartVisitor(server.resourceProvider, entries,
+ file, InheritanceManager3(), result.content));
allResults.add(KytheGetKytheEntriesResult(entries, files));
}
//
diff --git a/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart b/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart
index 223e056..54ffabf 100644
--- a/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart
+++ b/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart
@@ -24,7 +24,7 @@
var context = tracker.getContext(analysisContext);
if (context == null) return;
- var librariesObject = context.getLibraries(resolvedUnit.path!);
+ var librariesObject = context.getLibraries(resolvedUnit.path);
var importedUriSet = resolvedUnit.libraryElement.importedLibraries
.map((importedLibrary) => importedLibrary.source.uri)
@@ -261,8 +261,8 @@
0, // length
declaration.locationStartLine,
declaration.locationStartColumn,
- declaration.locationStartLine, // endLine
- declaration.locationStartColumn, // endColumn
+ endLine: declaration.locationStartLine,
+ endColumn: declaration.locationStartColumn,
),
parameters: declaration.parameters,
returnType: declaration.returnType,
diff --git a/pkg/analysis_server/lib/src/domains/execution/completion.dart b/pkg/analysis_server/lib/src/domains/execution/completion.dart
index 97ab5bf..7162de9 100644
--- a/pkg/analysis_server/lib/src/domains/execution/completion.dart
+++ b/pkg/analysis_server/lib/src/domains/execution/completion.dart
@@ -53,7 +53,7 @@
// Compute the patched context file content.
var targetCode = SourceEdit.applySequence(
- contextResult.content!,
+ contextResult.content,
changeBuilder.sourceChange.edits[0].edits,
);
diff --git a/pkg/analysis_server/lib/src/edit/edit_domain.dart b/pkg/analysis_server/lib/src/edit/edit_domain.dart
index 0e5ba49..b73448c 100644
--- a/pkg/analysis_server/lib/src/edit/edit_domain.dart
+++ b/pkg/analysis_server/lib/src/edit/edit_domain.dart
@@ -32,7 +32,6 @@
import 'package:analysis_server/src/services/correction/status.dart';
import 'package:analysis_server/src/services/refactoring/refactoring.dart';
import 'package:analysis_server/src/services/search/search_engine.dart';
-import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/analysis/session.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/error/error.dart' as engine;
@@ -402,7 +401,7 @@
return;
}
var libraryUnit = result.libraryElement.definingCompilationUnit;
- if (libraryUnit != result.unit!.declaredElement) {
+ if (libraryUnit != result.unit.declaredElement) {
// The file in the request is a part of a library. We need to pass the
// defining compilation unit to the computer, not the part.
result = await server.getResolvedUnit(libraryUnit.source.fullName);
@@ -484,8 +483,8 @@
return;
}
var fileStamp = -1;
- var code = result.content!;
- var unit = result.unit!;
+ var code = result.content;
+ var unit = result.unit;
var errors = result.errors;
// check if there are scan/parse errors in the file
var numScanParseErrors = _getNumberOfScanParseErrors(errors);
@@ -575,8 +574,8 @@
if (fixes.isNotEmpty) {
fixes.sort(Fix.SORT_BY_RELEVANCE);
var lineInfo = LineInfo.fromContent(content);
- ResolvedUnitResult result = engine.ResolvedUnitResultImpl(session, file,
- Uri.file(file), true, content, lineInfo, false, null, errors);
+ var result = engine.ErrorsResultImpl(
+ session, file, Uri.file(file), lineInfo, false, errors);
var serverError = newAnalysisError_fromEngine(result, error);
var errorFixes = AnalysisErrorFixes(serverError);
errorFixesList.add(errorFixes);
@@ -611,7 +610,7 @@
var provider = TopLevelDeclarationsProvider(tracker);
return provider.get(
result.session.analysisContext,
- result.path!,
+ result.path,
name,
);
}, extensionCache: server.getExtensionCacheFor(result));
@@ -628,7 +627,7 @@
error.errorCode: ${error.errorCode}
''';
throw CaughtExceptionWithFiles(exception, stackTrace, {
- file: result.content!,
+ file: result.content,
'parameters': parametersFile,
});
}
@@ -674,8 +673,8 @@
if (fixes.isNotEmpty) {
fixes.sort(Fix.SORT_BY_RELEVANCE);
var lineInfo = LineInfo.fromContent(content);
- ResolvedUnitResult result = engine.ResolvedUnitResultImpl(session, file,
- Uri.file(file), true, content, lineInfo, false, null, errors);
+ var result = engine.ErrorsResultImpl(
+ session, file, Uri.file(file), lineInfo, false, errors);
var serverError = newAnalysisError_fromEngine(result, error);
var errorFixes = AnalysisErrorFixes(serverError);
errorFixesList.add(errorFixes);
@@ -723,8 +722,8 @@
if (fixes.isNotEmpty) {
fixes.sort(Fix.SORT_BY_RELEVANCE);
var lineInfo = LineInfo.fromContent(content);
- ResolvedUnitResult result = engine.ResolvedUnitResultImpl(session, file,
- Uri.file(file), true, content, lineInfo, false, null, errors);
+ var result = engine.ErrorsResultImpl(
+ session, file, Uri.file(file), lineInfo, false, errors);
var serverError = newAnalysisError_fromEngine(result, error);
var errorFixes = AnalysisErrorFixes(serverError);
errorFixesList.add(errorFixes);
@@ -767,7 +766,7 @@
length: $length
''';
throw CaughtExceptionWithFiles(exception, stackTrace, {
- file: result.content!,
+ file: result.content,
'parameters': parametersFile,
});
}
diff --git a/pkg/analysis_server/lib/src/flutter/flutter_notifications.dart b/pkg/analysis_server/lib/src/flutter/flutter_notifications.dart
index 36e5272..74085faa 100644
--- a/pkg/analysis_server/lib/src/flutter/flutter_notifications.dart
+++ b/pkg/analysis_server/lib/src/flutter/flutter_notifications.dart
@@ -15,7 +15,7 @@
var outline = computer.compute();
// send notification
var params = protocol.FlutterOutlineParams(
- resolvedUnit.path!,
+ resolvedUnit.path,
outline,
);
server.sendNotification(params.toNotification());
diff --git a/pkg/analysis_server/lib/src/flutter/flutter_outline_computer.dart b/pkg/analysis_server/lib/src/flutter/flutter_outline_computer.dart
index d216445..8c3dd26 100644
--- a/pkg/analysis_server/lib/src/flutter/flutter_outline_computer.dart
+++ b/pkg/analysis_server/lib/src/flutter/flutter_outline_computer.dart
@@ -31,7 +31,7 @@
// Create outlines for widgets.
var visitor = _FlutterOutlineBuilder(this);
- resolvedUnit.unit!.accept(visitor);
+ resolvedUnit.unit.accept(visitor);
// Associate Flutter outlines with Dart outlines.
for (var outline in visitor.outlines) {
@@ -66,7 +66,7 @@
var name = parameter.displayName;
- var label = resolvedUnit.content!.substring(argument.offset, argument.end);
+ var label = resolvedUnit.content.substring(argument.offset, argument.end);
if (label.contains('\n')) {
label = '…';
}
diff --git a/pkg/analysis_server/lib/src/lsp/client_configuration.dart b/pkg/analysis_server/lib/src/lsp/client_configuration.dart
index 332330f..9093676 100644
--- a/pkg/analysis_server/lib/src/lsp/client_configuration.dart
+++ b/pkg/analysis_server/lib/src/lsp/client_configuration.dart
@@ -2,10 +2,102 @@
// 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.
+import 'package:collection/collection.dart';
+import 'package:path/path.dart' as path;
+
+/// Provides access to both global and resource-specific client configuration.
+///
+/// Resource-specific config is currently only supported at the WorkspaceFolder
+/// level so when looking up config for a resource, the nearest WorkspaceFolders
+/// config will be used.
+class LspClientConfiguration {
+ /// Global settings for the workspace.
+ ///
+ /// Used as a fallback for resource settings if no specific config is found
+ /// for the resource.
+ LspGlobalClientConfiguration _globalSettings =
+ LspGlobalClientConfiguration({});
+
+ /// Settings for each resource.
+ ///
+ /// Keys are string paths without trailing path separators (eg. 'C:\foo').
+ final Map<String, LspResourceClientConfiguration> _resourceSettings =
+ <String, LspResourceClientConfiguration>{};
+
+ /// Pattern for stripping trailing slashes that may be been provided by the
+ /// client (in WorkspaceFolder URIs) for consistent comparisons.
+ final _trailingSlashPattern = RegExp(r'[\/]+$');
+
+ /// Returns the global configuration for the whole workspace.
+ LspGlobalClientConfiguration get global => _globalSettings;
+
+ /// Returns whether or not the provided new configuration changes any values
+ /// that would require analysis roots to be updated.
+ bool affectsAnalysisRoots(LspGlobalClientConfiguration otherConfig) {
+ return _globalSettings.analysisExcludedFolders !=
+ otherConfig.analysisExcludedFolders;
+ }
+
+ /// Returns config for a given resource.
+ ///
+ /// Because we only support config at the WorkspaceFolder level, this is done
+ /// by finding the nearest WorkspaceFolder to [resourcePath] and using config
+ /// for that.
+ ///
+ /// If no specific config is available, returns [global].
+ LspResourceClientConfiguration forResource(String resourcePath) {
+ final workspaceFolder = _getWorkspaceFolderPath(resourcePath);
+
+ if (workspaceFolder == null) {
+ return _globalSettings;
+ }
+
+ return _resourceSettings[_normaliseFolderPath(workspaceFolder)] ??
+ _globalSettings;
+ }
+
+ /// Replaces all previously known configuration with updated values from the
+ /// client.
+ void replace(
+ Map<String, Object?> globalConfig,
+ Map<String, Map<String, Object?>> workspaceFolderConfig,
+ ) {
+ _globalSettings = LspGlobalClientConfiguration(globalConfig);
+
+ _resourceSettings
+ ..clear()
+ ..addAll(workspaceFolderConfig.map(
+ (key, value) => MapEntry(
+ _normaliseFolderPath(key),
+ LspResourceClientConfiguration(value, _globalSettings),
+ ),
+ ));
+ }
+
+ /// Gets the path for the WorkspaceFolder closest to [resourcePath].
+ String? _getWorkspaceFolderPath(String resourcePath) {
+ final candidates = _resourceSettings.keys
+ .where((wfPath) =>
+ wfPath == _normaliseFolderPath(resourcePath) ||
+ path.isWithin(wfPath, resourcePath))
+ .toList();
+ candidates.sort((a, b) => -a.length.compareTo(b.length));
+ return candidates.firstOrNull;
+ }
+
+ /// Normalises a folder path to never have a trailing path separator.
+ String _normaliseFolderPath(String path) =>
+ path.replaceAll(_trailingSlashPattern, '');
+}
+
/// Wraps the client (editor) configuration to provide stronger typing and
/// handling of default values where a setting has not been supplied.
-class LspClientConfiguration {
- final Map<String, dynamic> _settings = <String, dynamic>{};
+///
+/// Settings in this class are only allowed to be configured at the workspace
+/// level (they will be ignored at the resource level).
+class LspGlobalClientConfiguration extends LspResourceClientConfiguration {
+ LspGlobalClientConfiguration(Map<String, Object?> settings)
+ : super(settings, null);
List<String> get analysisExcludedFolders {
// This setting is documented as a string array, but because editors are
@@ -20,30 +112,48 @@
}
}
- bool get completeFunctionCalls => _settings['completeFunctionCalls'] ?? false;
- bool get enableSdkFormatter => _settings['enableSdkFormatter'] ?? true;
- int? get lineLength => _settings['lineLength'];
+ /// Whether methods/functions in completion should include parens and argument
+ /// placeholders when used in an invocation context.
+ bool get completeFunctionCalls =>
+ _settings['completeFunctionCalls'] as bool? ?? false;
/// A preview flag for enabling commit characters for completions.
///
/// This is a temporary setting to allow this feature to be tested without
/// defaulting to on for everybody.
bool get previewCommitCharacters =>
- _settings['previewCommitCharacters'] ?? false;
+ _settings['previewCommitCharacters'] as bool? ?? false;
/// Whether diagnostics should be generated for TODO comments.
- bool get showTodos => _settings['showTodos'] ?? false;
+ bool get showTodos => _settings['showTodos'] as bool? ?? false;
+}
- /// Returns whether or not the provided new configuration changes any values
- /// that would require analysis roots to be updated.
- bool affectsAnalysisRoots(Map<String, dynamic> newConfig) {
- return _settings['analysisExcludedFolders'] !=
- newConfig['analysisExcludedFolders'];
- }
+/// Wraps the client (editor) configuration for a specific resource.
+///
+/// Settings in this class are only allowed to be configured either for a
+/// resource or for the whole workspace.
+///
+/// Right now, we treat "resource" to always mean a WorkspaceFolder since no
+/// known editors allow per-file configuration and it allows us to keep the
+/// settings cached, invalidated only when WorkspaceFolders change.
+class LspResourceClientConfiguration {
+ final Map<String, Object?> _settings;
+ final LspResourceClientConfiguration? _fallback;
- void replace(Map<String, dynamic> newConfig) {
- _settings
- ..clear()
- ..addAll(newConfig);
- }
+ LspResourceClientConfiguration(this._settings, this._fallback);
+
+ /// Whether to enable the SDK formatter.
+ ///
+ /// If this setting is `false`, the formatter will be unregistered with the
+ /// client.
+ bool get enableSdkFormatter =>
+ _settings['enableSdkFormatter'] as bool? ??
+ _fallback?.enableSdkFormatter ??
+ true;
+
+ /// The line length used when formatting documents.
+ ///
+ /// If null, the formatters default will be used.
+ int? get lineLength =>
+ _settings['lineLength'] as int? ?? _fallback?.lineLength;
}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/commands/fix_all.dart b/pkg/analysis_server/lib/src/lsp/handlers/commands/fix_all.dart
index 784e2fe..4d4f523 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/commands/fix_all.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/commands/fix_all.dart
@@ -12,7 +12,6 @@
import 'package:analysis_server/src/lsp/progress.dart';
import 'package:analysis_server/src/services/correction/bulk_fix_processor.dart';
import 'package:analysis_server/src/services/correction/change_workspace.dart';
-import 'package:analyzer/src/dart/analysis/analysis_context_collection.dart';
class FixAllCommandHandler extends SimpleEditCommandHandler {
FixAllCommandHandler(LspAnalysisServer server) : super(server);
@@ -48,14 +47,13 @@
final processor =
BulkFixProcessor(server.instrumentationService, workspace);
- final collection = AnalysisContextCollectionImpl(
- includedPaths: [path],
- resourceProvider: server.resourceProvider,
- sdkPath: server.sdkManager.defaultSdkDirectory,
- );
- final changeBuilder = await processor.fixErrors(collection.contexts);
- final change = changeBuilder.sourceChange;
+ final context = server.contextManager.getContextFor(path);
+ if (context == null) {
+ return success(null);
+ }
+ final changeBuilder = await processor.fixErrorsForFile(context, path);
+ final change = changeBuilder.sourceChange;
if (change.edits.isEmpty) {
return success(null);
}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/commands/organize_imports.dart b/pkg/analysis_server/lib/src/lsp/handlers/commands/organize_imports.dart
index 6b3ac68..2a81ac0 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/commands/organize_imports.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/commands/organize_imports.dart
@@ -41,8 +41,8 @@
}
return result.mapResult((result) {
- final code = result.content!;
- final unit = result.unit!;
+ final code = result.content;
+ final unit = result.unit;
if (hasScanParseErrors(result.errors)) {
// It's not uncommon for editors to run this command automatically on-save
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/commands/perform_refactor.dart b/pkg/analysis_server/lib/src/lsp/handlers/commands/perform_refactor.dart
index ed17c2a..20c4d27 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/commands/perform_refactor.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/commands/perform_refactor.dart
@@ -14,6 +14,8 @@
import 'package:analysis_server/src/services/refactoring/refactoring.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/analysis/session.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/ast/utilities.dart';
final _manager = _RefactorManager();
@@ -173,6 +175,32 @@
InlineMethodRefactoring(server.searchEngine, result, offset);
return success(refactor);
+ case RefactoringKind.CONVERT_GETTER_TO_METHOD:
+ final node = NodeLocator(offset).searchWithin(result.unit);
+ final element = server.getElementOfNode(node);
+ if (element != null) {
+ if (element is PropertyAccessorElement) {
+ final refactor = ConvertGetterToMethodRefactoring(
+ server.searchEngine, result.session, element);
+ return success(refactor);
+ }
+ }
+ return error(ServerErrorCodes.InvalidCommandArguments,
+ 'Location supplied to $commandName $kind is not longer valid');
+
+ case RefactoringKind.CONVERT_METHOD_TO_GETTER:
+ final node = NodeLocator(offset).searchWithin(result.unit);
+ final element = server.getElementOfNode(node);
+ if (element != null) {
+ if (element is ExecutableElement) {
+ final refactor = ConvertMethodToGetterRefactoring(
+ server.searchEngine, result.session, element);
+ return success(refactor);
+ }
+ }
+ return error(ServerErrorCodes.InvalidCommandArguments,
+ 'Location supplied to $commandName $kind is not longer valid');
+
default:
return error(ServerErrorCodes.InvalidCommandArguments,
'Unknown RefactoringKind $kind was supplied to $commandName');
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_change_workspace_folders.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_change_workspace_folders.dart
index 9a530d3..e270255 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_change_workspace_folders.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_change_workspace_folders.dart
@@ -23,8 +23,8 @@
DidChangeWorkspaceFoldersParams.jsonHandler;
@override
- ErrorOr<void> handle(
- DidChangeWorkspaceFoldersParams params, CancellationToken token) {
+ Future<ErrorOr<void>> handle(
+ DidChangeWorkspaceFoldersParams params, CancellationToken token) async {
// Don't do anything if our analysis roots are not based on open workspaces.
if (!updateAnalysisRoots) {
return success(null);
@@ -37,7 +37,7 @@
.map((wf) => Uri.parse(wf.uri).toFilePath())
.toList();
- server.updateWorkspaceFolders(added, removed);
+ await server.updateWorkspaceFolders(added, removed);
return success(null);
}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart
index 5063d04..9f7152c 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart
@@ -4,12 +4,11 @@
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
-import 'package:analysis_server/plugin/edit/assist/assist_core.dart';
-import 'package:analysis_server/plugin/edit/fix/fix_core.dart';
import 'package:analysis_server/src/lsp/constants.dart';
import 'package:analysis_server/src/lsp/handlers/handlers.dart';
import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
import 'package:analysis_server/src/lsp/mapping.dart';
+import 'package:analysis_server/src/plugin/plugin_manager.dart';
import 'package:analysis_server/src/protocol_server.dart' hide Position;
import 'package:analysis_server/src/services/correction/assist.dart';
import 'package:analysis_server/src/services/correction/assist_internal.dart';
@@ -21,12 +20,37 @@
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/analysis/session.dart'
show InconsistentAnalysisException;
-import 'package:analyzer/error/error.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/util/file_paths.dart' as file_paths;
+import 'package:analyzer_plugin/protocol/protocol.dart' as plugin;
+import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
import 'package:collection/collection.dart' show groupBy;
class CodeActionHandler extends MessageHandler<CodeActionParams,
List<Either2<Command, CodeAction>>> {
+ // Because server+plugin results are different types and we lose
+ // priorites when converting them to CodeActions, store the priorities
+ // against each action in an expando. This avoids wrapping CodeActions in
+ // another wrapper class (since we can't modify the LSP-spec-generated
+ // CodeAction class).
+ final codeActionPriorities = Expando<int>();
+
+ /// A comparator that can be used to sort [CodeActions]s using priorties
+ /// in [codeActionPriorities]. The highest number priority will be sorted
+ /// before lower number priorityies. Items with the same relevance are sorted
+ /// alphabetically by their title.
+ late final Comparator<CodeAction> _codeActionComparator =
+ (CodeAction a, CodeAction b) {
+ // We should never be sorting actions without priorities.
+ final aPriority = codeActionPriorities[a] ?? 0;
+ final bPriority = codeActionPriorities[b] ?? 0;
+ if (aPriority != bPriority) {
+ return bPriority - aPriority;
+ }
+ return a.title.compareTo(b.title);
+ };
+
CodeActionHandler(LspAnalysisServer server) : super(server);
@override
@@ -145,12 +169,12 @@
/// version of each document being modified so it's important to call this
/// immediately after computing edits to ensure the document is not modified
/// before the version number is read.
- CodeAction _createAssistAction(Assist assist) {
+ CodeAction _createAssistAction(SourceChange change) {
return CodeAction(
- title: assist.change.message,
- kind: toCodeActionKind(assist.change.id, CodeActionKind.Refactor),
+ title: change.message,
+ kind: toCodeActionKind(change.id, CodeActionKind.Refactor),
diagnostics: const [],
- edit: createWorkspaceEdit(server, assist.change),
+ edit: createWorkspaceEdit(server, change),
);
}
@@ -158,12 +182,12 @@
/// version of each document being modified so it's important to call this
/// immediately after computing edits to ensure the document is not modified
/// before the version number is read.
- CodeAction _createFixAction(Fix fix, Diagnostic diagnostic) {
+ CodeAction _createFixAction(SourceChange change, Diagnostic diagnostic) {
return CodeAction(
- title: fix.change.message,
- kind: toCodeActionKind(fix.change.id, CodeActionKind.QuickFix),
+ title: change.message,
+ kind: toCodeActionKind(change.id, CodeActionKind.QuickFix),
diagnostics: [diagnostic],
- edit: createWorkspaceEdit(server, fix.change),
+ edit: createWorkspaceEdit(server, change),
);
}
@@ -220,6 +244,7 @@
Future<List<Either2<Command, CodeAction>>> _getAssistActions(
bool Function(CodeActionKind?) shouldIncludeKind,
bool supportsLiteralCodeActions,
+ String path,
Range range,
int offset,
int length,
@@ -234,13 +259,28 @@
length,
);
final processor = AssistProcessor(context);
- final assists = await processor.compute();
- assists.sort(Assist.SORT_BY_RELEVANCE);
+ final serverFuture = processor.compute();
+ final pluginFuture = _getPluginAssistChanges(path, offset, length);
- final assistActions =
- _dedupeActions(assists.map(_createAssistAction), range.start);
+ final assists = await serverFuture;
+ final pluginChanges = await pluginFuture;
- return assistActions
+ final codeActions = <CodeAction>[];
+ codeActions.addAll(assists.map((assist) {
+ final action = _createAssistAction(assist.change);
+ codeActionPriorities[action] = assist.kind.priority;
+ return action;
+ }));
+ codeActions.addAll(pluginChanges.map((change) {
+ final action = _createAssistAction(change.change);
+ codeActionPriorities[action] = change.priority;
+ return action;
+ }));
+
+ final dedupedCodeActions = _dedupeActions(codeActions, range.start);
+ dedupedCodeActions.sort(_codeActionComparator);
+
+ return dedupedCodeActions
.where((action) => shouldIncludeKind(action.kind))
.map((action) => Either2<Command, CodeAction>.t2(action))
.toList();
@@ -266,11 +306,11 @@
final results = await Future.wait([
_getSourceActions(shouldIncludeKind, supportsLiterals,
supportsWorkspaceApplyEdit, path),
- _getAssistActions(
- shouldIncludeKind, supportsLiterals, range, offset, length, unit),
+ _getAssistActions(shouldIncludeKind, supportsLiterals, path, range,
+ offset, length, unit),
_getRefactorActions(
shouldIncludeKind, supportsLiterals, path, offset, length, unit),
- _getFixActions(shouldIncludeKind, supportsLiterals,
+ _getFixActions(shouldIncludeKind, supportsLiterals, path, offset,
supportedDiagnosticTags, range, unit),
]);
final flatResults = results.expand((x) => x).toList();
@@ -281,22 +321,23 @@
Future<List<Either2<Command, CodeAction>>> _getFixActions(
bool Function(CodeActionKind?) shouldIncludeKind,
bool supportsLiteralCodeActions,
+ String path,
+ int offset,
Set<DiagnosticTag> supportedDiagnosticTags,
Range range,
ResolvedUnitResult unit,
) async {
+ final clientSupportsCodeDescription =
+ server.clientCapabilities?.diagnosticCodeDescription ?? false;
+ // TODO(dantup): We may be missing fixes for pubspec, analysis_options,
+ // android manifests (see _computeServerErrorFixes in EditDomainHandler).
final lineInfo = unit.lineInfo;
final codeActions = <CodeAction>[];
final fixContributor = DartFixContributor();
- try {
- final errorCodeCounts = <ErrorCode, int>{};
- // Count the errors by code so we know whether to include a fix-all.
- for (final error in unit.errors) {
- errorCodeCounts[error.errorCode] =
- (errorCodeCounts[error.errorCode] ?? 0) + 1;
- }
+ final pluginFuture = _getPluginFixActions(unit, offset);
+ try {
for (final error in unit.errors) {
// Server lineNumber is one-based so subtract one.
var errorLine = lineInfo.getLocation(error.offset).lineNumber - 1;
@@ -309,28 +350,50 @@
var tracker = server.declarationsTracker!;
return TopLevelDeclarationsProvider(tracker).get(
unit.session.analysisContext,
- unit.path!,
+ unit.path,
name,
);
}, extensionCache: server.getExtensionCacheFor(unit));
final fixes = await fixContributor.computeFixes(context);
if (fixes.isNotEmpty) {
- fixes.sort(Fix.SORT_BY_RELEVANCE);
-
final diagnostic = toDiagnostic(
unit,
error,
supportedTags: supportedDiagnosticTags,
- clientSupportsCodeDescription:
- server.clientCapabilities?.diagnosticCodeDescription ?? false,
+ clientSupportsCodeDescription: clientSupportsCodeDescription,
);
codeActions.addAll(
- fixes.map((fix) => _createFixAction(fix, diagnostic)),
+ fixes.map((fix) {
+ final action = _createFixAction(fix.change, diagnostic);
+ codeActionPriorities[action] = fix.kind.priority;
+ return action;
+ }),
);
}
}
+ Diagnostic pluginErrorToDiagnostic(AnalysisError error) {
+ return pluginToDiagnostic(
+ (_) => lineInfo,
+ error,
+ supportedTags: supportedDiagnosticTags,
+ clientSupportsCodeDescription: clientSupportsCodeDescription,
+ );
+ }
+
+ final pluginFixes = await pluginFuture;
+ final pluginFixActions = pluginFixes.expand(
+ (fix) => fix.fixes.map((fixChange) {
+ final action = _createFixAction(
+ fixChange.change, pluginErrorToDiagnostic(fix.error));
+ codeActionPriorities[action] = fixChange.priority;
+ return action;
+ }),
+ );
+ codeActions.addAll(pluginFixActions);
+
final dedupedActions = _dedupeActions(codeActions, range.start);
+ dedupedActions.sort(_codeActionComparator);
return dedupedActions
.where((action) => shouldIncludeKind(action.kind))
@@ -344,6 +407,61 @@
}
}
+ Future<Iterable<plugin.PrioritizedSourceChange>> _getPluginAssistChanges(
+ String path, int offset, int length) async {
+ final requestParams = plugin.EditGetAssistsParams(path, offset, length);
+ final driver = server.getAnalysisDriver(path);
+
+ Map<PluginInfo, Future<plugin.Response>> pluginFutures;
+ if (driver == null) {
+ pluginFutures = <PluginInfo, Future<plugin.Response>>{};
+ } else {
+ pluginFutures = server.pluginManager.broadcastRequest(
+ requestParams,
+ contextRoot: driver.analysisContext!.contextRoot,
+ );
+ }
+
+ final pluginChanges = <plugin.PrioritizedSourceChange>[];
+ final responses =
+ await waitForResponses(pluginFutures, requestParameters: requestParams);
+
+ for (final response in responses) {
+ final result = plugin.EditGetAssistsResult.fromResponse(response);
+ pluginChanges.addAll(result.assists);
+ }
+
+ return pluginChanges;
+ }
+
+ Future<Iterable<plugin.AnalysisErrorFixes>> _getPluginFixActions(
+ ResolvedUnitResult unit, int offset) async {
+ final file = unit.path;
+ final requestParams = plugin.EditGetFixesParams(file, offset);
+ final driver = server.getAnalysisDriver(file);
+
+ Map<PluginInfo, Future<plugin.Response>> pluginFutures;
+ if (driver == null) {
+ pluginFutures = <PluginInfo, Future<plugin.Response>>{};
+ } else {
+ pluginFutures = server.pluginManager.broadcastRequest(
+ requestParams,
+ contextRoot: driver.analysisContext!.contextRoot,
+ );
+ }
+
+ final pluginFixes = <plugin.AnalysisErrorFixes>[];
+ final responses =
+ await waitForResponses(pluginFutures, requestParameters: requestParams);
+
+ for (final response in responses) {
+ final result = plugin.EditGetFixesResult.fromResponse(response);
+ pluginFixes.addAll(result.fixes);
+ }
+
+ return pluginFixes;
+ }
+
Future<List<Either2<Command, CodeAction>>> _getRefactorActions(
bool Function(CodeActionKind) shouldIncludeKind,
bool supportsLiteralCodeActions,
@@ -428,6 +546,28 @@
}
}
+ // Converts/Rewrites
+ if (shouldIncludeKind(CodeActionKind.RefactorRewrite)) {
+ final node = NodeLocator(offset).searchWithin(unit.unit);
+ final element = server.getElementOfNode(node);
+ // Getter to Method
+ if (element is PropertyAccessorElement) {
+ refactorActions.add(createRefactor(
+ CodeActionKind.RefactorRewrite,
+ 'Convert Getter to Method',
+ RefactoringKind.CONVERT_GETTER_TO_METHOD));
+ }
+
+ // Method to Getter
+ if (element is ExecutableElement &&
+ element is! PropertyAccessorElement) {
+ refactorActions.add(createRefactor(
+ CodeActionKind.RefactorRewrite,
+ 'Convert Method to Getter',
+ RefactoringKind.CONVERT_METHOD_TO_GETTER));
+ }
+ }
+
return refactorActions;
} on InconsistentAnalysisException {
// If an InconsistentAnalysisException occurs, it's likely the user modified
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
index ccf8bb2..2ab3d5d 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
@@ -205,7 +205,7 @@
) async {
final performance = CompletionPerformance();
performance.path = unit.path;
- performance.setContentsAndOffset(unit.content!, offset);
+ performance.setContentsAndOffset(unit.content, offset);
server.performanceStats.completion.add(performance);
return await performance.runRequestOperation((perf) async {
@@ -261,7 +261,7 @@
/// insert dupes.
final completeFunctionCalls = _hasExistingArgList(target.entity)
? false
- : server.clientConfiguration.completeFunctionCalls;
+ : server.clientConfiguration.global.completeFunctionCalls;
final results = serverSuggestions.map(
(item) {
@@ -292,7 +292,7 @@
// depending on how the spec is updated.
// https://github.com/microsoft/vscode-languageserver-node/issues/673
includeCommitCharacters:
- server.clientConfiguration.previewCommitCharacters,
+ server.clientConfiguration.global.previewCommitCharacters,
completeFunctionCalls: completeFunctionCalls,
);
},
@@ -374,7 +374,7 @@
importingUris.first == '${library.uri}';
}).map((item) => declarationToCompletionItem(
capabilities,
- unit.path!,
+ unit.path,
offset,
includedSet,
library,
@@ -390,8 +390,8 @@
// this should be removed (or made conditional based on a capability)
// depending on how the spec is updated.
// https://github.com/microsoft/vscode-languageserver-node/issues/673
- includeCommitCharacters:
- server.clientConfiguration.previewCommitCharacters,
+ includeCommitCharacters: server
+ .clientConfiguration.global.previewCommitCharacters,
completeFunctionCalls: completeFunctionCalls,
));
results.addAll(setResults);
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion_resolve.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion_resolve.dart
index 1463107..30935d6 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion_resolve.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion_resolve.dart
@@ -111,7 +111,7 @@
analyzer.LibraryElement requestedLibraryElement;
{
- final result = await session.getLibraryByUri2(library.uriStr);
+ final result = await session.getLibraryByUri(library.uriStr);
if (result is LibraryElementResult) {
requestedLibraryElement = result.element;
} else {
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_document_highlights.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_document_highlights.dart
index ff213a4..ae96228 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_document_highlights.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_document_highlights.dart
@@ -34,7 +34,7 @@
return offset.mapResult((requestedOffset) {
final collector = OccurrencesCollectorImpl();
- addDartOccurrences(collector, unit.result.unit!);
+ addDartOccurrences(collector, unit.result.unit);
// Find an occurrence that has an instance that spans the position.
for (final occurrence in collector.allOccurrences) {
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_format_on_type.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_format_on_type.dart
index 1ed3a71..3148284 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_format_on_type.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_format_on_type.dart
@@ -32,8 +32,8 @@
return success(null);
}
- return generateEditsForFormatting(
- result, server.clientConfiguration.lineLength);
+ final lineLength = server.clientConfiguration.forResource(path).lineLength;
+ return generateEditsForFormatting(result, lineLength);
}
@override
@@ -43,12 +43,15 @@
return success(null);
}
- if (!server.clientConfiguration.enableSdkFormatter) {
- return error(ServerErrorCodes.FeatureDisabled,
- 'Formatter was disabled by client settings');
- }
-
final path = pathOfDoc(params.textDocument);
- return path.mapResult((path) => formatFile(path));
+ return path.mapResult((path) {
+ if (!server.clientConfiguration.forResource(path).enableSdkFormatter) {
+ // Because we now support formatting for just some WorkspaceFolders
+ // we should silently do nothing for those that are disabled.
+ return success(null);
+ }
+
+ return formatFile(path);
+ });
}
}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_format_range.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_format_range.dart
index d6f7247..f92433a 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_format_range.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_format_range.dart
@@ -32,9 +32,8 @@
return success(null);
}
- return generateEditsForFormatting(
- result, server.clientConfiguration.lineLength,
- range: range);
+ final lineLength = server.clientConfiguration.forResource(path).lineLength;
+ return generateEditsForFormatting(result, lineLength, range: range);
}
@override
@@ -44,12 +43,14 @@
return success(null);
}
- if (!server.clientConfiguration.enableSdkFormatter) {
- return error(ServerErrorCodes.FeatureDisabled,
- 'Formatter was disabled by client settings');
- }
-
final path = pathOfDoc(params.textDocument);
- return path.mapResult((path) => formatRange(path, params.range));
+ return path.mapResult((path) {
+ if (!server.clientConfiguration.forResource(path).enableSdkFormatter) {
+ // Because we now support formatting for just some WorkspaceFolders
+ // we should silently do nothing for those that are disabled.
+ return success(null);
+ }
+ return formatRange(path, params.range);
+ });
}
}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_formatting.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_formatting.dart
index 75b7a41..23a7cad 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_formatting.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_formatting.dart
@@ -32,8 +32,8 @@
return success(null);
}
- return generateEditsForFormatting(
- result, server.clientConfiguration.lineLength);
+ final lineLength = server.clientConfiguration.forResource(path).lineLength;
+ return generateEditsForFormatting(result, lineLength);
}
@override
@@ -43,12 +43,14 @@
return success(null);
}
- if (!server.clientConfiguration.enableSdkFormatter) {
- return error(ServerErrorCodes.FeatureDisabled,
- 'Formatter was disabled by client settings');
- }
-
final path = pathOfDoc(params.textDocument);
- return path.mapResult((path) => formatFile(path));
+ return path.mapResult((path) {
+ if (!server.clientConfiguration.forResource(path).enableSdkFormatter) {
+ // Because we now support formatting for just some WorkspaceFolders
+ // we should silently do nothing for those that are disabled.
+ return success(null);
+ }
+ return formatFile(path);
+ });
}
}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_hover.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_hover.dart
index c533db2..1195c9b 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_hover.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_hover.dart
@@ -83,10 +83,6 @@
ErrorOr<Hover?> _getHover(ResolvedUnitResult unit, int offset) {
final compilationUnit = unit.unit;
- if (compilationUnit == null) {
- return success(null);
- }
-
final computer = DartUnitHoverComputer(
server.getDartdocDirectiveInfoFor(unit), compilationUnit, offset);
final hover = computer.compute();
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_initialized.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_initialized.dart
index d842bbb..b0e3ca3 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_initialized.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_initialized.dart
@@ -28,10 +28,8 @@
server,
);
- await server.fetchClientConfigurationAndPerformDynamicRegistration();
-
if (!server.initializationOptions.onlyAnalyzeProjectsWithOpenFiles) {
- server.updateWorkspaceFolders(openWorkspacePaths, const []);
+ await server.updateWorkspaceFolders(openWorkspacePaths, const []);
}
return success(null);
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_references.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_references.dart
index b302227..93c78da 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_references.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_references.dart
@@ -83,7 +83,7 @@
convert(results, toLocation).whereNotNull().toList();
final compilationUnit = unit.unit;
- if (compilationUnit != null && params.context.includeDeclaration == true) {
+ if (params.context.includeDeclaration == true) {
// Also include the definition for the symbol at this location.
referenceResults.addAll(_getDeclarations(compilationUnit, offset));
}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_signature_help.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_signature_help.dart
index 34f4193..25a78ca 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_signature_help.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_signature_help.dart
@@ -62,7 +62,7 @@
// signature help for that.
final typeArgsSignature = _tryGetTypeArgsSignatureHelp(
dartDocInfo,
- unit.result.unit!,
+ unit.result.unit,
offset,
autoTriggered,
formats,
@@ -72,7 +72,7 @@
}
final computer =
- DartUnitSignatureComputer(dartDocInfo, unit.result.unit!, offset);
+ DartUnitSignatureComputer(dartDocInfo, unit.result.unit, offset);
if (!computer.offsetIsValid) {
return success(null); // No error, just no valid hover.
}
diff --git a/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart b/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
index ab57310..2dcd219 100644
--- a/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
+++ b/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
@@ -35,6 +35,7 @@
import 'package:analysis_server/src/services/completion/completion_performance.dart'
show CompletionPerformance;
import 'package:analysis_server/src/services/refactoring/refactoring.dart';
+import 'package:analysis_server/src/utilities/process.dart';
import 'package:analyzer/dart/analysis/context_locator.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/error/error.dart';
@@ -126,6 +127,7 @@
CrashReportingAttachmentsBuilder crashReportingAttachmentsBuilder,
InstrumentationService instrumentationService, {
http.Client? httpClient,
+ ProcessRunner? processRunner,
DiagnosticServer? diagnosticServer,
// Disable to avoid using this in unit tests.
bool enableBazelWatcher = false,
@@ -137,6 +139,7 @@
baseResourceProvider,
instrumentationService,
httpClient,
+ processRunner,
LspNotificationManager(channel, baseResourceProvider.pathContext),
enableBazelWatcher: enableBazelWatcher,
) {
@@ -184,10 +187,10 @@
RefactoringWorkspace(driverMap.values, searchEngine);
void addPriorityFile(String filePath) {
- // When a pubspec is opened, trigger package name caching for completion.
- if (!pubPackageService.isRunning &&
- file_paths.isPubspecYaml(resourceProvider.pathContext, filePath)) {
- pubPackageService.beginPackageNamePreload();
+ // When pubspecs are opened, trigger pre-loading of pub package names and
+ // versions.
+ if (file_paths.isPubspecYaml(resourceProvider.pathContext, filePath)) {
+ pubPackageService.beginCachePreloads([filePath]);
}
final didAdd = priorityFiles.add(filePath);
@@ -205,33 +208,49 @@
/// register/unregister requests for any supported/enabled dynamic registrations.
Future<void> fetchClientConfigurationAndPerformDynamicRegistration() async {
if (clientCapabilities?.configuration ?? false) {
+ // Take a copy of workspace folders because we need to match up the
+ // responses to the request by index and it's possible _workspaceFolders
+ // will change after we sent the request but before we get the response.
+ final folders = _workspaceFolders.toList();
+
// Fetch all configuration we care about from the client. This is just
// "dart" for now, but in future this may be extended to include
// others (for example "flutter").
final response = await sendRequest(
Method.workspace_configuration,
ConfigurationParams(items: [
+ // Dart settings for each workspace folder.
+ for (final folder in folders)
+ ConfigurationItem(
+ scopeUri: Uri.file(folder).toString(),
+ section: 'dart',
+ ),
+ // Global Dart settings. This comes last to simplify matching up the
+ // indexes in the results (folder[i] is the i'th item).
ConfigurationItem(section: 'dart'),
]));
final result = response.result;
- // Expect the result to be a single list (to match the single
- // ConfigurationItem we requested above) and that it should be
- // a standard map of settings.
+ // Expect the result to be a list with 1 + folders.length items to
+ // match the request above, and each should be a standard map of settings.
// If the above code is extended to support multiple sets of config
- // this will need tweaking to handle each group appropriately.
+ // this will need tweaking to handle the item for each section.
if (result != null &&
result is List<dynamic> &&
- result.length == 1 &&
- result.first is Map<String, dynamic>) {
- final newConfig = result.first;
- final refreshRoots =
- clientConfiguration.affectsAnalysisRoots(newConfig);
+ result.length == 1 + folders.length) {
+ // Config is stored as a map keyed by the workspace folder, and a key of
+ // null for the global config
+ final workspaceFolderConfig = {
+ for (var i = 0; i < folders.length; i++)
+ folders[i]: result[i] as Map<String, Object?>? ?? {},
+ };
+ final newGlobalConfig = result.last as Map<String, Object?>? ?? {};
- clientConfiguration.replace(newConfig);
+ final oldGlobalConfig = clientConfiguration.global;
+ clientConfiguration.replace(newGlobalConfig, workspaceFolderConfig);
- if (refreshRoots) {
+ if (clientConfiguration.affectsAnalysisRoots(oldGlobalConfig)) {
_refreshAnalysisRoots();
}
}
@@ -638,14 +657,16 @@
sendServerErrorNotification('Socket error', error, stack);
}
- void updateWorkspaceFolders(
- List<String> addedPaths, List<String> removedPaths) {
+ Future<void> updateWorkspaceFolders(
+ List<String> addedPaths, List<String> removedPaths) async {
// TODO(dantup): This is currently case-sensitive!
_workspaceFolders
..addAll(addedPaths)
..removeAll(removedPaths);
+ await fetchClientConfigurationAndPerformDynamicRegistration();
+
_refreshAnalysisRoots();
}
@@ -699,7 +720,7 @@
? _workspaceFolders.toSet()
: _getRootsForOpenFiles();
- final excludedPaths = clientConfiguration.analysisExcludedFolders
+ final excludedPaths = clientConfiguration.global.analysisExcludedFolders
.expand((excludePath) => resourceProvider.pathContext
.isAbsolute(excludePath)
? [excludePath]
@@ -825,42 +846,8 @@
}
analysisDriver.results.listen((result) {
- var path = result.path;
- if (path == null) {
- // This shouldn't occur - result.path is marked with a TODO to become
- // non-nullable.
- return;
- }
- filesToFlush.add(path);
- if (analysisServer.isAnalyzed(path)) {
- final serverErrors = protocol.doAnalysisError_listFromEngine(result);
- recordAnalysisErrors(path, serverErrors);
- }
- analysisServer.getDocumentationCacheFor(result)?.cacheFromResult(result);
- analysisServer.getExtensionCacheFor(result)?.cacheFromResult(result);
- final unit = result.unit;
- if (unit != null) {
- if (analysisServer.shouldSendClosingLabelsFor(path)) {
- final labels = DartUnitClosingLabelsComputer(result.lineInfo, unit)
- .compute()
- .map((l) => toClosingLabel(result.lineInfo, l))
- .toList();
-
- analysisServer.publishClosingLabels(path, labels);
- }
- if (analysisServer.shouldSendOutlineFor(path)) {
- final outline = DartUnitOutlineComputer(
- result,
- withBasicFlutter: true,
- ).compute();
- final lspOutline = toOutline(result.lineInfo, outline);
- analysisServer.publishOutline(path, lspOutline);
- }
- if (analysisServer.shouldSendFlutterOutlineFor(path)) {
- final outline = FlutterOutlineComputer(result).compute();
- final lspOutline = toFlutterOutline(result.lineInfo, outline);
- analysisServer.publishFlutterOutline(path, lspOutline);
- }
+ if (result is FileResult) {
+ _handleFileResult(result);
}
});
analysisDriver.exceptions.listen(analysisServer.logExceptionResult);
@@ -868,6 +855,18 @@
}
@override
+ void pubspecChanged(String pubspecPath) {
+ analysisServer.pubPackageService.fetchPackageVersionsViaPubOutdated(
+ pubspecPath,
+ pubspecWasModified: true);
+ }
+
+ @override
+ void pubspecRemoved(String pubspecPath) {
+ analysisServer.pubPackageService.flushPackageCaches(pubspecPath);
+ }
+
+ @override
void recordAnalysisErrors(String path, List<protocol.AnalysisError> errors) {
final errorsToSend = errors.where(_shouldSendError).toList();
filesToFlush.add(path);
@@ -875,7 +874,53 @@
.recordAnalysisErrors(NotificationManager.serverId, path, errorsToSend);
}
+ void _handleFileResult(FileResult result) {
+ var path = result.path;
+ filesToFlush.add(path);
+
+ if (result is AnalysisResultWithErrors) {
+ if (analysisServer.isAnalyzed(path)) {
+ final serverErrors = protocol.doAnalysisError_listFromEngine(result);
+ recordAnalysisErrors(path, serverErrors);
+ }
+ }
+
+ if (result is ResolvedUnitResult) {
+ _handleResolvedUnitResult(result);
+ }
+ }
+
+ void _handleResolvedUnitResult(ResolvedUnitResult result) {
+ var path = result.path;
+
+ analysisServer.getDocumentationCacheFor(result)?.cacheFromResult(result);
+ analysisServer.getExtensionCacheFor(result)?.cacheFromResult(result);
+
+ final unit = result.unit;
+ if (analysisServer.shouldSendClosingLabelsFor(path)) {
+ final labels = DartUnitClosingLabelsComputer(result.lineInfo, unit)
+ .compute()
+ .map((l) => toClosingLabel(result.lineInfo, l))
+ .toList();
+
+ analysisServer.publishClosingLabels(path, labels);
+ }
+ if (analysisServer.shouldSendOutlineFor(path)) {
+ final outline = DartUnitOutlineComputer(
+ result,
+ withBasicFlutter: true,
+ ).compute();
+ final lspOutline = toOutline(result.lineInfo, outline);
+ analysisServer.publishOutline(path, lspOutline);
+ }
+ if (analysisServer.shouldSendFlutterOutlineFor(path)) {
+ final outline = FlutterOutlineComputer(result).compute();
+ final lspOutline = toFlutterOutline(result.lineInfo, outline);
+ analysisServer.publishFlutterOutline(path, lspOutline);
+ }
+ }
+
bool _shouldSendError(protocol.AnalysisError error) =>
error.code != ErrorType.TODO.name.toLowerCase() ||
- analysisServer.clientConfiguration.showTodos;
+ analysisServer.clientConfiguration.global.showTodos;
}
diff --git a/pkg/analysis_server/lib/src/lsp/mapping.dart b/pkg/analysis_server/lib/src/lsp/mapping.dart
index 429920f..da9bb2a 100644
--- a/pkg/analysis_server/lib/src/lsp/mapping.dart
+++ b/pkg/analysis_server/lib/src/lsp/mapping.dart
@@ -49,6 +49,15 @@
],
};
+/// Pattern for docComplete text on completion items that can be upgraded to
+/// the "detail" field so that it can be shown more prominently by clients.
+///
+/// This is typically used for labels like _latest compatible_ and _latest_ in
+/// the pubspec version items. These go into docComplete so that they appear
+/// reasonably for non-LSP clients where there is no equivalent of the detail
+/// field.
+final _upgradableDocCompletePattern = RegExp(r'^_([\w ]{0,20})_$');
+
lsp.Either2<String, lsp.MarkupContent> asStringOrMarkupContent(
Set<lsp.MarkupKind>? preferredFormats, String content) {
return preferredFormats == null
@@ -866,19 +875,30 @@
range: toRange(lineInfo, label.offset, label.length),
label: label.label);
-lsp.CodeActionKind toCodeActionKind(String? id, lsp.CodeActionKind fallback) {
+/// Converts [id] to a [CodeActionKind] using [fallbackOrPrefix] as a fallback
+/// or a prefix if the ID is not already a fix/refactor.
+lsp.CodeActionKind toCodeActionKind(
+ String? id, lsp.CodeActionKind fallbackOrPrefix) {
if (id == null) {
- return fallback;
+ return fallbackOrPrefix;
}
// Dart fixes and assists start with "dart.assist." and "dart.fix." but in LSP
// we want to use the predefined prefixes for CodeActions.
- final newId = id
+ var newId = id
.replaceAll('dart.assist', lsp.CodeActionKind.Refactor.toString())
.replaceAll('dart.fix', lsp.CodeActionKind.QuickFix.toString())
.replaceAll(
'analysisOptions.assist', lsp.CodeActionKind.Refactor.toString())
.replaceAll(
'analysisOptions.fix', lsp.CodeActionKind.QuickFix.toString());
+
+ // If the ID does not start with either of the kinds above, prefix it as
+ // it will be an unqualified ID from a plugin.
+ if (!newId.startsWith(lsp.CodeActionKind.Refactor.toString()) &&
+ !newId.startsWith(lsp.CodeActionKind.QuickFix.toString())) {
+ newId = '$fallbackOrPrefix.$newId';
+ }
+
return lsp.CodeActionKind(newId);
}
@@ -956,7 +976,21 @@
final insertText = insertTextInfo.first;
final insertTextFormat = insertTextInfo.last;
final isMultilineCompletion = insertText.contains('\n');
- final cleanedDoc = cleanDartdoc(suggestion.docComplete);
+
+ var cleanedDoc = cleanDartdoc(suggestion.docComplete);
+ var detail = getCompletionDetail(suggestion, completionKind,
+ supportsCompletionDeprecatedFlag || supportsDeprecatedTag);
+
+ // To improve the display of some items (like pubspec version numbers),
+ // short labels in the format `_foo_` in docComplete are "upgraded" to the
+ // detail field.
+ final labelMatch = cleanedDoc != null
+ ? _upgradableDocCompletePattern.firstMatch(cleanedDoc)
+ : null;
+ if (labelMatch != null) {
+ cleanedDoc = null;
+ detail = labelMatch.group(1);
+ }
// Because we potentially send thousands of these items, we should minimise
// the generated JSON as much as possible - for example using nulls in place
@@ -971,8 +1005,7 @@
commitCharacters:
includeCommitCharacters ? dartCompletionCommitCharacters : null,
data: resolutionData,
- detail: getCompletionDetail(suggestion, completionKind,
- supportsCompletionDeprecatedFlag || supportsDeprecatedTag),
+ detail: detail,
documentation: cleanedDoc != null
? asStringOrMarkupContent(formats, cleanedDoc)
: null,
diff --git a/pkg/analysis_server/lib/src/lsp/server_capabilities_computer.dart b/pkg/analysis_server/lib/src/lsp/server_capabilities_computer.dart
index ca0b352..89f26d4 100644
--- a/pkg/analysis_server/lib/src/lsp/server_capabilities_computer.dart
+++ b/pkg/analysis_server/lib/src/lsp/server_capabilities_computer.dart
@@ -136,9 +136,10 @@
LspClientCapabilities clientCapabilities) {
final codeActionLiteralSupport = clientCapabilities.literalCodeActions;
final renameOptionsSupport = clientCapabilities.renameValidation;
- final enableFormatter = _server.clientConfiguration.enableSdkFormatter;
+ final enableFormatter =
+ _server.clientConfiguration.global.enableSdkFormatter;
final previewCommitCharacters =
- _server.clientConfiguration.previewCommitCharacters;
+ _server.clientConfiguration.global.previewCommitCharacters;
final dynamicRegistrations =
ClientDynamicRegistrations(clientCapabilities.raw);
@@ -321,9 +322,10 @@
final registrations = <Registration>[];
- final enableFormatter = _server.clientConfiguration.enableSdkFormatter;
+ final enableFormatter =
+ _server.clientConfiguration.global.enableSdkFormatter;
final previewCommitCharacters =
- _server.clientConfiguration.previewCommitCharacters;
+ _server.clientConfiguration.global.previewCommitCharacters;
/// Helper for creating registrations with IDs.
void register(bool condition, Method method, [ToJsonable? options]) {
diff --git a/pkg/analysis_server/lib/src/operation/operation_analysis.dart b/pkg/analysis_server/lib/src/operation/operation_analysis.dart
index 05538df..94f0005 100644
--- a/pkg/analysis_server/lib/src/operation/operation_analysis.dart
+++ b/pkg/analysis_server/lib/src/operation/operation_analysis.dart
@@ -94,7 +94,7 @@
AnalysisServer server, ResolvedUnitResult resolvedUnit) {
_sendNotification(server, () {
protocol.FileKind fileKind;
- var unit = resolvedUnit.unit!;
+ var unit = resolvedUnit.unit;
if (unit.directives.any((d) => d is PartOfDirective)) {
fileKind = protocol.FileKind.PART;
} else {
@@ -112,7 +112,7 @@
// send notification
var params = protocol.AnalysisOutlineParams(
- resolvedUnit.path!, fileKind, outline,
+ resolvedUnit.path, fileKind, outline,
libraryName: libraryName);
server.sendNotification(params.toNotification());
});
diff --git a/pkg/analysis_server/lib/src/protocol_server.dart b/pkg/analysis_server/lib/src/protocol_server.dart
index c03f74b..7ad36bd 100644
--- a/pkg/analysis_server/lib/src/protocol_server.dart
+++ b/pkg/analysis_server/lib/src/protocol_server.dart
@@ -27,7 +27,7 @@
/// Returns a list of AnalysisErrors corresponding to the given list of Engine
/// errors.
List<AnalysisError> doAnalysisError_listFromEngine(
- engine.ResolvedUnitResult result) {
+ engine.AnalysisResultWithErrors result) {
return mapEngineErrors(result, result.errors, newAnalysisError_fromEngine);
}
@@ -79,9 +79,10 @@
/// Translates engine errors through the ErrorProcessor.
List<T> mapEngineErrors<T>(
- engine.ResolvedUnitResult result,
+ engine.AnalysisResultWithErrors result,
List<engine.AnalysisError> errors,
- T Function(engine.ResolvedUnitResult result, engine.AnalysisError error,
+ T Function(
+ engine.AnalysisResultWithErrors result, engine.AnalysisError error,
[engine.ErrorSeverity errorSeverity])
constructor) {
var analysisOptions = result.session.analysisContext.analysisOptions;
@@ -106,7 +107,7 @@
///
/// If an [errorSeverity] is specified, it will override the one in [error].
AnalysisError newAnalysisError_fromEngine(
- engine.ResolvedUnitResult result, engine.AnalysisError error,
+ engine.AnalysisResultWithErrors result, engine.AnalysisError error,
[engine.ErrorSeverity? errorSeverity]) {
var errorCode = error.errorCode;
// prepare location
@@ -125,8 +126,8 @@
var endLine = endLocation.lineNumber;
var endColumn = endLocation.columnNumber;
- location = Location(
- file, offset, length, startLine, startColumn, endLine, endColumn);
+ location = Location(file, offset, length, startLine, startColumn,
+ endLine: endLine, endColumn: endColumn);
}
// Default to the error's severity if none is specified.
@@ -155,7 +156,7 @@
/// Create a DiagnosticMessage based on an [engine.DiagnosticMessage].
DiagnosticMessage newDiagnosticMessage(
- engine.ResolvedUnitResult result, engine.DiagnosticMessage message) {
+ engine.AnalysisResultWithErrors result, engine.DiagnosticMessage message) {
var file = message.filePath;
var offset = message.offset;
var length = message.length;
@@ -170,8 +171,8 @@
return DiagnosticMessage(
message.messageText(includeUrl: true),
- Location(
- file, offset, length, startLine, startColumn, endLine, endColumn));
+ Location(file, offset, length, startLine, startColumn,
+ endLine: endLine, endColumn: endColumn));
}
/// Create a Location based on an [engine.Element].
@@ -316,5 +317,6 @@
// should be able to throw an exception. Try removing the try statement.
}
return Location(unitElement.source.fullName, range.offset, range.length,
- startLine, startColumn, endLine, endColumn);
+ startLine, startColumn,
+ endLine: endLine, endColumn: endColumn);
}
diff --git a/pkg/analysis_server/lib/src/services/completion/completion_core.dart b/pkg/analysis_server/lib/src/services/completion/completion_core.dart
index 2c71a1e..d6fe971 100644
--- a/pkg/analysis_server/lib/src/services/completion/completion_core.dart
+++ b/pkg/analysis_server/lib/src/services/completion/completion_core.dart
@@ -44,7 +44,7 @@
ResourceProvider get resourceProvider => result.session.resourceProvider;
@override
- Source get source => result.unit!.declaredElement!.source;
+ Source get source => result.unit.declaredElement!.source;
@override
String? get sourceContents => result.content;
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
index fce6916..b71fa3e 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
@@ -100,7 +100,7 @@
}) async {
request.checkAborted();
var pathContext = request.resourceProvider.pathContext;
- if (!file_paths.isDart(pathContext, request.result.path!)) {
+ if (!file_paths.isDart(pathContext, request.result.path)) {
return const <CompletionSuggestion>[];
}
@@ -458,7 +458,7 @@
return performance.run(
'build DartCompletionRequest',
(_) {
- var unit = request.result.unit!;
+ var unit = request.result.unit;
var libSource = unit.declaredElement!.library.source;
var objectType = request.result.typeProvider.objectType;
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/documentation_cache.dart b/pkg/analysis_server/lib/src/services/completion/dart/documentation_cache.dart
index 4457f2e..0ca62d6 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/documentation_cache.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/documentation_cache.dart
@@ -29,7 +29,7 @@
/// Fill the cache with data from the [result].
void cacheFromResult(ResolvedUnitResult result) {
- var compilationUnit = result.unit?.declaredElement;
+ var compilationUnit = result.unit.declaredElement;
if (compilationUnit != null) {
documentationCache.remove(_keyForUnit(compilationUnit));
_cacheFromElement(compilationUnit);
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/extension_cache.dart b/pkg/analysis_server/lib/src/services/completion/dart/extension_cache.dart
index 96decc0..38481dc 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/extension_cache.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/extension_cache.dart
@@ -21,7 +21,7 @@
/// Fill the cache with data from the [result].
void cacheFromResult(ResolvedUnitResult result) {
- var element = result.unit?.declaredElement;
+ var element = result.unit.declaredElement;
if (element != null) {
_cacheFromElement(element);
for (var library in result.libraryElement.importedLibraries) {
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/local_library_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/local_library_contributor.dart
index c767698..f14d554 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/local_library_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/local_library_contributor.dart
@@ -158,7 +158,7 @@
return;
}
- var libraryUnits = request.result.unit?.declaredElement?.library.units;
+ var libraryUnits = request.result.unit.declaredElement?.library.units;
if (libraryUnits == null) {
return;
}
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart b/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
index 467c954..9bcd314 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
@@ -704,7 +704,7 @@
ExecutableElement element, bool invokeSuper) async {
var displayTextBuffer = StringBuffer();
var builder = ChangeBuilder(session: request.result.session);
- await builder.addDartFileEdit(request.result.path!, (builder) {
+ await builder.addDartFileEdit(request.result.path, (builder) {
builder.addReplacement(range.node(targetId), (builder) {
builder.writeOverride(
element,
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart b/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart
index d045443..26a1a94 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart
@@ -158,7 +158,8 @@
bool isDeprecated = false}) {
var name = id.name;
// TODO(danrubel) use lineInfo to determine startLine and startColumn
- var location = Location(source.fullName, id.offset, id.length, 0, 0, 0, 0);
+ var location = Location(source.fullName, id.offset, id.length, 0, 0,
+ endLine: 0, endColumn: 0);
var flags = protocol.Element.makeFlags(
isAbstract: isAbstract,
isDeprecated: isDeprecated,
@@ -194,7 +195,7 @@
}
String getRequestLineIndent(DartCompletionRequest request) {
- var content = request.result.content!;
+ var content = request.result.content;
var lineStartOffset = request.offset;
var notWhitespaceOffset = request.offset;
for (; lineStartOffset > 0; lineStartOffset--) {
diff --git a/pkg/analysis_server/lib/src/services/completion/postfix/postfix_completion.dart b/pkg/analysis_server/lib/src/services/completion/postfix/postfix_completion.dart
index 8aa88e2..988a42d 100644
--- a/pkg/analysis_server/lib/src/services/completion/postfix/postfix_completion.dart
+++ b/pkg/analysis_server/lib/src/services/completion/postfix/postfix_completion.dart
@@ -264,7 +264,7 @@
String get eol => utils.endOfLine;
- String get file => completionContext.resolveResult.path!;
+ String get file => completionContext.resolveResult.path;
String get key => completionContext.key;
diff --git a/pkg/analysis_server/lib/src/services/completion/statement/statement_completion.dart b/pkg/analysis_server/lib/src/services/completion/statement/statement_completion.dart
index 9bd0039..e337213 100644
--- a/pkg/analysis_server/lib/src/services/completion/statement/statement_completion.dart
+++ b/pkg/analysis_server/lib/src/services/completion/statement/statement_completion.dart
@@ -120,7 +120,7 @@
String get eol => utils.endOfLine;
- String get file => statementContext.resolveResult.path!;
+ String get file => statementContext.resolveResult.path;
LineInfo get lineInfo => statementContext.resolveResult.lineInfo;
@@ -128,7 +128,7 @@
Source get source => unitElement.source;
- CompilationUnit get unit => statementContext.resolveResult.unit!;
+ CompilationUnit get unit => statementContext.resolveResult.unit;
CompilationUnitElement get unitElement => unit.declaredElement!;
diff --git a/pkg/analysis_server/lib/src/services/completion/yaml/analysis_options_generator.dart b/pkg/analysis_server/lib/src/services/completion/yaml/analysis_options_generator.dart
index 7f60edd..bd175b9 100644
--- a/pkg/analysis_server/lib/src/services/completion/yaml/analysis_options_generator.dart
+++ b/pkg/analysis_server/lib/src/services/completion/yaml/analysis_options_generator.dart
@@ -30,6 +30,7 @@
AnalyzerOptions.chromeOsManifestChecks: EmptyProducer(),
}),
AnalyzerOptions.plugins: EmptyProducer(),
+ AnalyzerOptions.propagateLinterExceptions: EmptyProducer(),
AnalyzerOptions.strong_mode: MapProducer({
AnalyzerOptions.declarationCasts: EmptyProducer(),
AnalyzerOptions.implicitCasts: EmptyProducer(),
diff --git a/pkg/analysis_server/lib/src/services/completion/yaml/producer.dart b/pkg/analysis_server/lib/src/services/completion/yaml/producer.dart
index 960346f..5d7f681 100644
--- a/pkg/analysis_server/lib/src/services/completion/yaml/producer.dart
+++ b/pkg/analysis_server/lib/src/services/completion/yaml/producer.dart
@@ -176,9 +176,11 @@
const Producer();
/// A utility method used to create a suggestion for the [identifier].
- CompletionSuggestion identifier(String identifier, {int relevance = 1000}) =>
+ CompletionSuggestion identifier(String identifier,
+ {int relevance = 1000, String? docComplete}) =>
CompletionSuggestion(CompletionSuggestionKind.IDENTIFIER, relevance,
- identifier, identifier.length, 0, false, false);
+ identifier, identifier.length, 0, false, false,
+ docComplete: docComplete);
/// A utility method used to create a suggestion for the package [packageName].
CompletionSuggestion packageName(String packageName,
diff --git a/pkg/analysis_server/lib/src/services/completion/yaml/pubspec_generator.dart b/pkg/analysis_server/lib/src/services/completion/yaml/pubspec_generator.dart
index 724bb6f..a34d791 100644
--- a/pkg/analysis_server/lib/src/services/completion/yaml/pubspec_generator.dart
+++ b/pkg/analysis_server/lib/src/services/completion/yaml/pubspec_generator.dart
@@ -37,18 +37,25 @@
@override
Iterable<CompletionSuggestion> suggestions(
YamlCompletionRequest request) sync* {
- // TOOD(dantup): Consider supporting async completion requests so this
- // could call packageDetails() (with a short timeout, and pub retries
- // disabled). A user that explicitly invokes completion in the location
- // of a version may be prepared to wait a short period for a web request
- // to get completion versions (this is also the only way for non-LSP
- // clients to get them, since there are no resolve calls).
+ final versions = request.pubPackageService
+ ?.cachedPubOutdatedVersions(request.filePath, package);
+ final resolvable = versions?.resolvableVersion;
+ var latest = versions?.latestVersion;
+
+ // If we didn't get a latest version from the "pub outdated" results, we can
+ // use the result from the Pub API if we've called it (this will usually
+ // only be the case for LSP where a resolve() call was sent).
//
- // Supporting this will require making the completion async further up.
- final details = request.pubPackageService?.cachedPackageDetails(package);
- final version = details?.latestVersion;
- if (version != null) {
- yield identifier('^$version');
+ // This allows us (in some cases) to still show version numbers even if the
+ // package was newly added to pubspec and not saved, so not yet in the
+ // "pub outdated" results.
+ latest ??= request.pubPackageService?.cachedPubApiLatestVersion(package);
+
+ if (resolvable != null && resolvable != latest) {
+ yield identifier('^$resolvable', docComplete: '_latest compatible_');
+ }
+ if (latest != null) {
+ yield identifier('^$latest', docComplete: '_latest_');
}
}
}
diff --git a/pkg/analysis_server/lib/src/services/correction/base_processor.dart b/pkg/analysis_server/lib/src/services/correction/base_processor.dart
index 543d8c9..fb8a04f 100644
--- a/pkg/analysis_server/lib/src/services/correction/base_processor.dart
+++ b/pkg/analysis_server/lib/src/services/correction/base_processor.dart
@@ -33,7 +33,7 @@
this.selectionLength = 0,
required this.resolvedResult,
required this.workspace,
- }) : file = resolvedResult.path!,
+ }) : file = resolvedResult.path,
session = resolvedResult.session,
sessionHelper = AnalysisSessionHelper(resolvedResult.session),
typeProvider = resolvedResult.typeProvider,
diff --git a/pkg/analysis_server/lib/src/services/correction/bulk_fix_processor.dart b/pkg/analysis_server/lib/src/services/correction/bulk_fix_processor.dart
index b43cfbc..7313659 100644
--- a/pkg/analysis_server/lib/src/services/correction/bulk_fix_processor.dart
+++ b/pkg/analysis_server/lib/src/services/correction/bulk_fix_processor.dart
@@ -172,7 +172,7 @@
file_paths.isGenerated(path)) {
continue;
}
- var library = await context.currentSession.getResolvedLibrary2(path);
+ var library = await context.currentSession.getResolvedLibrary(path);
if (library is ResolvedLibraryResult) {
await _fixErrorsInLibrary(library);
}
@@ -182,6 +182,22 @@
return builder;
}
+ /// Return a change builder that has been used to create fixes for the
+ /// diagnostics in [file] in the given [context].
+ Future<ChangeBuilder> fixErrorsForFile(
+ AnalysisContext context, String path) async {
+ var pathContext = context.contextRoot.resourceProvider.pathContext;
+
+ if (file_paths.isDart(pathContext, path) && !file_paths.isGenerated(path)) {
+ var library = await context.currentSession.getResolvedLibrary(path);
+ if (library is ResolvedLibraryResult) {
+ await _fixErrorsInLibrary(library);
+ }
+ }
+
+ return builder;
+ }
+
/// Return a change builder that has been used to create all fixes for a
/// specific diagnostic code in the given [unit].
Future<ChangeBuilder> fixOfTypeInUnit(
@@ -269,7 +285,7 @@
/// library associated with the analysis [result].
Future<void> _fixErrorsInLibrary(ResolvedLibraryResult result) async {
var analysisOptions = result.session.analysisContext.analysisOptions;
- for (var unitResult in result.units!) {
+ for (var unitResult in result.units) {
var overrideSet = _readOverrideSet(unitResult);
for (var error in unitResult.errors) {
var processor = ErrorProcessor.getProcessor(analysisOptions, error);
@@ -336,7 +352,7 @@
await compute(producer);
var newHash = computeChangeHash();
if (newHash != oldHash) {
- changeMap.add(result.path!, code);
+ changeMap.add(result.path, code);
}
}
@@ -401,7 +417,7 @@
if (useConfigFiles) {
var provider = result.session.resourceProvider;
var context = provider.pathContext;
- var dartFileName = result.path!;
+ var dartFileName = result.path;
var configFileName = '${context.withoutExtension(dartFileName)}.config';
var configFile = provider.getFile(configFileName);
try {
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/abstract_producer.dart b/pkg/analysis_server/lib/src/services/correction/dart/abstract_producer.dart
index bc10e17..14485d2 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/abstract_producer.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/abstract_producer.dart
@@ -249,12 +249,12 @@
this.overrideSet,
this.selectionOffset = -1,
this.selectionLength = 0,
- }) : file = resolvedResult.path!,
+ }) : file = resolvedResult.path,
session = resolvedResult.session,
sessionHelper = AnalysisSessionHelper(resolvedResult.session),
typeProvider = resolvedResult.typeProvider,
selectionEnd = selectionOffset + selectionLength,
- unit = resolvedResult.unit!,
+ unit = resolvedResult.unit,
utils = CorrectionUtils(resolvedResult);
/// Return `true` if the lint with the given [name] is enabled.
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/convert_into_async_body.dart b/pkg/analysis_server/lib/src/services/correction/dart/convert_into_async_body.dart
index 1ccaff4..8a6b2c8 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/convert_into_async_body.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/convert_into_async_body.dart
@@ -17,8 +17,9 @@
var body = getEnclosingFunctionBody();
if (body == null ||
body is EmptyFunctionBody ||
- body.isAsynchronous ||
- body.isGenerator) {
+ // Do not offer a correction if there is an `async`, `async*`, `sync*`,
+ // or the fictional `sync` keyword.
+ body.keyword != null) {
return;
}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/convert_part_of_to_uri.dart b/pkg/analysis_server/lib/src/services/correction/dart/convert_part_of_to_uri.dart
index 0f22239..c841c0f 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/convert_part_of_to_uri.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/convert_part_of_to_uri.dart
@@ -27,7 +27,7 @@
}
var libraryPath = resolvedResult.libraryElement.source.fullName;
- var partPath = resolvedResult.path!;
+ var partPath = resolvedResult.path;
var relativePath = relative(libraryPath, from: dirname(partPath));
var uri = Uri.file(relativePath).toString();
var replacementRange = range.node(libraryName);
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/create_method.dart b/pkg/analysis_server/lib/src/services/correction/dart/create_method.dart
index 2f320ef..9009561 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/create_method.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/create_method.dart
@@ -154,7 +154,7 @@
// use different utils
var targetPath = targetClassElement.source.fullName;
var targetResolveResult =
- await resolvedResult.session.getResolvedUnit2(targetPath);
+ await resolvedResult.session.getResolvedUnit(targetPath);
if (targetResolveResult is! ResolvedUnitResult) {
return;
}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap.dart b/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap.dart
index 1b02c88..318a934 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap.dart
@@ -39,7 +39,7 @@
Iterable<CorrectionProducer> _wrapMultipleWidgets() sync* {
var selectionRange = SourceRange(selectionOffset, selectionLength);
var analyzer = SelectionAnalyzer(selectionRange);
- resolvedResult.unit!.accept(analyzer);
+ resolvedResult.unit.accept(analyzer);
var widgetExpressions = <Expression>[];
if (analyzer.hasSelectedNodes) {
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/import_library.dart b/pkg/analysis_server/lib/src/services/correction/dart/import_library.dart
index 69137bf..00b0dd7d 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/import_library.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/import_library.dart
@@ -450,7 +450,7 @@
@override
Future<void> compute(ChangeBuilder builder) async {
- var result = await sessionHelper.session.getLibraryByUri2(uri.toString());
+ var result = await sessionHelper.session.getLibraryByUri(uri.toString());
if (result is LibraryElementResult) {
var library = result.element;
if (library
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/organize_imports.dart b/pkg/analysis_server/lib/src/services/correction/dart/organize_imports.dart
index caca5ec..d5cf7c0 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/organize_imports.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/organize_imports.dart
@@ -25,7 +25,7 @@
@override
Future<void> compute(ChangeBuilder builder) async {
var organizer =
- ImportOrganizer(resolvedResult.content!, unit, resolvedResult.errors);
+ ImportOrganizer(resolvedResult.content, unit, resolvedResult.errors);
// todo (pq): consider restructuring organizer to allow a passed-in change
// builder
for (var edit in organizer.organize()) {
diff --git a/pkg/analysis_server/lib/src/services/correction/statement_analyzer.dart b/pkg/analysis_server/lib/src/services/correction/statement_analyzer.dart
index 9f1c68a..9a156c4 100644
--- a/pkg/analysis_server/lib/src/services/correction/statement_analyzer.dart
+++ b/pkg/analysis_server/lib/src/services/correction/statement_analyzer.dart
@@ -52,7 +52,7 @@
/// Analyze the selection, compute [status] and nodes.
void analyze() {
- resolveResult.unit!.accept(this);
+ resolveResult.unit.accept(this);
}
/// Records fatal error with given message and [Location].
@@ -73,7 +73,7 @@
{
var selectionStart = selection.offset;
var selectionEnd = selection.end;
- var commentRanges = getCommentRanges(resolveResult.unit!);
+ var commentRanges = getCommentRanges(resolveResult.unit);
for (var commentRange in commentRanges) {
if (commentRange.contains(selectionStart)) {
invalidSelection('Selection begins inside a comment.');
@@ -208,9 +208,9 @@
/// Returns `true` if there are [Token]s in the given [SourceRange].
bool _hasTokens(SourceRange range) {
- var fullText = resolveResult.content!;
+ var fullText = resolveResult.content;
var rangeText = fullText.substring(range.offset, range.end);
- return _getTokens(rangeText, resolveResult.unit!.featureSet).isNotEmpty;
+ return _getTokens(rangeText, resolveResult.unit.featureSet).isNotEmpty;
}
/// Returns `true` if [nodes] contains [node].
diff --git a/pkg/analysis_server/lib/src/services/correction/util.dart b/pkg/analysis_server/lib/src/services/correction/util.dart
index 7259632..7fc3b9f 100644
--- a/pkg/analysis_server/lib/src/services/correction/util.dart
+++ b/pkg/analysis_server/lib/src/services/correction/util.dart
@@ -37,7 +37,7 @@
LibraryElement targetLibrary, Set<Source> libraries) async {
var libraryPath = targetLibrary.source.fullName;
- var resolveResult = await session.getResolvedUnit2(libraryPath);
+ var resolveResult = await session.getResolvedUnit(libraryPath);
if (resolveResult is! ResolvedUnitResult) {
return;
}
@@ -537,9 +537,9 @@
String? _endOfLine;
CorrectionUtils(ResolvedUnitResult result)
- : unit = result.unit!,
+ : unit = result.unit,
_library = result.libraryElement,
- _buffer = result.content!;
+ _buffer = result.content;
/// Returns the EOL to use for this [CompilationUnit].
String get endOfLine {
@@ -860,14 +860,13 @@
/// used by the generated source, but not imported.
String? getTypeSource(DartType type, Set<Source> librariesToImport,
{StringBuffer? parametersBuffer}) {
- var aliasElement = type.aliasElement;
- var aliasArguments = type.aliasArguments;
- if (aliasElement != null && aliasArguments != null) {
+ var alias = type.alias;
+ if (alias != null) {
return _getTypeCodeElementArguments(
librariesToImport: librariesToImport,
- element: aliasElement,
+ element: alias.element,
isNullable: type.nullabilitySuffix == NullabilitySuffix.question,
- typeArguments: aliasArguments,
+ typeArguments: alias.typeArguments,
);
}
diff --git a/pkg/analysis_server/lib/src/services/flutter/property.dart b/pkg/analysis_server/lib/src/services/flutter/property.dart
index 11af175..2a6586d 100644
--- a/pkg/analysis_server/lib/src/services/flutter/property.dart
+++ b/pkg/analysis_server/lib/src/services/flutter/property.dart
@@ -118,7 +118,7 @@
);
}
- await builder.addDartFileEdit(resolvedUnit.path!, (builder) {
+ await builder.addDartFileEdit(resolvedUnit.path, (builder) {
_changeCode(builder, (builder) {
var expression = value.expression;
if (expression != null) {
@@ -155,7 +155,7 @@
}
var beginOffset = argumentExpression.offset;
- await builder.addDartFileEdit(resolvedUnit.path!, (builder) {
+ await builder.addDartFileEdit(resolvedUnit.path, (builder) {
builder.addDeletion(
SourceRange(beginOffset, endOffset - beginOffset),
);
@@ -559,7 +559,7 @@
var builder = ChangeBuilder(session: property.resolvedUnit.session);
- await builder.addDartFileEdit(property.resolvedUnit.path!, (builder) {
+ await builder.addDartFileEdit(property.resolvedUnit.path, (builder) {
property._changeCode(builder, (builder) {
if (leftCode == rightCode && topCode == bottomCode) {
builder.writeReference(classEdgeInsets);
@@ -659,7 +659,7 @@
String? _expressionCode(Expression? expression) {
if (expression != null) {
- var content = property.resolvedUnit.content!;
+ var content = property.resolvedUnit.content;
return content.substring(expression.offset, expression.end);
}
return null;
diff --git a/pkg/analysis_server/lib/src/services/flutter/widget_descriptions.dart b/pkg/analysis_server/lib/src/services/flutter/widget_descriptions.dart
index f38a7cc..77da5dda 100644
--- a/pkg/analysis_server/lib/src/services/flutter/widget_descriptions.dart
+++ b/pkg/analysis_server/lib/src/services/flutter/widget_descriptions.dart
@@ -336,7 +336,7 @@
String? valueExpressionCode;
if (valueExpression != null) {
- valueExpressionCode = resolvedUnit.content!.substring(
+ valueExpressionCode = resolvedUnit.content.substring(
valueExpression.offset,
valueExpression.end,
);
diff --git a/pkg/analysis_server/lib/src/services/pub/pub_command.dart b/pkg/analysis_server/lib/src/services/pub/pub_command.dart
new file mode 100644
index 0000000..a649d65
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/pub/pub_command.dart
@@ -0,0 +1,149 @@
+// 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.
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:io';
+
+import 'package:analysis_server/src/utilities/process.dart';
+import 'package:analyzer/instrumentation/service.dart';
+import 'package:path/path.dart' as path;
+
+/// A class for interacting with the `pub` command.
+///
+/// `pub` commands will be queued and not run concurrently.
+class PubCommand {
+ static const String _pubEnvironmentKey = 'PUB_ENVIRONMENT';
+ final InstrumentationService _instrumentationService;
+ late final ProcessRunner _processRunner;
+ late final String _pubPath;
+ late final String _pubEnvironmentValue;
+
+ /// Tracks the last queued command to avoid overlapping because pub does not
+ /// do its own locking when accessing the cache.
+ ///
+ /// https://github.com/dart-lang/pub/issues/1178
+ ///
+ /// This does not prevent running concurrently with commands spawned by other
+ /// tools (such as the IDE).
+ var _lastQueuedCommand = Future<void>.value();
+
+ PubCommand(this._instrumentationService, this._processRunner) {
+ _pubPath = path.join(
+ path.dirname(Platform.resolvedExecutable),
+ Platform.isWindows ? 'pub.bat' : 'pub',
+ );
+
+ // When calling the `pub` command, we must add an identifier to the
+ // PUB_ENVIRONMENT environment variable (joined with colons).
+ const _pubEnvString = 'analysis_server.pub_api';
+ final existingPubEnv = Platform.environment[_pubEnvironmentKey];
+ _pubEnvironmentValue = [
+ if (existingPubEnv?.isNotEmpty ?? false) existingPubEnv,
+ _pubEnvString,
+ ].join(':');
+ }
+
+ /// Runs `pub outdated --show-all` and returns the results.
+ ///
+ /// If any error occurs executing the command, returns an empty list.
+ Future<List<PubOutdatedPackageDetails>> outdatedVersions(
+ String pubspecPath) async {
+ final packageDirectory = path.dirname(pubspecPath);
+ final result = await _runPubJsonCommand(
+ ['outdated', '--show-all', '--json'],
+ workingDirectory: packageDirectory);
+
+ if (result == null) {
+ return [];
+ }
+
+ final packages =
+ (result['packages'] as List<dynamic>?)?.cast<Map<String, Object?>>();
+ if (packages == null) {
+ return [];
+ }
+
+ return packages
+ .map(
+ (json) => PubOutdatedPackageDetails(
+ json['package'] as String,
+ currentVersion: _version(json, 'current'),
+ latestVersion: _version(json, 'latest'),
+ resolvableVersion: _version(json, 'resolvable'),
+ upgradableVersion: _version(json, 'upgradable'),
+ ),
+ )
+ .toList();
+ }
+
+ /// Runs a pub command and decodes JSON from `stdout`.
+ ///
+ /// Returns null if:
+ /// - exit code is non-zero
+ /// - returned text cannot be decoded as JSON
+ Future<Map<String, Object?>?> _runPubJsonCommand(List<String> args,
+ {required String workingDirectory}) async {
+ // Atomically replace the lastQueuedCommand future with our own to ensure
+ // only one command waits on any previous commands future.
+ final completer = Completer<void>();
+ final lastCommand = _lastQueuedCommand;
+ _lastQueuedCommand = completer.future;
+ // And wait for that previous command to finish.
+ await lastCommand.catchError((_) {});
+
+ try {
+ final command = [_pubPath, ...args];
+
+ _instrumentationService.logInfo('Running pub command $command');
+ final result = await _processRunner.run(_pubPath, args,
+ workingDirectory: workingDirectory,
+ environment: {_pubEnvironmentKey: _pubEnvironmentValue});
+
+ if (result.exitCode != 0) {
+ _instrumentationService.logError(
+ 'pub command returned ${result.exitCode} exit code: ${result.stderr}.');
+ return null;
+ }
+
+ try {
+ final results = jsonDecode(result.stdout);
+ _instrumentationService.logInfo('pub command completed successfully');
+ return results;
+ } catch (e) {
+ _instrumentationService
+ .logError('pub command returned invalid JSON: $e.');
+ return null;
+ }
+ } catch (e) {
+ _instrumentationService.logError('pub command failed to run: $e.');
+ return null;
+ } finally {
+ completer.complete();
+ }
+ }
+
+ String? _version(Map<String, Object?> json, String type) {
+ final versionType = json[type] as Map<String, Object?>?;
+ final version =
+ versionType != null ? versionType['version'] as String? : null;
+ return version;
+ }
+}
+
+class PubOutdatedPackageDetails {
+ final String packageName;
+ final String? currentVersion;
+ final String? latestVersion;
+ final String? resolvableVersion;
+ final String? upgradableVersion;
+
+ PubOutdatedPackageDetails(
+ this.packageName, {
+ required this.currentVersion,
+ required this.latestVersion,
+ required this.resolvableVersion,
+ required this.upgradableVersion,
+ });
+}
diff --git a/pkg/analysis_server/lib/src/services/pub/pub_package_service.dart b/pkg/analysis_server/lib/src/services/pub/pub_package_service.dart
index d0990db..4b6ef3a8 100644
--- a/pkg/analysis_server/lib/src/services/pub/pub_package_service.dart
+++ b/pkg/analysis_server/lib/src/services/pub/pub_package_service.dart
@@ -6,10 +6,11 @@
import 'dart:convert';
import 'package:analysis_server/src/services/pub/pub_api.dart';
+import 'package:analysis_server/src/services/pub/pub_command.dart';
import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:analyzer/instrumentation/service.dart';
import 'package:meta/meta.dart';
+import 'package:path/path.dart' as path;
/// Information about Pub packages that can be converted to/from JSON and
/// cached to disk.
@@ -130,16 +131,26 @@
/// A service for providing Pub package information.
///
-/// Uses a [PubApi] to communicate with Pub and caches to disk using [cacheResourceProvider].
+/// Uses a [PubApi] to communicate with the Pub API and a [PubCommand] to
+/// interact with the local `pub` command.
+///
+/// Expensive results are cached to disk using [resourceProvider].
class PubPackageService {
final InstrumentationService _instrumentationService;
final PubApi _api;
+
+ /// A wrapper over the "pub" command line too.
+ ///
+ /// This can be null when not running on a real file system because it may
+ /// try to interact with folders that don't really exist.
+ final PubCommand? _command;
+
Timer? _nextPackageNameListRequestTimer;
Timer? _nextWriteDiskCacheTimer;
- /// [ResourceProvider] used for caching. This should generally be a
- /// [PhysicalResourceProvider] outside of tests.
- final ResourceProvider cacheResourceProvider;
+ /// [ResourceProvider] used for accessing the disk for caches and checking
+ /// project types. This will be a [PhysicalResourceProvider] outside of tests.
+ final ResourceProvider resourceProvider;
/// The current cache of package information. Initially `null`, but
/// overwritten after first read of cache from disk or fetch from the API.
@@ -148,25 +159,50 @@
int _packageDetailsRequestsInFlight = 0;
- PubPackageService(
- this._instrumentationService, this.cacheResourceProvider, this._api);
+ /// A cache of version numbers from running the "pub outdated" command used
+ /// for completion in pubspec.yaml.
+ final _pubspecPackageVersions =
+ <String, Map<String, PubOutdatedPackageDetails>>{};
- /// Gets the last set of package results or an empty List if no results.
+ PubPackageService(this._instrumentationService, this.resourceProvider,
+ this._api, this._command);
+
+ /// Gets the last set of package results from the Pub API or an empty List if
+ /// no results.
+ ///
+ /// This data is used for completion of package names in pubspec.yaml
+ /// and for clients that support lazy resolution of completion items may also
+ /// include their descriptions and/or version numbers.
List<PubPackage> get cachedPackages =>
packageCache?.packages.values.toList() ?? [];
- bool get isRunning => _nextPackageNameListRequestTimer != null;
+ @visibleForTesting
+ bool get isPackageNamesTimerRunning =>
+ _nextPackageNameListRequestTimer != null;
@visibleForTesting
File get packageCacheFile {
- final cacheFolder = cacheResourceProvider
+ final cacheFolder = resourceProvider
.getStateLocation('.pub-package-details-cache')!
..create();
return cacheFolder.getChildAssumingFile('packages.json');
}
- /// Begin a request to pre-load the package name list.
+ /// Begins preloading caches for package names and pub versions.
+ void beginCachePreloads(List<String> pubspecs) {
+ beginPackageNamePreload();
+ for (final pubspec in pubspecs) {
+ fetchPackageVersionsViaPubOutdated(pubspec, pubspecWasModified: false);
+ }
+ }
+
+ /// Begin a timer to pre-load and update the package name list if one has not
+ /// already been started.
void beginPackageNamePreload() {
+ if (isPackageNamesTimerRunning) {
+ return;
+ }
+
// If first time, try to read from disk.
var cache = packageCache;
if (cache == null) {
@@ -179,11 +215,69 @@
Timer(cache.cacheTimeRemaining, _fetchFromServer);
}
- /// Gets the cached package details for package [packageName].
+ /// Gets the latest cached package version fetched from the Pub API for the
+ /// package [packageName].
+ String? cachedPubApiLatestVersion(String packageName) =>
+ packageCache?.packages[packageName]?.latestVersion;
+
+ /// Gets the package versions cached using "pub outdated" for the package
+ /// [packageName] for the project using [pubspecPath].
///
- /// Returns null if no package details are cached.
- PubPackage? cachedPackageDetails(String packageName) =>
- packageCache?.packages[packageName];
+ /// Versions in here might only be available for packages that are in the
+ /// pubspec on disk. Newly-added packages in the overlay might not be
+ /// available.
+ PubOutdatedPackageDetails? cachedPubOutdatedVersions(
+ String pubspecPath, String packageName) {
+ final pubspecCache = _pubspecPackageVersions[pubspecPath];
+ return pubspecCache != null ? pubspecCache[packageName] : null;
+ }
+
+ /// Begin a request to pre-load package versions using the "pub outdated"
+ /// command.
+ ///
+ /// If [pubspecWasModified] is true, the command will always be run. Otherwise it
+ /// will only be run if data is not already cached.
+ Future<void> fetchPackageVersionsViaPubOutdated(String pubspecPath,
+ {required bool pubspecWasModified}) async {
+ final pubCommand = _command;
+ if (pubCommand == null) {
+ return;
+ }
+
+ // If we already have a cache for the file and it was not modified (only
+ // opened) we do not need to re-run the command.
+ if (!pubspecWasModified &&
+ _pubspecPackageVersions.containsKey(pubspecPath)) {
+ return;
+ }
+
+ // Check if this pubspec is inside a DEPS-managed folder, and if so
+ // just cache an empty set of results since Pub is not managing
+ // dependencies.
+ if (_hasAncestorDEPSFile(pubspecPath)) {
+ _pubspecPackageVersions.putIfAbsent(pubspecPath, () => {});
+ return;
+ }
+
+ final results = await pubCommand.outdatedVersions(pubspecPath);
+ final cache = _pubspecPackageVersions.putIfAbsent(pubspecPath, () => {});
+ for (final package in results) {
+ // We use the versions from the "pub outdated" results but only cache them
+ // in-memory for this specific pubspec, as the resolved version may be
+ // restricted by constraints/dependencies in the pubspec. The "pub"
+ // command does caching of the JSON versions to make "pub outdated" fast.
+ cache[package.packageName] = package;
+ }
+ }
+
+ /// Clears package caches for [pubspecPath].
+ ///
+ /// Does not remove other caches that are not pubspec-specific (for example
+ /// the latest version pulled directly from the Pub API independant of
+ /// pubspec).
+ Future<void> flushPackageCaches(String pubspecPath) async {
+ _pubspecPackageVersions.remove(pubspecPath);
+ }
/// Gets package details for package [packageName].
///
@@ -267,6 +361,19 @@
}
}
+ /// Checks whether there is a DEPS file in any folder walking up from the
+ /// pubspec at [pubspecPath].
+ bool _hasAncestorDEPSFile(String pubspecPath) {
+ var folder = path.dirname(pubspecPath);
+ do {
+ if (resourceProvider.getFile(path.join(folder, 'DEPS')).exists) {
+ return true;
+ }
+ folder = path.dirname(folder);
+ } while (folder != path.dirname(folder));
+ return false;
+ }
+
/// Writes the package cache to disk after
/// [PackageDetailsCache._writeCacheDebounceDuration] has elapsed, restarting
/// the timer each time this method is called.
diff --git a/pkg/analysis_server/lib/src/services/refactoring/extract_local.dart b/pkg/analysis_server/lib/src/services/refactoring/extract_local.dart
index 2432c5b..7d361dc 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/extract_local.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/extract_local.dart
@@ -61,12 +61,12 @@
utils = CorrectionUtils(resolveResult);
}
- String get file => resolveResult.path!;
+ String get file => resolveResult.path;
@override
String get refactoringName => 'Extract Local Variable';
- CompilationUnit get unit => resolveResult.unit!;
+ CompilationUnit get unit => resolveResult.unit;
CompilationUnitElement get unitElement => unit.declaredElement!;
@@ -231,7 +231,7 @@
return RefactoringStatus.fatal(
'The selection offset must be greater than zero.');
}
- if (selectionOffset + selectionLength >= resolveResult.content!.length) {
+ if (selectionOffset + selectionLength >= resolveResult.content.length) {
return RefactoringStatus.fatal(
'The selection end offset must be less then the length of the file.');
}
diff --git a/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart b/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
index a2c9a19..ebb50c0 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
@@ -297,7 +297,7 @@
// add replace edit
var edit = newSourceEdit_range(range, invocationSource);
doSourceChange_addElementEdit(
- change, resolveResult.unit!.declaredElement!, edit);
+ change, resolveResult.unit.declaredElement!, edit);
}
// add method declaration
{
@@ -378,7 +378,7 @@
var offset = _parentMember!.end;
var edit = SourceEdit(offset, 0, '$eol$eol$prefix$declarationSource');
doSourceChange_addElementEdit(
- change, resolveResult.unit!.declaredElement!, edit);
+ change, resolveResult.unit.declaredElement!, edit);
}
}
// done
@@ -450,7 +450,7 @@
return RefactoringStatus.fatal(
'The selection offset must be greater than zero.');
}
- if (selectionOffset + selectionLength >= resolveResult.content!.length) {
+ if (selectionOffset + selectionLength >= resolveResult.content.length) {
return RefactoringStatus.fatal(
'The selection end offset must be less then the length of the file.');
}
@@ -658,12 +658,11 @@
var originalSource = utils.getText(range.offset, range.length);
var pattern = _SourcePattern();
var replaceEdits = <SourceEdit>[];
- resolveResult.unit!
- .accept(_GetSourcePatternVisitor(range, pattern, replaceEdits));
+ resolveResult.unit.accept(_GetSourcePatternVisitor(range, pattern, replaceEdits));
replaceEdits = replaceEdits.reversed.toList();
var source = SourceEdit.applySequence(originalSource, replaceEdits);
pattern.normalizedSource =
- _getNormalizedSource(source, resolveResult.unit!.featureSet);
+ _getNormalizedSource(source, resolveResult.unit.featureSet);
return pattern;
}
@@ -706,7 +705,7 @@
var result = RefactoringStatus();
var assignedUsedVariables = <VariableElement>[];
- var unit = resolveResult.unit!;
+ var unit = resolveResult.unit;
_visibleRangeMap = VisibleRangesComputer.forNode(unit);
unit.accept(
_InitializeParametersVisitor(this, assignedUsedVariables),
diff --git a/pkg/analysis_server/lib/src/services/refactoring/extract_widget.dart b/pkg/analysis_server/lib/src/services/refactoring/extract_widget.dart
index 36304e9..6fe4778 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/extract_widget.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/extract_widget.dart
@@ -85,7 +85,7 @@
}
FeatureSet get _featureSet {
- return resolveResult.unit!.featureSet;
+ return resolveResult.unit.featureSet;
}
Flutter get _flutter => Flutter.instance;
@@ -144,7 +144,7 @@
Future<SourceChange> createChange() async {
var builder =
ChangeBuilder(session: sessionHelper.session, eol: utils.endOfLine);
- await builder.addDartFileEdit(resolveResult.path!, (builder) {
+ await builder.addDartFileEdit(resolveResult.path, (builder) {
final expression = _expression;
final statements = _statements;
if (expression != null) {
diff --git a/pkg/analysis_server/lib/src/services/refactoring/inline_local.dart b/pkg/analysis_server/lib/src/services/refactoring/inline_local.dart
index c7577b6..e0f3df71 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/inline_local.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/inline_local.dart
@@ -114,7 +114,7 @@
@override
Future<SourceChange> createChange() {
var change = SourceChange(refactoringName);
- var unitElement = resolveResult.unit!.declaredElement!;
+ var unitElement = resolveResult.unit.declaredElement!;
var state = _initialState!;
// remove declaration
{
diff --git a/pkg/analysis_server/lib/src/services/refactoring/inline_method.dart b/pkg/analysis_server/lib/src/services/refactoring/inline_method.dart
index 1cff243..f3e4b67 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/inline_method.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/inline_method.dart
@@ -363,7 +363,7 @@
_methodNode = methodNode;
var resolvedUnit = declaration.resolvedUnit!;
- _methodUnit = resolvedUnit.unit!;
+ _methodUnit = resolvedUnit.unit;
_methodUtils = CorrectionUtils(resolvedUnit);
if (methodNode is MethodDeclaration) {
diff --git a/pkg/analysis_server/lib/src/services/refactoring/move_file.dart b/pkg/analysis_server/lib/src/services/refactoring/move_file.dart
index b8535bd..f768861 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/move_file.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/move_file.dart
@@ -71,7 +71,7 @@
@override
Future<SourceChange> createChange() async {
var changeBuilder = ChangeBuilder(session: resolvedUnit.session);
- var element = resolvedUnit.unit!.declaredElement;
+ var element = resolvedUnit.unit.declaredElement;
if (element == null) {
return changeBuilder.sourceChange;
}
@@ -85,21 +85,21 @@
if (element == libraryElement.definingCompilationUnit) {
// Handle part-of directives in this library
var libraryResult = await driver.currentSession
- .getResolvedLibraryByElement2(libraryElement);
+ .getResolvedLibraryByElement(libraryElement);
if (libraryResult is! ResolvedLibraryResult) {
return changeBuilder.sourceChange;
}
- var definingUnitResult = libraryResult.units!.first;
- for (var result in libraryResult.units!) {
+ var definingUnitResult = libraryResult.units.first;
+ for (var result in libraryResult.units) {
if (result.isPart) {
- var partOfs = result.unit!.directives
+ var partOfs = result.unit.directives
.whereType<PartOfDirective>()
.map((e) => e.uri)
.whereNotNull()
.where((uri) => _isRelativeUri(uri.stringValue));
if (partOfs.isNotEmpty) {
await changeBuilder.addDartFileEdit(
- result.unit!.declaredElement!.source.fullName, (builder) {
+ result.unit.declaredElement!.source.fullName, (builder) {
partOfs.forEach((uri) {
var newLocation =
pathContext.join(newDir, pathos.basename(newFile));
@@ -113,9 +113,8 @@
}
if (newDir != oldDir) {
- await changeBuilder.addDartFileEdit(definingUnitResult.path!,
- (builder) {
- for (var directive in definingUnitResult.unit!.directives) {
+ await changeBuilder.addDartFileEdit(definingUnitResult.path, (builder) {
+ for (var directive in definingUnitResult.unit.directives) {
if (directive is UriBasedDirective) {
_updateUriReference(builder, directive, oldDir, newDir);
}
@@ -124,7 +123,7 @@
}
} else if (newDir != oldDir) {
// Otherwise, we need to update any relative part-of references.
- var partOfs = resolvedUnit.unit!.directives
+ var partOfs = resolvedUnit.unit.directives
.whereType<PartOfDirective>()
.map((e) => e.uri)
.whereNotNull()
diff --git a/pkg/analysis_server/lib/src/services/refactoring/rename_class_member.dart b/pkg/analysis_server/lib/src/services/refactoring/rename_class_member.dart
index 422d944..91654f8 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/rename_class_member.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/rename_class_member.dart
@@ -334,9 +334,6 @@
}
var unit = result.unit;
- if (unit == null) {
- return const [];
- }
var collector = _LocalElementsCollector(name);
unit.accept(collector);
diff --git a/pkg/analysis_server/lib/src/services/refactoring/rename_extension_member.dart b/pkg/analysis_server/lib/src/services/refactoring/rename_extension_member.dart
index 5367235..f0b65ab 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/rename_extension_member.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/rename_extension_member.dart
@@ -165,9 +165,6 @@
}
var unit = result.unit;
- if (unit == null) {
- return const [];
- }
var collector = _LocalElementsCollector(name);
unit.accept(collector);
diff --git a/pkg/analysis_server/lib/src/services/refactoring/rename_import.dart b/pkg/analysis_server/lib/src/services/refactoring/rename_import.dart
index 2dfbd42..4042b04 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/rename_import.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/rename_import.dart
@@ -108,7 +108,7 @@
ImportDirective? _findNode() {
var library = element.library;
var path = library.source.fullName;
- var unitResult = session.getParsedUnit2(path);
+ var unitResult = session.getParsedUnit(path);
if (unitResult is! ParsedUnitResult) {
return null;
}
@@ -122,7 +122,7 @@
/// it. Otherwise return `null`.
SimpleIdentifier? _getInterpolationIdentifier(SourceReference reference) {
var source = reference.element.source!;
- var unitResult = session.getParsedUnit2(source.fullName);
+ var unitResult = session.getParsedUnit(source.fullName);
if (unitResult is! ParsedUnitResult) {
return null;
}
diff --git a/pkg/analysis_server/lib/src/status/diagnostics.dart b/pkg/analysis_server/lib/src/status/diagnostics.dart
index 610be65..999bc4d 100644
--- a/pkg/analysis_server/lib/src/status/diagnostics.dart
+++ b/pkg/analysis_server/lib/src/status/diagnostics.dart
@@ -246,7 +246,7 @@
var result = await driver.getResult2(filePath);
if (result is ResolvedUnitResult) {
var writer = AstWriter(buf);
- result.unit!.accept(writer);
+ result.unit.accept(writer);
} else {
p(
'An AST could not be produced for the file '
@@ -836,7 +836,7 @@
var result = await driver.getResult2(filePath);
CompilationUnitElement? compilationUnitElement;
if (result is ResolvedUnitResult) {
- compilationUnitElement = result.unit?.declaredElement;
+ compilationUnitElement = result.unit.declaredElement;
}
if (compilationUnitElement != null) {
var writer = ElementWriter(buf);
diff --git a/pkg/analysis_server/lib/src/utilities/mocks.dart b/pkg/analysis_server/lib/src/utilities/mocks.dart
index 5022dcd..9c581cd 100644
--- a/pkg/analysis_server/lib/src/utilities/mocks.dart
+++ b/pkg/analysis_server/lib/src/utilities/mocks.dart
@@ -146,6 +146,8 @@
plugin.AnalysisUpdateContentParams? analysisUpdateContentParams;
plugin.RequestParams? broadcastedRequest;
Map<PluginInfo, Future<plugin.Response>>? broadcastResults;
+ Map<PluginInfo, Future<plugin.Response>>? Function(plugin.RequestParams)?
+ handleRequest;
@override
List<PluginInfo> plugins = [];
@@ -192,7 +194,9 @@
plugin.RequestParams params,
{analyzer.ContextRoot? contextRoot}) {
broadcastedRequest = params;
- return broadcastResults ?? <PluginInfo, Future<plugin.Response>>{};
+ return handleRequest?.call(params) ??
+ broadcastResults ??
+ <PluginInfo, Future<plugin.Response>>{};
}
@override
diff --git a/pkg/analysis_server/lib/src/utilities/process.dart b/pkg/analysis_server/lib/src/utilities/process.dart
new file mode 100644
index 0000000..70ea179
--- /dev/null
+++ b/pkg/analysis_server/lib/src/utilities/process.dart
@@ -0,0 +1,32 @@
+// 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.
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:io';
+
+/// An abstraction over [Process] from 'dart:io' to allow mocking in tests.
+class ProcessRunner {
+ Future<ProcessResult> run(
+ String executable,
+ List<String> arguments, {
+ String? workingDirectory,
+ Map<String, String>? environment,
+ bool includeParentEnvironment = true,
+ bool runInShell = false,
+ Encoding? stdoutEncoding = systemEncoding,
+ Encoding? stderrEncoding = systemEncoding,
+ }) async {
+ return Process.run(
+ executable,
+ arguments,
+ workingDirectory: workingDirectory,
+ environment: environment,
+ includeParentEnvironment: includeParentEnvironment,
+ runInShell: runInShell,
+ stdoutEncoding: stdoutEncoding,
+ stderrEncoding: stderrEncoding,
+ );
+ }
+}
diff --git a/pkg/analysis_server/test/abstract_context.dart b/pkg/analysis_server/test/abstract_context.dart
index f628981..fb9d441 100644
--- a/pkg/analysis_server/test/abstract_context.dart
+++ b/pkg/analysis_server/test/abstract_context.dart
@@ -90,7 +90,7 @@
var analysisContext = contextFor(testPackageRootPath);
var files = analysisContext.contextRoot.analyzedFiles().toList();
for (var path in files) {
- await analysisContext.currentSession.getResolvedUnit2(path);
+ await analysisContext.currentSession.getResolvedUnit(path);
}
}
@@ -172,7 +172,7 @@
Future<ResolvedUnitResult> resolveFile(String path) async {
path = convertPath(path);
var session = contextFor(path).currentSession;
- return await session.getResolvedUnit2(path) as ResolvedUnitResult;
+ return await session.getResolvedUnit(path) as ResolvedUnitResult;
}
@mustCallSuper
diff --git a/pkg/analysis_server/test/abstract_single_unit.dart b/pkg/analysis_server/test/abstract_single_unit.dart
index e479d9c..b18416c 100644
--- a/pkg/analysis_server/test/abstract_single_unit.dart
+++ b/pkg/analysis_server/test/abstract_single_unit.dart
@@ -70,10 +70,10 @@
}
Future<void> resolveTestFile() async {
- var result = await session.getResolvedUnit2(testFile) as ResolvedUnitResult;
+ var result = await session.getResolvedUnit(testFile) as ResolvedUnitResult;
testAnalysisResult = result;
- testCode = result.content!;
- testUnit = result.unit!;
+ testCode = result.content;
+ testUnit = result.unit;
if (verifyNoTestUnitErrors) {
expect(result.errors.where((AnalysisError error) {
return error.errorCode != HintCode.DEAD_CODE &&
diff --git a/pkg/analysis_server/test/edit/fixes_test.dart b/pkg/analysis_server/test/edit/fixes_test.dart
index 53ba68b..ff64169 100644
--- a/pkg/analysis_server/test/edit/fixes_test.dart
+++ b/pkg/analysis_server/test/edit/fixes_test.dart
@@ -73,7 +73,7 @@
var fixes = plugin.AnalysisErrorFixes(AnalysisError(
AnalysisErrorSeverity.ERROR,
AnalysisErrorType.HINT,
- Location('', 0, 0, 0, 0, 0, 0),
+ Location('', 0, 0, 0, 0, endLine: 0, endColumn: 0),
'message',
'code'));
var result = plugin.EditGetFixesResult(<plugin.AnalysisErrorFixes>[fixes]);
diff --git a/pkg/analysis_server/test/integration/support/protocol_matchers.dart b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
index 3c0e282..3c3eecb 100644
--- a/pkg/analysis_server/test/integration/support/protocol_matchers.dart
+++ b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
@@ -1104,15 +1104,16 @@
/// "length": int
/// "startLine": int
/// "startColumn": int
-/// "endLine": int
-/// "endColumn": int
+/// "endLine": optional int
+/// "endColumn": optional int
/// }
final Matcher isLocation = LazyMatcher(() => MatchesJsonObject('Location', {
'file': isFilePath,
'offset': isInt,
'length': isInt,
'startLine': isInt,
- 'startColumn': isInt,
+ 'startColumn': isInt
+ }, optionalFields: {
'endLine': isInt,
'endColumn': isInt
}));
diff --git a/pkg/analysis_server/test/lsp/client_configuration_test.dart b/pkg/analysis_server/test/lsp/client_configuration_test.dart
new file mode 100644
index 0000000..86788dc
--- /dev/null
+++ b/pkg/analysis_server/test/lsp/client_configuration_test.dart
@@ -0,0 +1,62 @@
+// 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.
+
+import 'package:analysis_server/src/lsp/client_configuration.dart';
+import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+void main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(ClientConfigurationTest);
+ });
+}
+
+@reflectiveTest
+class ClientConfigurationTest with ResourceProviderMixin {
+ void test_folderConfig() {
+ final folder = convertPath('/home/test');
+ final file = convertPath('/home/test/file.dart');
+ final config = LspClientConfiguration();
+ config.replace(
+ {'lineLength': 100},
+ {
+ folder: {'lineLength': 200}
+ },
+ );
+ expect(config.forResource(file).lineLength, equals(200));
+ }
+
+ void test_folderConfig_globalFallback() {
+ final file = convertPath('/home/test/file.dart');
+ final config = LspClientConfiguration();
+ config.replace({'lineLength': 100}, {});
+ // Should fall back to the global config.
+ expect(config.forResource(file).lineLength, equals(100));
+ }
+
+ void test_folderConfig_nested() {
+ final folderOne = convertPath('/one');
+ final folderTwo = convertPath('/one/two');
+ final folderThree = convertPath('/one/two/three');
+ final file = convertPath('/one/two/three/file.dart');
+ final config = LspClientConfiguration();
+ config.replace(
+ {'lineLength': 50},
+ {
+ folderOne: {'lineLength': 100},
+ folderThree: {'lineLength': 300},
+ folderTwo: {'lineLength': 200},
+ },
+ );
+ // Should use the inner-most folder (folderThree).
+ expect(config.forResource(file).lineLength, equals(300));
+ }
+
+ void test_globalConfig() {
+ final config = LspClientConfiguration();
+ config.replace({'lineLength': 100}, {});
+ expect(config.global.lineLength, equals(100));
+ }
+}
diff --git a/pkg/analysis_server/test/lsp/code_actions_assists_test.dart b/pkg/analysis_server/test/lsp/code_actions_assists_test.dart
index 67323f9..2797109 100644
--- a/pkg/analysis_server/test/lsp/code_actions_assists_test.dart
+++ b/pkg/analysis_server/test/lsp/code_actions_assists_test.dart
@@ -7,6 +7,8 @@
import 'package:analysis_server/lsp_protocol/protocol_custom_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
+import 'package:analyzer_plugin/protocol/protocol_common.dart' as plugin;
+import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
import 'package:collection/collection.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -166,6 +168,87 @@
expect(codeActions, isEmpty);
}
+ Future<void> test_plugin() async {
+ // This code should get an assist to replace 'foo' with 'bar'.'
+ const content = '[[foo]]';
+ const expectedContent = 'bar';
+
+ final pluginResult = plugin.EditGetAssistsResult([
+ plugin.PrioritizedSourceChange(
+ 0,
+ plugin.SourceChange(
+ "Change 'foo' to 'bar'",
+ edits: [
+ plugin.SourceFileEdit(mainFilePath, 0,
+ edits: [plugin.SourceEdit(0, 3, 'bar')])
+ ],
+ id: 'fooToBar',
+ ),
+ )
+ ]);
+ configureTestPlugin(
+ handler: (request) =>
+ request is plugin.EditGetAssistsParams ? pluginResult : null,
+ );
+
+ newFile(mainFilePath, content: withoutMarkers(content));
+ await initialize(
+ textDocumentCapabilities: withCodeActionKinds(
+ emptyTextDocumentClientCapabilities, [CodeActionKind.Refactor]),
+ );
+
+ final codeActions = await getCodeActions(mainFileUri.toString(),
+ range: rangeFromMarkers(content));
+ final assist = findEditAction(codeActions,
+ CodeActionKind('refactor.fooToBar'), "Change 'foo' to 'bar'")!;
+
+ final edit = assist.edit!;
+ expect(edit.changes, isNotNull);
+
+ // Ensure applying the changes will give us the expected content.
+ final contents = {
+ mainFilePath: withoutMarkers(content),
+ };
+ applyChanges(contents, edit.changes!);
+ expect(contents[mainFilePath], equals(expectedContent));
+ }
+
+ Future<void> test_plugin_sortsWithServer() async {
+ // Produces a server assist of "Convert to single quoted string" (with a
+ // priority of 30).
+ const content = 'import "[[dart:async]]";';
+
+ // Provide two plugin results that should sort either side of the server assist.
+ final pluginResult = plugin.EditGetAssistsResult([
+ plugin.PrioritizedSourceChange(10, plugin.SourceChange('Low')),
+ plugin.PrioritizedSourceChange(100, plugin.SourceChange('High')),
+ ]);
+ configureTestPlugin(
+ handler: (request) =>
+ request is plugin.EditGetAssistsParams ? pluginResult : null,
+ );
+
+ newFile(mainFilePath, content: withoutMarkers(content));
+ await initialize(
+ textDocumentCapabilities: withCodeActionKinds(
+ emptyTextDocumentClientCapabilities, [CodeActionKind.Refactor]),
+ );
+
+ final codeActions = await getCodeActions(mainFileUri.toString(),
+ range: rangeFromMarkers(content));
+ final codeActionTitles = codeActions.map((action) =>
+ action.map((command) => command.title, (action) => action.title));
+
+ expect(
+ codeActionTitles,
+ containsAllInOrder([
+ 'High',
+ 'Convert to single quoted string',
+ 'Low',
+ ]),
+ );
+ }
+
Future<void> test_snippetTextEdits_supported() async {
// This tests experimental support for including Snippets in TextEdits.
// https://github.com/rust-analyzer/rust-analyzer/blob/b35559a2460e7f0b2b79a7029db0c5d4e0acdb44/docs/dev/lsp-extensions.md#snippet-textedit
diff --git a/pkg/analysis_server/test/lsp/code_actions_fixes_test.dart b/pkg/analysis_server/test/lsp/code_actions_fixes_test.dart
index 2a9184a..925b13b 100644
--- a/pkg/analysis_server/test/lsp/code_actions_fixes_test.dart
+++ b/pkg/analysis_server/test/lsp/code_actions_fixes_test.dart
@@ -3,6 +3,8 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
+import 'package:analyzer_plugin/protocol/protocol_common.dart' as plugin;
+import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
import 'package:linter/src/rules.dart';
import 'package:path/path.dart' as path;
import 'package:test/test.dart';
@@ -350,6 +352,111 @@
final codeActions = await getCodeActions(otherFileUri.toString());
expect(codeActions, isEmpty);
}
+
+ Future<void> test_plugin() async {
+ // This code should get a fix to replace 'foo' with 'bar'.'
+ const content = '[[foo]]';
+ const expectedContent = 'bar';
+
+ final pluginResult = plugin.EditGetFixesResult([
+ plugin.AnalysisErrorFixes(
+ plugin.AnalysisError(
+ plugin.AnalysisErrorSeverity.ERROR,
+ plugin.AnalysisErrorType.HINT,
+ plugin.Location(mainFilePath, 0, 3, 0, 0),
+ "Do not use 'foo'",
+ 'do_not_use_foo',
+ ),
+ fixes: [
+ plugin.PrioritizedSourceChange(
+ 0,
+ plugin.SourceChange(
+ "Change 'foo' to 'bar'",
+ edits: [
+ plugin.SourceFileEdit(mainFilePath, 0,
+ edits: [plugin.SourceEdit(0, 3, 'bar')])
+ ],
+ id: 'fooToBar',
+ ),
+ )
+ ],
+ )
+ ]);
+ configureTestPlugin(
+ handler: (request) =>
+ request is plugin.EditGetFixesParams ? pluginResult : null,
+ );
+
+ newFile(mainFilePath, content: withoutMarkers(content));
+ await initialize(
+ textDocumentCapabilities: withCodeActionKinds(
+ emptyTextDocumentClientCapabilities, [CodeActionKind.QuickFix]),
+ );
+
+ final codeActions = await getCodeActions(mainFileUri.toString(),
+ range: rangeFromMarkers(content));
+ final assist = findEditAction(codeActions,
+ CodeActionKind('quickfix.fooToBar'), "Change 'foo' to 'bar'")!;
+
+ final edit = assist.edit!;
+ expect(edit.changes, isNotNull);
+
+ // Ensure applying the changes will give us the expected content.
+ final contents = {
+ mainFilePath: withoutMarkers(content),
+ };
+ applyChanges(contents, edit.changes!);
+ expect(contents[mainFilePath], equals(expectedContent));
+ }
+
+ Future<void> test_plugin_sortsWithServer() async {
+ // Produces a server fix for removing unused import with a default
+ // priority of 50.
+ const content = '''
+[[import]] 'dart:convert';
+''';
+
+ // Provide two plugin results that should sort either side of the server fix.
+ final pluginResult = plugin.EditGetFixesResult([
+ plugin.AnalysisErrorFixes(
+ plugin.AnalysisError(
+ plugin.AnalysisErrorSeverity.ERROR,
+ plugin.AnalysisErrorType.HINT,
+ plugin.Location(mainFilePath, 0, 3, 0, 0),
+ 'Dummy error',
+ 'dummy',
+ ),
+ fixes: [
+ plugin.PrioritizedSourceChange(10, plugin.SourceChange('Low')),
+ plugin.PrioritizedSourceChange(100, plugin.SourceChange('High')),
+ ],
+ )
+ ]);
+ configureTestPlugin(
+ handler: (request) =>
+ request is plugin.EditGetFixesParams ? pluginResult : null,
+ );
+
+ newFile(mainFilePath, content: withoutMarkers(content));
+ await initialize(
+ textDocumentCapabilities: withCodeActionKinds(
+ emptyTextDocumentClientCapabilities, [CodeActionKind.QuickFix]),
+ );
+
+ final codeActions = await getCodeActions(mainFileUri.toString(),
+ range: rangeFromMarkers(content));
+ final codeActionTitles = codeActions.map((action) =>
+ action.map((command) => command.title, (action) => action.title));
+
+ expect(
+ codeActionTitles,
+ containsAllInOrder([
+ 'High',
+ 'Remove unused import',
+ 'Low',
+ ]),
+ );
+ }
}
@reflectiveTest
diff --git a/pkg/analysis_server/test/lsp/code_actions_refactor_test.dart b/pkg/analysis_server/test/lsp/code_actions_refactor_test.dart
index 5ebc918..e8921f7 100644
--- a/pkg/analysis_server/test/lsp/code_actions_refactor_test.dart
+++ b/pkg/analysis_server/test/lsp/code_actions_refactor_test.dart
@@ -20,10 +20,76 @@
defineReflectiveTests(ExtractVariableRefactorCodeActionsTest);
defineReflectiveTests(InlineLocalVariableRefactorCodeActionsTest);
defineReflectiveTests(InlineMethodRefactorCodeActionsTest);
+ defineReflectiveTests(ConvertGetterToMethodCodeActionsTest);
+ defineReflectiveTests(ConvertMethodToGetterCodeActionsTest);
});
}
@reflectiveTest
+class ConvertGetterToMethodCodeActionsTest extends AbstractCodeActionsTest {
+ final refactorTitle = 'Convert Getter to Method';
+
+ Future<void> test_refactor() async {
+ const content = '''
+int get ^test => 42;
+main() {
+ var a = test;
+ var b = test;
+}
+''';
+ const expectedContent = '''
+int test() => 42;
+main() {
+ var a = test();
+ var b = test();
+}
+''';
+ newFile(mainFilePath, content: withoutMarkers(content));
+ await initialize();
+
+ final codeActions = await getCodeActions(mainFileUri.toString(),
+ position: positionFromMarker(content));
+ final codeAction =
+ findCommand(codeActions, Commands.performRefactor, refactorTitle)!;
+
+ await verifyCodeActionEdits(
+ codeAction, withoutMarkers(content), expectedContent);
+ }
+}
+
+@reflectiveTest
+class ConvertMethodToGetterCodeActionsTest extends AbstractCodeActionsTest {
+ final refactorTitle = 'Convert Method to Getter';
+
+ Future<void> test_refactor() async {
+ const content = '''
+int ^test() => 42;
+main() {
+ var a = test();
+ var b = test();
+}
+''';
+ const expectedContent = '''
+int get test => 42;
+main() {
+ var a = test;
+ var b = test;
+}
+''';
+ newFile(mainFilePath, content: withoutMarkers(content));
+ await initialize();
+
+ final codeActions = await getCodeActions(mainFileUri.toString(),
+ position: positionFromMarker(content));
+ final codeAction =
+ findCommand(codeActions, Commands.performRefactor, refactorTitle)!;
+
+ await verifyCodeActionEdits(
+ codeAction, withoutMarkers(content), expectedContent);
+ }
+}
+
+@reflectiveTest
class ExtractMethodRefactorCodeActionsTest extends AbstractCodeActionsTest {
final extractMethodTitle = 'Extract Method';
@@ -176,7 +242,12 @@
}
''';
newFile(mainFilePath, content: withoutMarkers(content));
- await initialize();
+ await initialize(
+ textDocumentCapabilities: withCodeActionKinds(
+ emptyTextDocumentClientCapabilities,
+ [CodeActionKind.Empty], // Support everything (empty prefix matches all)
+ ),
+ );
final ofKind = (CodeActionKind kind) => getCodeActions(
mainFileUri.toString(),
@@ -184,13 +255,31 @@
kinds: [kind],
);
- // The code above will return a RefactorExtract that should be included
- // by both Refactor and RefactorExtract, but not RefactorExtractFoo or
- // RefactorRewrite
- expect(await ofKind(CodeActionKind.Refactor), isNotEmpty);
- expect(await ofKind(CodeActionKind.RefactorExtract), isNotEmpty);
- expect(await ofKind(CodeActionKind('refactor.extract.foo')), isEmpty);
- expect(await ofKind(CodeActionKind.RefactorRewrite), isEmpty);
+ // Helper that requests CodeActions for [kind] and ensures all results
+ // returned have either an equal kind, or a kind that is prefixed with the
+ // requested kind followed by a dot.
+ Future<void> checkResults(CodeActionKind kind) async {
+ final results = await ofKind(kind);
+ for (final result in results) {
+ final resultKind = result.map(
+ (cmd) => throw 'Expected CodeAction, got Command: ${cmd.title}',
+ (action) => action.kind,
+ );
+ expect(
+ '$resultKind',
+ anyOf([
+ equals('$kind'),
+ startsWith('$kind.'),
+ ]),
+ );
+ }
+ }
+
+ // Check a few of each that will produces multiple matches and no matches.
+ await checkResults(CodeActionKind.Refactor);
+ await checkResults(CodeActionKind.RefactorExtract);
+ await checkResults(CodeActionKind('refactor.extract.foo'));
+ await checkResults(CodeActionKind.RefactorRewrite);
}
Future<void> test_generatesNames() async {
diff --git a/pkg/analysis_server/test/lsp/completion.dart b/pkg/analysis_server/test/lsp/completion.dart
index 75c85b1..6d70a26 100644
--- a/pkg/analysis_server/test/lsp/completion.dart
+++ b/pkg/analysis_server/test/lsp/completion.dart
@@ -8,6 +8,9 @@
import 'server_abstract.dart';
mixin CompletionTestMixin on AbstractLspAnalysisServerTest {
+ /// The last set of completion results fetched.
+ List<CompletionItem> completionResults = [];
+
int sortTextSorter(CompletionItem item1, CompletionItem item2) =>
(item1.sortText ?? item1.label).compareTo(item2.sortText ?? item2.label);
@@ -40,23 +43,24 @@
if (openCloseFile) {
await openFile(fileUri, withoutMarkers(content));
}
- final res = await getCompletion(fileUri, positionFromMarker(content));
+ completionResults =
+ await getCompletion(fileUri, positionFromMarker(content));
if (openCloseFile) {
await closeFile(fileUri);
}
// Sort the completions by sortText and filter to those we expect, so the ordering
// can be compared.
- final sortedResults = res
+ final sortedResults = completionResults
.where((r) => expectCompletions.contains(r.label))
.toList()
- ..sort(sortTextSorter);
+ ..sort(sortTextSorter);
expect(sortedResults.map((item) => item.label), equals(expectCompletions));
// Check the edits apply correctly.
if (applyEditsFor != null) {
- var item = res.singleWhere((c) => c.label == applyEditsFor);
+ var item = completionResults.singleWhere((c) => c.label == applyEditsFor);
final insertFormat = item.insertTextFormat;
if (resolve) {
diff --git a/pkg/analysis_server/test/lsp/completion_yaml_test.dart b/pkg/analysis_server/test/lsp/completion_yaml_test.dart
index 9d26755..52bf479 100644
--- a/pkg/analysis_server/test/lsp/completion_yaml_test.dart
+++ b/pkg/analysis_server/test/lsp/completion_yaml_test.dart
@@ -2,6 +2,8 @@
// 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.
+import 'dart:io';
+
import 'package:analysis_server/src/services/pub/pub_api.dart';
import 'package:http/http.dart';
import 'package:linter/src/rules.dart';
@@ -367,7 +369,7 @@
);
}
- Future<void> test_package_version() async {
+ Future<void> test_package_versions_fromApi() async {
httpClient.sendHandler = (BaseRequest request) async {
if (request.url.path.startsWith(PubApi.packageNameListPath)) {
return Response(samplePackageList, 200);
@@ -418,6 +420,163 @@
);
}
+ Future<void> test_package_versions_fromPubOutdated() async {
+ final json = r'''
+ {
+ "packages": [
+ {
+ "package": "one",
+ "latest": { "version": "3.2.1" },
+ "resolvable": { "version": "1.2.4" }
+ }
+ ]
+ }
+ ''';
+ processRunner.runHandler =
+ (executable, args, {dir, env}) => ProcessResult(1, 0, json, '');
+
+ final content = '''
+name: foo
+version: 1.0.0
+
+dependencies:
+ one: ^''';
+
+ final expected = '''
+name: foo
+version: 1.0.0
+
+dependencies:
+ one: ^1.2.4''';
+
+ await initialize();
+ await openFile(pubspecFileUri, withoutMarkers(content));
+ await pumpEventQueue(times: 500);
+
+ await verifyCompletions(
+ pubspecFileUri,
+ content,
+ expectCompletions: ['^1.2.4', '^3.2.1'],
+ applyEditsFor: '^1.2.4',
+ expectedContent: expected,
+ openCloseFile: false,
+ );
+ }
+
+ Future<void> test_package_versions_fromPubOutdated_afterChange() async {
+ final initialJson = r'''
+ {
+ "packages": [
+ {
+ "package": "one",
+ "latest": { "version": "3.2.1" },
+ "resolvable": { "version": "1.2.3" }
+ }
+ ]
+ }
+ ''';
+ final updatedJson = r'''
+ {
+ "packages": [
+ {
+ "package": "one",
+ "latest": { "version": "2.1.0" },
+ "resolvable": { "version": "2.3.4" }
+ }
+ ]
+ }
+ ''';
+ processRunner.runHandler =
+ (executable, args, {dir, env}) => ProcessResult(1, 0, initialJson, '');
+
+ final content = '''
+name: foo
+version: 1.0.0
+
+dependencies:
+ one: ^''';
+
+ final expected = '''
+name: foo
+version: 1.0.0
+
+dependencies:
+ one: ^2.3.4''';
+
+ newFile(pubspecFilePath, content: content);
+ await initialize();
+ await openFile(pubspecFileUri, withoutMarkers(content));
+ await pumpEventQueue(times: 500);
+
+ // Modify the underlying file which should trigger an update of the
+ // cached data.
+ processRunner.runHandler =
+ (executable, args, {dir, env}) => ProcessResult(1, 0, updatedJson, '');
+ modifyFile(pubspecFilePath, '$content# trailing comment');
+ await pumpEventQueue(times: 500);
+
+ await verifyCompletions(
+ pubspecFileUri,
+ content,
+ expectCompletions: ['^2.3.4', '^2.1.0'],
+ applyEditsFor: '^2.3.4',
+ expectedContent: expected,
+ openCloseFile: false,
+ );
+
+ // Also veryify the detail fields were populated as expected.
+ expect(
+ completionResults.singleWhere((c) => c.label == '^2.3.4').detail,
+ equals('latest compatible'),
+ );
+ expect(
+ completionResults.singleWhere((c) => c.label == '^2.1.0').detail,
+ equals('latest'),
+ );
+ }
+
+ Future<void> test_package_versions_fromPubOutdated_afterDelete() async {
+ final initialJson = r'''
+ {
+ "packages": [
+ {
+ "package": "one",
+ "latest": { "version": "3.2.1" },
+ "resolvable": { "version": "1.2.3" }
+ }
+ ]
+ }
+ ''';
+ processRunner.runHandler =
+ (executable, args, {dir, env}) => ProcessResult(1, 0, initialJson, '');
+
+ final content = '''
+name: foo
+version: 1.0.0
+
+dependencies:
+ one: ^''';
+
+ newFile(pubspecFilePath, content: content);
+ await initialize();
+ await openFile(pubspecFileUri, withoutMarkers(content));
+ await pumpEventQueue(times: 500);
+
+ // Delete the underlying file which should trigger eviction of the cache.
+ deleteFile(pubspecFilePath);
+ await pumpEventQueue(times: 500);
+
+ await verifyCompletions(
+ pubspecFileUri,
+ content,
+ expectCompletions: [],
+ openCloseFile: false,
+ );
+
+ // There should have been no version numbers.
+ expect(completionResults, isEmpty);
+ }
+
Future<void> test_topLevel() async {
final content = '''
version: 1.0.0
diff --git a/pkg/analysis_server/test/lsp/diagnostic_test.dart b/pkg/analysis_server/test/lsp/diagnostic_test.dart
index 0f7ecf1..96c7f5a 100644
--- a/pkg/analysis_server/test/lsp/diagnostic_test.dart
+++ b/pkg/analysis_server/test/lsp/diagnostic_test.dart
@@ -30,12 +30,15 @@
final pluginError = plugin.AnalysisError(
plugin.AnalysisErrorSeverity.ERROR,
plugin.AnalysisErrorType.STATIC_TYPE_WARNING,
- plugin.Location(pluginAnalyzedFilePath, 0, 6, 0, 0, 0, 6),
+ plugin.Location(pluginAnalyzedFilePath, 0, 6, 0, 0,
+ endLine: 0, endColumn: 6),
'Test error from plugin',
'ERR1',
contextMessages: [
- plugin.DiagnosticMessage('Related error',
- plugin.Location(pluginAnalyzedFilePath, 31, 4, 1, 12, 1, 16))
+ plugin.DiagnosticMessage(
+ 'Related error',
+ plugin.Location(pluginAnalyzedFilePath, 31, 4, 1, 12,
+ endLine: 1, endColumn: 16))
],
);
final pluginResult =
@@ -317,7 +320,7 @@
final pluginError = plugin.AnalysisError(
plugin.AnalysisErrorSeverity.ERROR,
plugin.AnalysisErrorType.STATIC_TYPE_WARNING,
- plugin.Location(mainFilePath, 0, 1, 0, 0, 0, 1),
+ plugin.Location(mainFilePath, 0, 1, 0, 0, endLine: 0, endColumn: 1),
pluginErrorMessage,
'ERR1',
);
diff --git a/pkg/analysis_server/test/lsp/format_test.dart b/pkg/analysis_server/test/lsp/format_test.dart
index 741a740..5ba380f 100644
--- a/pkg/analysis_server/test/lsp/format_test.dart
+++ b/pkg/analysis_server/test/lsp/format_test.dart
@@ -309,6 +309,97 @@
await expectFormattedContents(mainFileUri, contents, expectedLongLines);
}
+ Future<void> test_lineLength_outsideWorkspaceFolders() async {
+ const contents = '''
+main() {
+ print('123456789 ''123456789 ''123456789 ');
+}
+''';
+ const expectedContents = '''
+main() {
+ print(
+ '123456789 '
+ '123456789 '
+ '123456789 ');
+}
+''';
+
+ await provideConfig(
+ () => initialize(
+ // Use empty roots so the test file is not inside any known
+ // WorkspaceFolder.
+ allowEmptyRootUri: true,
+ workspaceCapabilities: withDidChangeConfigurationDynamicRegistration(
+ withConfigurationSupport(emptyWorkspaceClientCapabilities)),
+ ),
+ // Global config (this should be used).
+ {'lineLength': 10},
+ );
+ await openFile(mainFileUri, contents);
+ await expectFormattedContents(mainFileUri, contents, expectedContents);
+ }
+
+ Future<void> test_lineLength_workspaceFolderSpecified() async {
+ const contents = '''
+main() {
+ print('123456789 ''123456789 ''123456789 ');
+}
+''';
+ const expectedContents = '''
+main() {
+ print(
+ '123456789 '
+ '123456789 '
+ '123456789 ');
+}
+''';
+
+ await provideConfig(
+ () => initialize(
+ workspaceCapabilities: withDidChangeConfigurationDynamicRegistration(
+ withConfigurationSupport(emptyWorkspaceClientCapabilities))),
+ // Global config.
+ {'lineLength': 200},
+ folderConfig: {
+ // WorkspaceFolder config for this project (this should be used).
+ projectFolderPath: {'lineLength': 10},
+ },
+ );
+ await openFile(mainFileUri, contents);
+ await expectFormattedContents(mainFileUri, contents, expectedContents);
+ }
+
+ Future<void> test_lineLength_workspaceFolderUnspecified() async {
+ const contents = '''
+main() {
+ print('123456789 ''123456789 ''123456789 ');
+}
+''';
+ const expectedContents = '''
+main() {
+ print(
+ '123456789 '
+ '123456789 '
+ '123456789 ');
+}
+''';
+
+ await provideConfig(
+ () => initialize(
+ workspaceCapabilities: withDidChangeConfigurationDynamicRegistration(
+ withConfigurationSupport(emptyWorkspaceClientCapabilities))),
+ // Global config (this should be used).
+ {'lineLength': 10},
+ folderConfig: {
+ // WorkspaceFolder config for this project that doesn't specific
+ // lineLength.
+ projectFolderPath: {'someOtherValue': 'foo'},
+ },
+ );
+ await openFile(mainFileUri, contents);
+ await expectFormattedContents(mainFileUri, contents, expectedContents);
+ }
+
Future<void> test_minimalEdits_addWhitespace() async {
// Check we only get one edit to add the required whitespace and not
// an entire document replacement.
diff --git a/pkg/analysis_server/test/lsp/pub_package_service_test.dart b/pkg/analysis_server/test/lsp/pub_package_service_test.dart
index b00f285..c22a0f5 100644
--- a/pkg/analysis_server/test/lsp/pub_package_service_test.dart
+++ b/pkg/analysis_server/test/lsp/pub_package_service_test.dart
@@ -2,10 +2,16 @@
// 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.
+import 'dart:io';
+
import 'package:analysis_server/src/services/pub/pub_api.dart';
+import 'package:analysis_server/src/services/pub/pub_command.dart';
import 'package:analysis_server/src/services/pub/pub_package_service.dart';
import 'package:analyzer/instrumentation/service.dart';
+import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
+import 'package:collection/collection.dart';
import 'package:http/http.dart';
+import 'package:path/path.dart' as path;
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -15,6 +21,7 @@
void main() {
defineReflectiveSuite(() {
defineReflectiveTests(PubApiTest);
+ defineReflectiveTests(PubCommandTest);
defineReflectiveTests(PubPackageServiceTest);
});
}
@@ -78,6 +85,168 @@
}
@reflectiveTest
+class PubCommandTest with ResourceProviderMixin {
+ late MockProcessRunner processRunner;
+ late PubCommand pubCommand;
+ late String pubspecPath, pubspec2Path;
+
+ void setUp() {
+ pubspecPath = convertPath('/home/project/pubspec.yaml');
+ pubspec2Path = convertPath('/home/project2/pubspec.yaml');
+ processRunner = MockProcessRunner();
+ pubCommand = PubCommand(InstrumentationService.NULL_SERVICE, processRunner);
+ }
+
+ Future<void> test_doesNotRunConcurrently() async {
+ var isRunning = false;
+ processRunner.runHandler = (executable, args, {dir, env}) async {
+ expect(isRunning, isFalse,
+ reason: 'pub commands should not run concurrently');
+ isRunning = true;
+ await pumpEventQueue(times: 500);
+ isRunning = false;
+ return ProcessResult(0, 0, '', '');
+ };
+ await Future.wait([
+ pubCommand.outdatedVersions(pubspecPath),
+ pubCommand.outdatedVersions(pubspecPath),
+ ]);
+ }
+
+ Future<void> test_outdated_args() async {
+ processRunner.runHandler = (executable, args, {dir, env}) {
+ var expectedPubPath = path.join(
+ path.dirname(Platform.resolvedExecutable),
+ Platform.isWindows ? 'pub.bat' : 'pub',
+ );
+ expect(executable, equals(expectedPubPath));
+ expect(
+ args,
+ equals([
+ 'outdated',
+ '--show-all',
+ '--json',
+ ]));
+ expect(dir, equals(convertPath('/home/project')));
+ expect(
+ env!['PUB_ENVIRONMENT'],
+ anyOf(equals('analysis_server.pub_api'),
+ endsWith(':analysis_server.pub_api')));
+ return ProcessResult(0, 0, '', '');
+ };
+ await pubCommand.outdatedVersions(pubspecPath);
+ }
+
+ Future<void> test_outdated_invalidJson() async {
+ processRunner.runHandler = (String executable, List<String> args,
+ {dir, env}) =>
+ ProcessResult(1, 0, 'NOT VALID JSON', '');
+ final result = await pubCommand.outdatedVersions(pubspecPath);
+ expect(result, isEmpty);
+ }
+
+ Future<void> test_outdated_missingFields() async {
+ final validJson = r'''
+ {
+ "packages": [
+ {
+ "package": "foo",
+ "current": { "version": "1.0.0" },
+ "upgradable": { "version": "2.0.0" },
+ "resolvable": { }
+ }
+ ]
+ }
+ ''';
+ processRunner.runHandler =
+ (executable, args, {dir, env}) => ProcessResult(1, 0, validJson, '');
+ final result = await pubCommand.outdatedVersions(pubspecPath);
+ expect(result, hasLength(1));
+ final package = result.first;
+ expect(package.packageName, equals('foo'));
+ expect(package.currentVersion, equals('1.0.0'));
+ expect(package.upgradableVersion, equals('2.0.0'));
+ expect(package.resolvableVersion, isNull);
+ expect(package.latestVersion, isNull);
+ }
+
+ Future<void> test_outdated_multiplePubspecs() async {
+ final pubspecJson1 = r'''
+ {
+ "packages": [
+ {
+ "package": "foo",
+ "resolvable": { "version": "1.1.1" }
+ }
+ ]
+ }
+ ''';
+ final pubspecJson2 = r'''
+ {
+ "packages": [
+ {
+ "package": "foo",
+ "resolvable": { "version": "2.2.2" }
+ }
+ ]
+ }
+ ''';
+
+ processRunner.runHandler = (executable, args, {dir, env}) {
+ // Return different json based on the directory we were invoked in.
+ final json =
+ dir == path.dirname(pubspecPath) ? pubspecJson1 : pubspecJson2;
+ return ProcessResult(1, 0, json, '');
+ };
+ final result1 = await pubCommand.outdatedVersions(pubspecPath);
+ final result2 = await pubCommand.outdatedVersions(pubspec2Path);
+ expect(result1.first.resolvableVersion, equals('1.1.1'));
+ expect(result2.first.resolvableVersion, equals('2.2.2'));
+ }
+
+ Future<void> test_outdated_nonZeroExitCode() async {
+ processRunner.runHandler =
+ (executable, args, {dir, env}) => ProcessResult(1, 123, '{}', '');
+ final result = await pubCommand.outdatedVersions(pubspecPath);
+ expect(result, isEmpty);
+ }
+
+ Future<void> test_validJson() async {
+ final validJson = r'''
+ {
+ "packages": [
+ {
+ "package": "foo",
+ "current": { "version": "1.0.0" },
+ "upgradable": { "version": "2.0.0" },
+ "resolvable": { "version": "3.0.0" },
+ "latest": { "version": "4.0.0" }
+ },
+ {
+ "package": "bar",
+ "current": { "version": "1.0.0" },
+ "upgradable": { "version": "2.0.0" },
+ "resolvable": { "version": "3.0.0" },
+ "latest": { "version": "4.0.0" }
+ }
+ ]
+ }
+ ''';
+ processRunner.runHandler =
+ (executable, args, {dir, env}) => ProcessResult(1, 0, validJson, '');
+ final result = await pubCommand.outdatedVersions(pubspecPath);
+ expect(result, hasLength(2));
+ result.forEachIndexed((index, package) {
+ expect(package.packageName, equals(index == 0 ? 'foo' : 'bar'));
+ expect(package.currentVersion, equals('1.0.0'));
+ expect(package.upgradableVersion, equals('2.0.0'));
+ expect(package.resolvableVersion, equals('3.0.0'));
+ expect(package.latestVersion, equals('4.0.0'));
+ });
+ }
+}
+
+@reflectiveTest
class PubPackageServiceTest extends AbstractLspAnalysisServerTest {
/// A sample API response for package names. This should match the JSON served
/// at https://pub.dev/api/package-name-completion-data.
@@ -194,13 +363,13 @@
Future<void> test_packageCache_initializesOnPubspecOpen() async {
await initialize();
- expect(server.pubPackageService.isRunning, isFalse);
+ expect(server.pubPackageService.isPackageNamesTimerRunning, isFalse);
expect(server.pubPackageService.packageCache, isNull);
expectPackages([]);
await openFile(pubspecFileUri, '');
await pumpEventQueue();
- expect(server.pubPackageService.isRunning, isTrue);
+ expect(server.pubPackageService.isPackageNamesTimerRunning, isTrue);
expect(server.pubPackageService.packageCache, isNotNull);
expectPackages([]);
}
diff --git a/pkg/analysis_server/test/lsp/server_abstract.dart b/pkg/analysis_server/test/lsp/server_abstract.dart
index ad2d20b..2e49ae5 100644
--- a/pkg/analysis_server/test/lsp/server_abstract.dart
+++ b/pkg/analysis_server/test/lsp/server_abstract.dart
@@ -48,6 +48,7 @@
late MockLspServerChannel channel;
late TestPluginManager pluginManager;
late LspAnalysisServer server;
+ late MockProcessRunner processRunner;
late MockHttpClient httpClient;
/// The number of context builds that had already occurred the last time
@@ -62,12 +63,25 @@
DiscoveredPluginInfo configureTestPlugin({
plugin.ResponseResult? respondWith,
plugin.Notification? notification,
+ plugin.ResponseResult? Function(plugin.RequestParams)? handler,
Duration respondAfter = Duration.zero,
}) {
final info = DiscoveredPluginInfo('a', 'b', 'c', server.notificationManager,
server.instrumentationService);
pluginManager.plugins.add(info);
+ if (handler != null) {
+ pluginManager.handleRequest = (request) {
+ final response = handler(request);
+ return response == null
+ ? null
+ : <PluginInfo, Future<plugin.Response>>{
+ info: Future.delayed(respondAfter)
+ .then((_) => response.toResponse('-', 1))
+ };
+ };
+ }
+
if (respondWith != null) {
pluginManager.broadcastResults = <PluginInfo, Future<plugin.Response>>{
info: Future.delayed(respondAfter)
@@ -151,6 +165,7 @@
void setUp() {
httpClient = MockHttpClient();
+ processRunner = MockProcessRunner();
channel = MockLspServerChannel(debugPrintCommunication);
// Create an SDK in the mock file system.
MockSdk(resourceProvider: resourceProvider);
@@ -162,7 +177,8 @@
DartSdkManager(convertPath('/sdk')),
CrashReportingAttachmentsBuilder.empty,
InstrumentationService.NULL_SERVICE,
- httpClient: httpClient);
+ httpClient: httpClient,
+ processRunner: processRunner);
server.pluginManager = pluginManager;
projectFolderPath = convertPath('/home/test');
@@ -1458,14 +1474,34 @@
/// Calls the supplied function and responds to any `workspace/configuration`
/// request with the supplied config.
- Future<ResponseMessage> provideConfig(Future<ResponseMessage> Function() f,
- FutureOr<Map<String, dynamic>> config) {
+ Future<ResponseMessage> provideConfig(
+ Future<ResponseMessage> Function() f,
+ FutureOr<Map<String, Object?>> globalConfig, {
+ FutureOr<Map<String, Map<String, Object?>>>? folderConfig,
+ }) {
return handleExpectedRequest<ResponseMessage, ConfigurationParams,
- List<Map<String, dynamic>>>(
+ List<Map<String, Object?>>>(
Method.workspace_configuration,
ConfigurationParams.fromJson,
f,
- handler: (configurationParams) async => [await config],
+ handler: (configurationParams) async {
+ // We must respond to the request for config with items that match the
+ // request. For any item in the request without a folder, we will return
+ // the global config. For any item in the request with a folder we will
+ // return the config for that item in the map, or fall back to the global
+ // config if it does not exist.
+ final global = await globalConfig;
+ final folders = await folderConfig;
+ return configurationParams.items.map(
+ (requestedConfig) {
+ final uri = requestedConfig.scopeUri;
+ final path = uri != null ? Uri.parse(uri).toFilePath() : null;
+ // Use the config the test provided for this path, or fall back to
+ // global.
+ return (folders != null ? folders[path] : null) ?? global;
+ },
+ ).toList();
+ },
);
}
diff --git a/pkg/analysis_server/test/lsp/test_all.dart b/pkg/analysis_server/test/lsp/test_all.dart
index fbdd56c..752d3f1 100644
--- a/pkg/analysis_server/test/lsp/test_all.dart
+++ b/pkg/analysis_server/test/lsp/test_all.dart
@@ -8,6 +8,7 @@
import 'analyzer_status_test.dart' as analyzer_status;
import 'cancel_request_test.dart' as cancel_request;
import 'change_workspace_folders_test.dart' as change_workspace_folders;
+import 'client_configuration_test.dart' as client_configuration;
import 'closing_labels_test.dart' as closing_labels;
import 'code_actions_assists_test.dart' as code_actions_assists;
import 'code_actions_fixes_test.dart' as code_actions_fixes;
@@ -48,6 +49,7 @@
analyzer_status.main();
cancel_request.main();
change_workspace_folders.main();
+ client_configuration.main();
closing_labels.main();
code_actions_assists.main();
code_actions_fixes.main();
diff --git a/pkg/analysis_server/test/mocks.dart b/pkg/analysis_server/test/mocks.dart
index d6cfa2c..e1f3ecd 100644
--- a/pkg/analysis_server/test/mocks.dart
+++ b/pkg/analysis_server/test/mocks.dart
@@ -3,9 +3,12 @@
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
+import 'dart:convert';
+import 'dart:io';
import 'package:analysis_server/protocol/protocol.dart';
import 'package:analysis_server/protocol/protocol_generated.dart';
+import 'package:analysis_server/src/utilities/process.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:http/http.dart' as http;
import 'package:test/test.dart';
@@ -47,6 +50,32 @@
}
}
+class MockProcessRunner implements ProcessRunner {
+ FutureOr<ProcessResult> Function(String executable, List<String> arguments,
+ {String? dir, Map<String, String>? env})? runHandler =
+ (executable, arguments, {dir, env}) => throw UnimplementedError();
+
+ @override
+ dynamic noSuchMethod(Invocation invocation) {
+ return super.noSuchMethod(invocation);
+ }
+
+ @override
+ Future<ProcessResult> run(
+ String executable,
+ List<String> arguments, {
+ String? workingDirectory,
+ Map<String, String>? environment,
+ bool includeParentEnvironment = true,
+ bool runInShell = false,
+ Encoding? stdoutEncoding = systemEncoding,
+ Encoding? stderrEncoding = systemEncoding,
+ }) async {
+ return runHandler!(executable, arguments,
+ dir: workingDirectory, env: environment);
+ }
+}
+
class MockSource implements Source {
@override
final String fullName;
diff --git a/pkg/analysis_server/test/protocol_server_test.dart b/pkg/analysis_server/test/protocol_server_test.dart
index 49cae54..ac31994 100644
--- a/pkg/analysis_server/test/protocol_server_test.dart
+++ b/pkg/analysis_server/test/protocol_server_test.dart
@@ -361,7 +361,7 @@
Map<String, FileResult> fileResults = {};
void addFileResult(FileResult result) {
- fileResults[result.path!] = result;
+ fileResults[result.path] = result;
}
@override
diff --git a/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart b/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
index 0a651c2..546faf8 100644
--- a/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
+++ b/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
@@ -536,7 +536,7 @@
DartCompletionRequest request);
Future computeSuggestions({int times = 200}) async {
- result = await session.getResolvedUnit2(testFile) as ResolvedUnitResult;
+ result = await session.getResolvedUnit(testFile) as ResolvedUnitResult;
var baseRequest = CompletionRequestImpl(
result, completionOffset, CompletionPerformance());
diff --git a/pkg/analysis_server/test/services/completion/dart/completion_manager_test.dart b/pkg/analysis_server/test/services/completion/dart/completion_manager_test.dart
index 4dd13ee..257fb5b 100644
--- a/pkg/analysis_server/test/services/completion/dart/completion_manager_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/completion_manager_test.dart
@@ -50,7 +50,7 @@
// Build the request
var baseRequest = CompletionRequestImpl(
- await session.getResolvedUnit2(testFile) as ResolvedUnitResult,
+ await session.getResolvedUnit(testFile) as ResolvedUnitResult,
completionOffset,
CompletionPerformance());
await baseRequest.performance.runRequestOperation((performance) async {
diff --git a/pkg/analysis_server/test/services/correction/organize_directives_test.dart b/pkg/analysis_server/test/services/correction/organize_directives_test.dart
index a147a80..7696ad5 100644
--- a/pkg/analysis_server/test/services/correction/organize_directives_test.dart
+++ b/pkg/analysis_server/test/services/correction/organize_directives_test.dart
@@ -582,8 +582,8 @@
Future<void> _computeUnitAndErrors(String code) async {
addTestSource(code);
- var result = await session.getResolvedUnit2(testFile) as ResolvedUnitResult;
- testUnit = result.unit!;
+ var result = await session.getResolvedUnit(testFile) as ResolvedUnitResult;
+ testUnit = result.unit;
testErrors = result.errors;
}
}
diff --git a/pkg/analysis_server/test/services/correction/sort_members_test.dart b/pkg/analysis_server/test/services/correction/sort_members_test.dart
index a766800..e434168 100644
--- a/pkg/analysis_server/test/services/correction/sort_members_test.dart
+++ b/pkg/analysis_server/test/services/correction/sort_members_test.dart
@@ -925,7 +925,7 @@
Future<void> _parseTestUnit(String code) async {
addTestSource(code);
- var result = session.getParsedUnit2(testFile) as ParsedUnitResult;
+ var result = session.getParsedUnit(testFile) as ParsedUnitResult;
testUnit = result.unit;
}
}
diff --git a/pkg/analysis_server/test/services/correction/status_test.dart b/pkg/analysis_server/test/services/correction/status_test.dart
index 41c0eec..055c0e4 100644
--- a/pkg/analysis_server/test/services/correction/status_test.dart
+++ b/pkg/analysis_server/test/services/correction/status_test.dart
@@ -98,7 +98,7 @@
}
void test_addFatalError_withLocation() {
- var location = Location('/test.dart', 1, 2, 3, 4, 5, 6);
+ var location = Location('/test.dart', 1, 2, 3, 4, endLine: 5, endColumn: 6);
var refactoringStatus = RefactoringStatus();
// initial state
expect(refactoringStatus.severity, null);
@@ -210,7 +210,7 @@
}
void test_newError() {
- var location = Location('/test.dart', 1, 2, 3, 4, 5, 6);
+ var location = Location('/test.dart', 1, 2, 3, 4, endLine: 5, endColumn: 6);
var refactoringStatus = RefactoringStatus.error('msg', location);
var problem = refactoringStatus.problem!;
var problemLocation = problem.location!;
diff --git a/pkg/analysis_server/test/services/refactoring/move_file_test.dart b/pkg/analysis_server/test/services/refactoring/move_file_test.dart
index ad4b7ef..5094b24 100644
--- a/pkg/analysis_server/test/services/refactoring/move_file_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/move_file_test.dart
@@ -67,7 +67,7 @@
// testAnalysisResult manually here, the path is referenced through the
// referenced File object to run on Windows:
testAnalysisResult =
- await session.getResolvedUnit2(file.path) as ResolvedUnitResult;
+ await session.getResolvedUnit(file.path) as ResolvedUnitResult;
_createRefactoring('/home/test/lib/222/new_name.dart', oldFile: file.path);
await _assertSuccessfulRefactoring();
@@ -90,7 +90,7 @@
// testAnalysisResult manually here, the path is referenced through the
// referenced File object to run on Windows:
testAnalysisResult =
- await session.getResolvedUnit2(file.path) as ResolvedUnitResult;
+ await session.getResolvedUnit(file.path) as ResolvedUnitResult;
_createRefactoring('/home/test0/test1/test3/lib/111/name.dart',
oldFile: file.path);
@@ -114,7 +114,7 @@
// testAnalysisResult manually here, the path is referenced through the
// referenced File object to run on Windows:
testAnalysisResult =
- await session.getResolvedUnit2(file.path) as ResolvedUnitResult;
+ await session.getResolvedUnit(file.path) as ResolvedUnitResult;
_createRefactoring('/home/test0/test1/test2/test3/lib/111/name.dart',
oldFile: file.path);
@@ -138,7 +138,7 @@
// testAnalysisResult manually here, the path is referenced through the
// referenced File object to run on Windows:
testAnalysisResult =
- await session.getResolvedUnit2(file.path) as ResolvedUnitResult;
+ await session.getResolvedUnit(file.path) as ResolvedUnitResult;
_createRefactoring('/home/test0/test1/lib/111/name.dart',
oldFile: file.path);
@@ -160,7 +160,7 @@
// testAnalysisResult manually here, the path is referenced through the
// referenced File object to run on Windows:
testAnalysisResult =
- await session.getResolvedUnit2(file.path) as ResolvedUnitResult;
+ await session.getResolvedUnit(file.path) as ResolvedUnitResult;
_createRefactoring('/home/test/lib/222/new_name.dart', oldFile: file.path);
await _assertSuccessfulRefactoring();
@@ -181,7 +181,7 @@
// testAnalysisResult manually here, the path is referenced through the
// referenced File object to run on Windows:
testAnalysisResult =
- await session.getResolvedUnit2(file.path) as ResolvedUnitResult;
+ await session.getResolvedUnit(file.path) as ResolvedUnitResult;
_createRefactoring('/home/test/lib/new_name.dart', oldFile: file.path);
await _assertSuccessfulRefactoring();
diff --git a/pkg/analysis_server/test/services/search/search_engine_test.dart b/pkg/analysis_server/test/services/search/search_engine_test.dart
index 99aa552..512db98 100644
--- a/pkg/analysis_server/test/services/search/search_engine_test.dart
+++ b/pkg/analysis_server/test/services/search/search_engine_test.dart
@@ -41,8 +41,8 @@
result = await resolveFile(path);
expect(result.state, ResultState.VALID);
- findNode = FindNode(result.content!, result.unit!);
- findElement = FindElement(result.unit!);
+ findNode = FindNode(result.content, result.unit);
+ findElement = FindElement(result.unit);
}
/// Put the [code] into the test file, and resolve it.
diff --git a/pkg/analysis_server/test/src/cider/completion_test.dart b/pkg/analysis_server/test/src/cider/completion_test.dart
index b83e4ef..7a50af7 100644
--- a/pkg/analysis_server/test/src/cider/completion_test.dart
+++ b/pkg/analysis_server/test/src/cider/completion_test.dart
@@ -806,7 +806,7 @@
/// for completion we don't resolve unnecessary node.
void _configureToCheckNotResolved({required Set<String> identifiers}) {
_testResolvedUnit = (resolvedUnitResult) {
- var unit = resolvedUnitResult.unit!;
+ var unit = resolvedUnitResult.unit;
unit.accept(
FunctionAstVisitor(
simpleIdentifier: (node) {
diff --git a/pkg/analysis_server/test/src/cider/fixes_test.dart b/pkg/analysis_server/test/src/cider/fixes_test.dart
index fa71e62..4e57e14 100644
--- a/pkg/analysis_server/test/src/cider/fixes_test.dart
+++ b/pkg/analysis_server/test/src/cider/fixes_test.dart
@@ -48,7 +48,7 @@
''');
// The file was resolved only once, even though we have 2 errors.
- expect(fileResolver.testView!.resolvedFiles, [convertPath(testPath)]);
+ expect(fileResolver.testView!.resolvedLibraries, [convertPath(testPath)]);
}
Future<void> test_createMethod() async {
diff --git a/pkg/analysis_server/test/src/cider/rename_test.dart b/pkg/analysis_server/test/src/cider/rename_test.dart
index 31c96d5..028aaea 100644
--- a/pkg/analysis_server/test/src/cider/rename_test.dart
+++ b/pkg/analysis_server/test/src/cider/rename_test.dart
@@ -107,6 +107,65 @@
expect(refactor.refactoringElement.offset, _correctionContext.offset);
}
+ void test_checkName_function() {
+ var result = _checkName(r'''
+int ^foo() => 2;
+''', 'bar');
+
+ expect(result, isNotNull);
+ expect(result?.status.problems.length, 0);
+ expect(result?.oldName, 'foo');
+ }
+
+ void test_checkName_local() {
+ var result = _checkName(r'''
+void foo() {
+ var ^a = 0; var b = a + 1;
+}
+''', 'bar');
+
+ expect(result, isNotNull);
+ expect(result?.status.problems.length, 0);
+ expect(result?.oldName, 'a');
+ }
+
+ void test_checkName_local_invalid() {
+ var result = _checkName(r'''
+void foo() {
+ var ^a = 0; var b = a + 1;
+}
+''', 'Aa');
+
+ expect(result, isNotNull);
+ expect(result?.status.problems.length, 1);
+ expect(result?.oldName, 'a');
+ }
+
+ void test_checkName_parameter() {
+ var result = _checkName(r'''
+void foo(String ^a) {
+ var b = a + 1;
+}
+''', 'bar');
+
+ expect(result, isNotNull);
+ expect(result?.status.problems.length, 0);
+ expect(result?.oldName, 'a');
+ }
+
+ CheckNameResponse? _checkName(String content, String newName) {
+ _updateFile(content);
+
+ return CiderRenameComputer(
+ fileResolver,
+ ).checkNewName(
+ convertPath(testPath),
+ _correctionContext.line,
+ _correctionContext.character,
+ newName,
+ );
+ }
+
CanRenameResponse? _compute(String content) {
_updateFile(content);
diff --git a/pkg/analysis_server/test/src/computer/closing_labels_computer_test.dart b/pkg/analysis_server/test/src/computer/closing_labels_computer_test.dart
index 37057d0..83a9954 100644
--- a/pkg/analysis_server/test/src/computer/closing_labels_computer_test.dart
+++ b/pkg/analysis_server/test/src/computer/closing_labels_computer_test.dart
@@ -398,8 +398,8 @@
Future<List<ClosingLabel>> _computeElements(String sourceContent) async {
newFile(sourcePath, content: sourceContent);
var result =
- await session.getResolvedUnit2(sourcePath) as ResolvedUnitResult;
- var computer = DartUnitClosingLabelsComputer(result.lineInfo, result.unit!);
+ await session.getResolvedUnit(sourcePath) as ResolvedUnitResult;
+ var computer = DartUnitClosingLabelsComputer(result.lineInfo, result.unit);
return computer.compute();
}
}
diff --git a/pkg/analysis_server/test/src/computer/folding_computer_test.dart b/pkg/analysis_server/test/src/computer/folding_computer_test.dart
index 62e7ad9..f63607d 100644
--- a/pkg/analysis_server/test/src/computer/folding_computer_test.dart
+++ b/pkg/analysis_server/test/src/computer/folding_computer_test.dart
@@ -582,8 +582,8 @@
Future<List<FoldingRegion>> _computeRegions(String sourceContent) async {
newFile(sourcePath, content: sourceContent);
var result =
- await session.getResolvedUnit2(sourcePath) as ResolvedUnitResult;
- var computer = DartUnitFoldingComputer(result.lineInfo, result.unit!);
+ await session.getResolvedUnit(sourcePath) as ResolvedUnitResult;
+ var computer = DartUnitFoldingComputer(result.lineInfo, result.unit);
return computer.compute();
}
}
diff --git a/pkg/analysis_server/test/src/computer/highlights_computer_test.dart b/pkg/analysis_server/test/src/computer/highlights_computer_test.dart
index 2012268..46a6c44 100644
--- a/pkg/analysis_server/test/src/computer/highlights_computer_test.dart
+++ b/pkg/analysis_server/test/src/computer/highlights_computer_test.dart
@@ -114,7 +114,7 @@
this.content = content;
newFile(sourcePath, content: content);
var result =
- await session.getResolvedUnit2(sourcePath) as ResolvedUnitResult;
+ await session.getResolvedUnit(sourcePath) as ResolvedUnitResult;
if (hasErrors) {
expect(result.errors, isNotEmpty);
@@ -122,7 +122,7 @@
expect(result.errors, isEmpty);
}
- var computer = DartUnitHighlightsComputer(result.unit!);
+ var computer = DartUnitHighlightsComputer(result.unit);
highlights = computer.compute();
}
}
diff --git a/pkg/analysis_server/test/src/computer/import_elements_computer_test.dart b/pkg/analysis_server/test/src/computer/import_elements_computer_test.dart
index ebdde35..fed52b7 100644
--- a/pkg/analysis_server/test/src/computer/import_elements_computer_test.dart
+++ b/pkg/analysis_server/test/src/computer/import_elements_computer_test.dart
@@ -50,7 +50,7 @@
Future<void> createBuilder(String content) async {
originalContent = content;
newFile(path, content: content);
- var result = await session.getResolvedUnit2(path) as ResolvedUnitResult;
+ var result = await session.getResolvedUnit(path) as ResolvedUnitResult;
computer = ImportElementsComputer(resourceProvider, result);
}
diff --git a/pkg/analysis_server/test/src/computer/imported_elements_computer_test.dart b/pkg/analysis_server/test/src/computer/imported_elements_computer_test.dart
index 2cd24c1..a63d9bc 100644
--- a/pkg/analysis_server/test/src/computer/imported_elements_computer_test.dart
+++ b/pkg/analysis_server/test/src/computer/imported_elements_computer_test.dart
@@ -471,9 +471,9 @@
// TODO(brianwilkerson) Automatically extract the selection from the content.
newFile(sourcePath, content: content);
var result =
- await session.getResolvedUnit2(sourcePath) as ResolvedUnitResult;
+ await session.getResolvedUnit(sourcePath) as ResolvedUnitResult;
var computer = ImportedElementsComputer(
- result.unit!, content.indexOf(selection), selection.length);
+ result.unit, content.indexOf(selection), selection.length);
importedElements = computer.compute();
}
}
diff --git a/pkg/analysis_server/test/src/computer/outline_computer_test.dart b/pkg/analysis_server/test/src/computer/outline_computer_test.dart
index 6db141d..a005ff2 100644
--- a/pkg/analysis_server/test/src/computer/outline_computer_test.dart
+++ b/pkg/analysis_server/test/src/computer/outline_computer_test.dart
@@ -32,7 +32,7 @@
testCode = code;
newFile(testPath, content: code);
var resolveResult =
- await session.getResolvedUnit2(testPath) as ResolvedUnitResult;
+ await session.getResolvedUnit(testPath) as ResolvedUnitResult;
return DartUnitOutlineComputer(
resolveResult,
withBasicFlutter: true,
diff --git a/pkg/analysis_server/test/src/computer/selection_range_computer_test.dart b/pkg/analysis_server/test/src/computer/selection_range_computer_test.dart
index cbb6cf8..27e9e7f 100644
--- a/pkg/analysis_server/test/src/computer/selection_range_computer_test.dart
+++ b/pkg/analysis_server/test/src/computer/selection_range_computer_test.dart
@@ -194,8 +194,8 @@
String sourceContent, int offset) async {
newFile(sourcePath, content: sourceContent);
var result =
- await session.getResolvedUnit2(sourcePath) as ResolvedUnitResult;
- var computer = DartSelectionRangeComputer(result.unit!, offset);
+ await session.getResolvedUnit(sourcePath) as ResolvedUnitResult;
+ var computer = DartSelectionRangeComputer(result.unit, offset);
return computer.compute();
}
diff --git a/pkg/analysis_server/test/src/flutter/flutter_outline_computer_test.dart b/pkg/analysis_server/test/src/flutter/flutter_outline_computer_test.dart
index f186301..c224c12 100644
--- a/pkg/analysis_server/test/src/flutter/flutter_outline_computer_test.dart
+++ b/pkg/analysis_server/test/src/flutter/flutter_outline_computer_test.dart
@@ -517,7 +517,7 @@
testCode = code;
newFile(testPath, content: code);
resolveResult =
- await session.getResolvedUnit2(testPath) as ResolvedUnitResult;
+ await session.getResolvedUnit(testPath) as ResolvedUnitResult;
computer = FlutterOutlineComputer(resolveResult);
return computer.compute();
}
diff --git a/pkg/analysis_server/test/src/plugin/protocol_test_utilities.dart b/pkg/analysis_server/test/src/plugin/protocol_test_utilities.dart
index 631dcac..4ad6049 100644
--- a/pkg/analysis_server/test/src/plugin/protocol_test_utilities.dart
+++ b/pkg/analysis_server/test/src/plugin/protocol_test_utilities.dart
@@ -79,7 +79,8 @@
Element element(int stringIndex, int intIndex, {ElementKind? kind}) =>
Element(kind ?? ElementKind.CLASS, strings[stringIndex++], intIndex++,
location: Location(fileName(stringIndex++), intIndex++, intIndex++,
- intIndex++, intIndex++, intIndex++, intIndex++),
+ intIndex++, intIndex++,
+ endLine: intIndex++, endColumn: intIndex++),
parameters: strings[stringIndex++],
returnType: strings[stringIndex++],
typeParameters: strings[stringIndex++]);
@@ -99,8 +100,8 @@
intIndex++,
intIndex++,
intIndex++,
- intIndex++,
- intIndex++);
+ endLine: intIndex++,
+ endColumn: intIndex++);
/// On return, increment [stringIndex] by 5 and [intIndex] by 7.
Occurrences occurrences(int stringIndex, int intIndex) {
diff --git a/pkg/analysis_server/test/src/plugin/result_merger_test.dart b/pkg/analysis_server/test/src/plugin/result_merger_test.dart
index 934e335..9affdc3 100644
--- a/pkg/analysis_server/test/src/plugin/result_merger_test.dart
+++ b/pkg/analysis_server/test/src/plugin/result_merger_test.dart
@@ -29,7 +29,8 @@
AnalysisError createError(int offset) {
var severity = AnalysisErrorSeverity.ERROR;
var type = AnalysisErrorType.HINT;
- var location = Location('test.dart', offset, 2, 3, 4, 5, 6);
+ var location =
+ Location('test.dart', offset, 2, 3, 4, endLine: 5, endColumn: 6);
return AnalysisError(severity, type, location, '', '');
}
@@ -68,7 +69,8 @@
AnalysisError createError(int offset) {
var severity = AnalysisErrorSeverity.ERROR;
var type = AnalysisErrorType.HINT;
- var location = Location('test.dart', offset, 2, 3, 4, 5, 6);
+ var location =
+ Location('test.dart', offset, 2, 3, 4, endLine: 5, endColumn: 6);
return AnalysisError(severity, type, location, '', '');
}
@@ -265,7 +267,7 @@
void test_mergeOutline() {
Element element(ElementKind kind, int offset) {
- var location = Location('', offset, 0, 0, 0, 0, 0);
+ var location = Location('', offset, 0, 0, 0, endLine: 0, endColumn: 0);
return Element(kind, '', 0, location: location);
}
diff --git a/pkg/analysis_server/test/src/services/completion/yaml/pubspec_generator_test.dart b/pkg/analysis_server/test/src/services/completion/yaml/pubspec_generator_test.dart
index 4f4923f..4eab94d 100644
--- a/pkg/analysis_server/test/src/services/completion/yaml/pubspec_generator_test.dart
+++ b/pkg/analysis_server/test/src/services/completion/yaml/pubspec_generator_test.dart
@@ -2,8 +2,11 @@
// 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.
+import 'dart:io';
+
import 'package:analysis_server/src/services/completion/yaml/pubspec_generator.dart';
import 'package:analysis_server/src/services/pub/pub_api.dart';
+import 'package:analysis_server/src/services/pub/pub_command.dart';
import 'package:analysis_server/src/services/pub/pub_package_service.dart';
import 'package:analyzer/instrumentation/service.dart';
import 'package:http/http.dart';
@@ -22,6 +25,7 @@
@reflectiveTest
class PubspecGeneratorTest extends YamlGeneratorTest {
late MockHttpClient httpClient;
+ late MockProcessRunner processRunner;
late PubPackageService pubPackageService;
@@ -34,10 +38,12 @@
void setUp() {
httpClient = MockHttpClient();
+ processRunner = MockProcessRunner();
pubPackageService = PubPackageService(
InstrumentationService.NULL_SERVICE,
resourceProvider,
- PubApi(InstrumentationService.NULL_SERVICE, httpClient, null));
+ PubApi(InstrumentationService.NULL_SERVICE, httpClient, null),
+ PubCommand(InstrumentationService.NULL_SERVICE, processRunner));
}
void tearDown() {
@@ -339,4 +345,46 @@
''');
assertSuggestion('two: ');
}
+
+ void test_packageVersion() async {
+ final json = r'''
+ {
+ "packages": [
+ {
+ "package": "one",
+ "latest": { "version": "3.2.1" },
+ "resolvable": { "version": "1.2.4" }
+ }
+ ]
+ }
+ ''';
+ processRunner.runHandler =
+ (executable, args, {dir, env}) => ProcessResult(1, 0, json, '');
+
+ pubPackageService.beginCachePreloads([convertPath('/home/test/$fileName')]);
+ await pumpEventQueue(times: 500);
+
+ getCompletions('''
+dependencies:
+ one: ^
+''');
+ assertSuggestion('^1.2.4');
+ assertSuggestion('^3.2.1');
+ }
+
+ /// Ensure in a repo with a DEPS file like the SDK, we do not run pub
+ /// processes to cache the version numbers.
+ void test_packageVersion_withDEPSfile() async {
+ var didRun = false;
+ processRunner.runHandler = (executable, args, {dir, env}) {
+ didRun = true;
+ return ProcessResult(1, 0, '', '');
+ };
+
+ newFile('/home/DEPS');
+ pubPackageService.beginCachePreloads([convertPath('/home/test/$fileName')]);
+ await pumpEventQueue(times: 500);
+
+ expect(didRun, isFalse);
+ }
}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/convert_into_async_body_test.dart b/pkg/analysis_server/test/src/services/correction/assist/convert_into_async_body_test.dart
index 0120636..fc933c1 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/convert_into_async_body_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/convert_into_async_body_test.dart
@@ -136,6 +136,17 @@
''');
}
+ Future<void> test_sync() async {
+ // This code is erroneous; the test ensures there is no error thrown when
+ // computing assists.
+ verifyNoTestUnitErrors = false;
+ await resolveTestCode('''
+Iterable<String> f() sync {}
+''');
+ await assertNoAssistAt('{}');
+ }
+
+
Future<void> test_syncStar() async {
await resolveTestCode('''
Iterable<String> f() sync* {}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/code_template_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/code_template_test.dart
index 5103661..f6ccc74 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/code_template_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/code_template_test.dart
@@ -72,7 +72,7 @@
}
void g(int x, int y) {}
''');
- var unit = testAnalysisResult.unit!;
+ var unit = testAnalysisResult.unit;
var function = unit.declarations[0] as FunctionDeclaration;
var body = function.functionExpression.body as BlockFunctionBody;
var statement = body.block.statements[0] as ExpressionStatement;
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/data_driven_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/data_driven_test.dart
index e2c4988..4022696 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/data_driven_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/data_driven_test.dart
@@ -6,7 +6,6 @@
import 'package:analysis_server/src/services/correction/dart/data_driven.dart';
import 'package:analysis_server/src/services/correction/fix/data_driven/transform_set_manager.dart';
import 'package:analysis_server/src/services/correction/fix_internal.dart';
-import 'package:analyzer/src/test_utilities/package_config_file_builder.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -441,7 +440,7 @@
Future<void> test_rename_removed() async {
setPackageContent('''
class C {
- C.new([C c]);
+ C.updated([C c]);
}
''');
addPackageDataFile('''
@@ -455,7 +454,7 @@
inClass: 'C'
changes:
- kind: 'rename'
- newName: 'new'
+ newName: 'updated'
''');
await resolveTestCode('''
import '$importUri';
@@ -463,7 +462,7 @@
''');
await assertHasFix('''
import '$importUri';
-C c() => C.new(C.new());
+C c() => C.updated(C.updated());
''');
}
}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_set_manager_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_set_manager_test.dart
index d182ab1..42d762b 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_set_manager_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_set_manager_test.dart
@@ -36,7 +36,7 @@
var testFile = convertPath('/home/test/lib/test.dart');
addSource(testFile, '');
var result = await session.getResolvedLibraryValid(testFile);
- var sets = manager.forLibrary(result.element!);
+ var sets = manager.forLibrary(result.element);
expect(sets, hasLength(2));
}
@@ -47,7 +47,7 @@
var testFile = convertPath('/home/test/lib/test.dart');
addSource(testFile, '');
var result = await session.getResolvedLibraryValid(testFile);
- var sets = manager.forLibrary(result.element!);
+ var sets = manager.forLibrary(result.element);
expect(sets, hasLength(0));
}
@@ -70,6 +70,6 @@
extension on AnalysisSession {
Future<ResolvedLibraryResult> getResolvedLibraryValid(String path) async {
- return await getResolvedLibrary2(path) as ResolvedLibraryResult;
+ return await getResolvedLibrary(path) as ResolvedLibraryResult;
}
}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart b/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart
index 366f8d1..00f2730 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart
@@ -262,7 +262,7 @@
Future<void> addUnimportedFile(String filePath, String content) async {
addSource(filePath, content);
- var result = await session.getResolvedUnit2(convertPath(filePath));
+ var result = await session.getResolvedUnit(convertPath(filePath));
extensionCache.cacheFromResult(result as ResolvedUnitResult);
}
diff --git a/pkg/analysis_server/test/src/services/flutter/widget_description.dart b/pkg/analysis_server/test/src/services/flutter/widget_description.dart
index 8cdbfff..33f47ad 100644
--- a/pkg/analysis_server/test/src/services/flutter/widget_description.dart
+++ b/pkg/analysis_server/test/src/services/flutter/widget_description.dart
@@ -24,7 +24,7 @@
expect(fileEdit.file, testAnalysisResult.path);
var actual = SourceEdit.applySequence(
- testAnalysisResult.content!,
+ testAnalysisResult.content,
fileEdit.edits,
);
expect(actual, expected);
@@ -50,7 +50,7 @@
Future<protocol.FlutterGetWidgetDescriptionResult?> getDescription(
String search) async {
- var content = testAnalysisResult.content!;
+ var content = testAnalysisResult.content;
var offset = content.indexOf(search);
if (offset == -1) {
diff --git a/pkg/analysis_server/test/stress/completion/completion_runner.dart b/pkg/analysis_server/test/stress/completion/completion_runner.dart
index 542d8fe..16d1e81 100644
--- a/pkg/analysis_server/test/stress/completion/completion_runner.dart
+++ b/pkg/analysis_server/test/stress/completion/completion_runner.dart
@@ -80,11 +80,11 @@
}
fileCount++;
output.write('.');
- var result = await context.currentSession.getResolvedUnit2(path)
+ var result = await context.currentSession.getResolvedUnit(path)
as ResolvedUnitResult;
- var content = result.content!;
+ var content = result.content;
var lineInfo = result.lineInfo;
- var identifiers = _identifiersIn(result.unit!);
+ var identifiers = _identifiersIn(result.unit);
for (var identifier in identifiers) {
identifierCount++;
@@ -94,7 +94,7 @@
content.substring(identifier.end);
resourceProvider.setOverlay(path,
content: modifiedContent, modificationStamp: stamp++);
- result = await context.currentSession.getResolvedUnit2(path)
+ result = await context.currentSession.getResolvedUnit(path)
as ResolvedUnitResult;
}
diff --git a/pkg/analysis_server/test/test_all.dart b/pkg/analysis_server/test/test_all.dart
index 4c5a33f..3e5769cc 100644
--- a/pkg/analysis_server/test/test_all.dart
+++ b/pkg/analysis_server/test/test_all.dart
@@ -26,6 +26,7 @@
import 'socket_server_test.dart' as socket_server;
import 'src/test_all.dart' as src;
import 'tool/test_all.dart' as tool;
+import 'verify_no_solo_test.dart' as verify_no_solo;
import 'verify_sorted_test.dart' as verify_sorted;
import 'verify_tests_test.dart' as verify_tests;
@@ -52,6 +53,7 @@
socket_server.main();
src.main();
tool.main();
+ verify_no_solo.main();
verify_sorted.main();
verify_tests.main();
defineReflectiveSuite(() {
diff --git a/pkg/analysis_server/test/verify_no_solo_test.dart b/pkg/analysis_server/test/verify_no_solo_test.dart
new file mode 100644
index 0000000..150c731
--- /dev/null
+++ b/pkg/analysis_server/test/verify_no_solo_test.dart
@@ -0,0 +1,109 @@
+// 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.
+
+import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
+import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/dart/analysis/session.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/file_system/physical_file_system.dart';
+import 'package:analyzer_utilities/package_root.dart';
+import 'package:test/test.dart';
+
+void main() {
+ group('analysis_server', () {
+ buildTests(packagePath: 'analysis_server');
+ });
+
+ group('analyzer', () {
+ buildTests(packagePath: 'analyzer');
+ });
+
+ group('analyzer_cli', () {
+ buildTests(packagePath: 'analyzer_cli');
+ });
+
+ group('analyzer_plugin', () {
+ buildTests(packagePath: 'analyzer_plugin');
+ });
+}
+
+void buildTests({required String packagePath}) {
+ var provider = PhysicalResourceProvider.INSTANCE;
+ var pkgRootPath = provider.pathContext.normalize(packageRoot);
+
+ var testsPath = _toPlatformPath(pkgRootPath, '$packagePath/test');
+
+ var collection = AnalysisContextCollection(
+ includedPaths: <String>[testsPath],
+ resourceProvider: provider,
+ );
+ var contexts = collection.contexts;
+ if (contexts.length != 1) {
+ fail('The directory $testsPath contains multiple analysis contexts.');
+ }
+
+ test('no @soloTest', () {
+ var failures = <String>[];
+ buildTestsIn(contexts[0].currentSession, testsPath,
+ provider.getFolder(testsPath), failures);
+
+ if (failures.isNotEmpty) {
+ fail('@soloTest annotation found in:\n${failures.join('\n')}');
+ }
+ });
+}
+
+void buildTestsIn(AnalysisSession session, String testDirPath, Folder directory,
+ List<String> failures) {
+ var pathContext = session.resourceProvider.pathContext;
+ var children = directory.getChildren();
+ children.sort((first, second) => first.shortName.compareTo(second.shortName));
+ for (var child in children) {
+ if (child is Folder) {
+ buildTestsIn(session, testDirPath, child, failures);
+ } else if (child is File && child.shortName.endsWith('_test.dart')) {
+ var path = child.path;
+ var relativePath = pathContext.relative(path, from: testDirPath);
+
+ var result = session.getParsedUnit(path);
+ if (result is! ParsedUnitResult) {
+ fail('Could not parse $path');
+ }
+ var unit = result.unit;
+ var errors = result.errors;
+ if (errors.isNotEmpty) {
+ fail('Errors found when parsing $path');
+ }
+ var tracker = SoloTestTracker();
+ unit.accept(tracker);
+ if (tracker.found) {
+ failures.add(relativePath);
+ }
+ }
+ }
+}
+
+String _toPlatformPath(String pathPath, String relativePosixPath) {
+ var pathContext = PhysicalResourceProvider.INSTANCE.pathContext;
+ return pathContext.joinAll([
+ pathPath,
+ ...relativePosixPath.split('/'),
+ ]);
+}
+
+/// A [RecursiveAstVisitor] that tracks whether any node is annotated with
+/// an annotation named 'soloTest'.
+class SoloTestTracker extends RecursiveAstVisitor<void> {
+ bool found = false;
+
+ @override
+ void visitAnnotation(Annotation node) {
+ if (node.name.name == 'soloTest') {
+ found = true;
+ }
+ super.visitAnnotation(node);
+ }
+}
diff --git a/pkg/analysis_server/test/verify_sorted_test.dart b/pkg/analysis_server/test/verify_sorted_test.dart
index 9cf62ed..dc12ccc 100644
--- a/pkg/analysis_server/test/verify_sorted_test.dart
+++ b/pkg/analysis_server/test/verify_sorted_test.dart
@@ -134,7 +134,7 @@
}
var relativePath = pathContext.relative(path, from: testDirPath);
test(relativePath, () {
- var result = session.getParsedUnit2(path);
+ var result = session.getParsedUnit(path);
if (result is! ParsedUnitResult) {
fail('Could not parse $path');
}
diff --git a/pkg/analysis_server/tool/code_completion/code_metrics.dart b/pkg/analysis_server/tool/code_completion/code_metrics.dart
index 5ff17b9..565a9fd 100644
--- a/pkg/analysis_server/tool/code_completion/code_metrics.dart
+++ b/pkg/analysis_server/tool/code_completion/code_metrics.dart
@@ -1394,7 +1394,7 @@
if (file_paths.isDart(pathContext, filePath)) {
try {
var resolvedUnitResult =
- await context.currentSession.getResolvedUnit2(filePath);
+ await context.currentSession.getResolvedUnit(filePath);
//
// Check for errors that cause the file to be skipped.
//
@@ -1411,7 +1411,7 @@
continue;
}
- resolvedUnitResult.unit!.accept(collector);
+ resolvedUnitResult.unit.accept(collector);
} catch (exception) {
print('Exception caught analyzing: "$filePath"');
print(exception.toString());
diff --git a/pkg/analysis_server/tool/code_completion/completion_metrics.dart b/pkg/analysis_server/tool/code_completion/completion_metrics.dart
index d32c961..46638b1 100644
--- a/pkg/analysis_server/tool/code_completion/completion_metrics.dart
+++ b/pkg/analysis_server/tool/code_completion/completion_metrics.dart
@@ -1293,7 +1293,7 @@
for (var filePath in context.contextRoot.analyzedFiles()) {
if (file_paths.isDart(pathContext, filePath)) {
try {
- var result = await context.currentSession.getResolvedUnit2(filePath)
+ var result = await context.currentSession.getResolvedUnit(filePath)
as ResolvedUnitResult;
var analysisError = getFirstErrorOrNull(result);
@@ -1315,11 +1315,11 @@
}
for (var result in results) {
_resolvedUnitResult = result;
- var filePath = result.path!;
+ var filePath = result.path;
// Use the ExpectedCompletionsVisitor to compute the set of expected
// completions for this CompilationUnit.
final visitor = ExpectedCompletionsVisitor(filePath);
- _resolvedUnitResult.unit!.accept(visitor);
+ _resolvedUnitResult.unit.accept(visitor);
for (var expectedCompletion in visitor.expectedCompletions) {
var resolvedUnitResult = _resolvedUnitResult;
@@ -1328,14 +1328,14 @@
// have the context reanalyze the file
if (options.overlay != CompletionMetricsOptions.OVERLAY_NONE) {
var overlayContents = _getOverlayContents(
- _resolvedUnitResult.content!, expectedCompletion);
+ _resolvedUnitResult.content, expectedCompletion);
_provider.setOverlay(filePath,
content: overlayContents,
modificationStamp: overlayModificationStamp++);
context.driver.changeFile(filePath);
resolvedUnitResult = await context.currentSession
- .getResolvedUnit2(filePath) as ResolvedUnitResult;
+ .getResolvedUnit(filePath) as ResolvedUnitResult;
}
// As this point the completion suggestions are computed,
diff --git a/pkg/analysis_server/tool/code_completion/flutter_metrics.dart b/pkg/analysis_server/tool/code_completion/flutter_metrics.dart
index ee267a5..edab701 100644
--- a/pkg/analysis_server/tool/code_completion/flutter_metrics.dart
+++ b/pkg/analysis_server/tool/code_completion/flutter_metrics.dart
@@ -207,7 +207,7 @@
if (file_paths.isDart(pathContext, filePath)) {
try {
var resolvedUnitResult =
- await context.currentSession.getResolvedUnit2(filePath);
+ await context.currentSession.getResolvedUnit(filePath);
//
// Check for errors that cause the file to be skipped.
//
@@ -224,7 +224,7 @@
continue;
}
- resolvedUnitResult.unit!.accept(collector);
+ resolvedUnitResult.unit.accept(collector);
} catch (exception, stackTrace) {
print('');
print('Exception caught analyzing: "$filePath"');
diff --git a/pkg/analysis_server/tool/code_completion/implicit_type_declarations.dart b/pkg/analysis_server/tool/code_completion/implicit_type_declarations.dart
index 6b0b3c1..8494fb4 100644
--- a/pkg/analysis_server/tool/code_completion/implicit_type_declarations.dart
+++ b/pkg/analysis_server/tool/code_completion/implicit_type_declarations.dart
@@ -184,7 +184,7 @@
if (file_paths.isDart(pathContext, filePath)) {
try {
var resolvedUnitResult =
- await context.currentSession.getResolvedUnit2(filePath);
+ await context.currentSession.getResolvedUnit(filePath);
//
// Check for errors that cause the file to be skipped.
//
@@ -208,7 +208,7 @@
continue;
}
- resolvedUnitResult.unit!.accept(collector);
+ resolvedUnitResult.unit.accept(collector);
} catch (exception, stacktrace) {
print('Exception caught analyzing: "$filePath"');
print(exception);
diff --git a/pkg/analysis_server/tool/code_completion/relevance_metrics.dart b/pkg/analysis_server/tool/code_completion/relevance_metrics.dart
index 0975c8a..8a24e94 100644
--- a/pkg/analysis_server/tool/code_completion/relevance_metrics.dart
+++ b/pkg/analysis_server/tool/code_completion/relevance_metrics.dart
@@ -1940,7 +1940,7 @@
if (file_paths.isDart(pathContext, filePath)) {
try {
var resolvedUnitResult =
- await context.currentSession.getResolvedUnit2(filePath);
+ await context.currentSession.getResolvedUnit(filePath);
//
// Check for errors that cause the file to be skipped.
//
@@ -1964,7 +1964,7 @@
continue;
}
- resolvedUnitResult.unit!.accept(collector);
+ resolvedUnitResult.unit.accept(collector);
} catch (exception, stacktrace) {
print('Exception caught analyzing: "$filePath"');
print(exception);
diff --git a/pkg/analysis_server/tool/code_completion/relevance_table_generator.dart b/pkg/analysis_server/tool/code_completion/relevance_table_generator.dart
index 52b219e..3e2af94 100644
--- a/pkg/analysis_server/tool/code_completion/relevance_table_generator.dart
+++ b/pkg/analysis_server/tool/code_completion/relevance_table_generator.dart
@@ -317,7 +317,7 @@
/// Initialize this collector prior to visiting the unit in the [result].
void initializeFrom(ResolvedUnitResult result) {
- unit = result.unit!;
+ unit = result.unit;
}
@override
@@ -1459,7 +1459,7 @@
if (file_paths.isDart(pathContext, filePath)) {
try {
var resolvedUnitResult =
- await context.currentSession.getResolvedUnit2(filePath);
+ await context.currentSession.getResolvedUnit(filePath);
//
// Check for errors that cause the file to be skipped.
//
@@ -1484,7 +1484,7 @@
}
collector.initializeFrom(resolvedUnitResult);
- resolvedUnitResult.unit!.accept(collector);
+ resolvedUnitResult.unit.accept(collector);
} catch (exception, stacktrace) {
print('Exception caught analyzing: "$filePath"');
print(exception);
diff --git a/pkg/analysis_server/tool/lsp_spec/README.md b/pkg/analysis_server/tool/lsp_spec/README.md
index 5376013..bac9b69 100644
--- a/pkg/analysis_server/tool/lsp_spec/README.md
+++ b/pkg/analysis_server/tool/lsp_spec/README.md
@@ -94,8 +94,8 @@
| textDocument/codeAction (organiseImports) | ✅ | ✅ | | ✅ | ✅ |
| textDocument/codeAction (fixAll) | ✅ | ✅ | | ✅ | ✅ |
| textDocument/codeAction (refactors) | ✅ | ✅ | | ✅ | ✅ |
-| textDocument/codeAction (assists) | ✅ | ✅ | | ✅ | ✅ | Only if the client advertises `codeActionLiteralSupport` with `Refactor`
-| textDocument/codeAction (fixes) | ✅ | ✅ | | ✅ | ✅ | Only if the client advertises `codeActionLiteralSupport` with `QuickFix`
+| textDocument/codeAction (assists) | ✅ | ✅ | ✅ | ✅ | ✅ | Only if the client advertises `codeActionLiteralSupport` with `Refactor`
+| textDocument/codeAction (fixes) | ✅ | ✅ | ✅ | ✅ | ✅ | Only if the client advertises `codeActionLiteralSupport` with `QuickFix`
| textDocument/codeLens | | | | | |
| codeLens/resolve | | | | | |
| textDocument/documentLink | | | | | |
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/Location.java b/pkg/analysis_server/tool/spec/generated/java/types/Location.java
index 1df7d78..13e14bd 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/Location.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/Location.java
@@ -63,17 +63,17 @@
/**
* The one-based index of the line containing the character immediately following the range.
*/
- private final int endLine;
+ private final Integer endLine;
/**
* The one-based index of the column containing the character immediately following the range.
*/
- private final int endColumn;
+ private final Integer endColumn;
/**
* Constructor for {@link Location}.
*/
- public Location(String file, int offset, int length, int startLine, int startColumn, int endLine, int endColumn) {
+ public Location(String file, int offset, int length, int startLine, int startColumn, Integer endLine, Integer endColumn) {
this.file = file;
this.offset = offset;
this.length = length;
@@ -93,8 +93,8 @@
other.length == length &&
other.startLine == startLine &&
other.startColumn == startColumn &&
- other.endLine == endLine &&
- other.endColumn == endColumn;
+ ObjectUtilities.equals(other.endLine, endLine) &&
+ ObjectUtilities.equals(other.endColumn, endColumn);
}
return false;
}
@@ -105,8 +105,8 @@
int length = jsonObject.get("length").getAsInt();
int startLine = jsonObject.get("startLine").getAsInt();
int startColumn = jsonObject.get("startColumn").getAsInt();
- int endLine = jsonObject.get("endLine").getAsInt();
- int endColumn = jsonObject.get("endColumn").getAsInt();
+ Integer endLine = jsonObject.get("endLine") == null ? null : jsonObject.get("endLine").getAsInt();
+ Integer endColumn = jsonObject.get("endColumn") == null ? null : jsonObject.get("endColumn").getAsInt();
return new Location(file, offset, length, startLine, startColumn, endLine, endColumn);
}
@@ -125,14 +125,14 @@
/**
* The one-based index of the column containing the character immediately following the range.
*/
- public int getEndColumn() {
+ public Integer getEndColumn() {
return endColumn;
}
/**
* The one-based index of the line containing the character immediately following the range.
*/
- public int getEndLine() {
+ public Integer getEndLine() {
return endLine;
}
@@ -191,8 +191,12 @@
jsonObject.addProperty("length", length);
jsonObject.addProperty("startLine", startLine);
jsonObject.addProperty("startColumn", startColumn);
- jsonObject.addProperty("endLine", endLine);
- jsonObject.addProperty("endColumn", endColumn);
+ if (endLine != null) {
+ jsonObject.addProperty("endLine", endLine);
+ }
+ if (endColumn != null) {
+ jsonObject.addProperty("endColumn", endColumn);
+ }
return jsonObject;
}
diff --git a/pkg/analysis_server_client/lib/src/protocol/protocol_common.dart b/pkg/analysis_server_client/lib/src/protocol/protocol_common.dart
index dfbd44c..76b7a2c 100644
--- a/pkg/analysis_server_client/lib/src/protocol/protocol_common.dart
+++ b/pkg/analysis_server_client/lib/src/protocol/protocol_common.dart
@@ -2884,8 +2884,8 @@
/// "length": int
/// "startLine": int
/// "startColumn": int
-/// "endLine": int
-/// "endColumn": int
+/// "endLine": optional int
+/// "endColumn": optional int
/// }
///
/// Clients may not extend, implement or mix-in this class.
@@ -2909,14 +2909,15 @@
/// The one-based index of the line containing the character immediately
/// following the range.
- int endLine;
+ int? endLine;
/// The one-based index of the column containing the character immediately
/// following the range.
- int endColumn;
+ int? endColumn;
- Location(this.file, this.offset, this.length, this.startLine,
- this.startColumn, this.endLine, this.endColumn);
+ Location(
+ this.file, this.offset, this.length, this.startLine, this.startColumn,
+ {this.endLine, this.endColumn});
factory Location.fromJson(
JsonDecoder jsonDecoder, String jsonPath, Object? json) {
@@ -2954,21 +2955,17 @@
} else {
throw jsonDecoder.mismatch(jsonPath, 'startColumn');
}
- int endLine;
+ int? endLine;
if (json.containsKey('endLine')) {
endLine = jsonDecoder.decodeInt(jsonPath + '.endLine', json['endLine']);
- } else {
- throw jsonDecoder.mismatch(jsonPath, 'endLine');
}
- int endColumn;
+ int? endColumn;
if (json.containsKey('endColumn')) {
endColumn =
jsonDecoder.decodeInt(jsonPath + '.endColumn', json['endColumn']);
- } else {
- throw jsonDecoder.mismatch(jsonPath, 'endColumn');
}
- return Location(
- file, offset, length, startLine, startColumn, endLine, endColumn);
+ return Location(file, offset, length, startLine, startColumn,
+ endLine: endLine, endColumn: endColumn);
} else {
throw jsonDecoder.mismatch(jsonPath, 'Location', json);
}
@@ -2982,8 +2979,14 @@
result['length'] = length;
result['startLine'] = startLine;
result['startColumn'] = startColumn;
- result['endLine'] = endLine;
- result['endColumn'] = endColumn;
+ var endLine = this.endLine;
+ if (endLine != null) {
+ result['endLine'] = endLine;
+ }
+ var endColumn = this.endColumn;
+ if (endColumn != null) {
+ result['endColumn'] = endColumn;
+ }
return result;
}
diff --git a/pkg/analysis_server_client/test/verify_sorted_test.dart b/pkg/analysis_server_client/test/verify_sorted_test.dart
index dfa4c4a..f4f4c57 100644
--- a/pkg/analysis_server_client/test/verify_sorted_test.dart
+++ b/pkg/analysis_server_client/test/verify_sorted_test.dart
@@ -55,7 +55,7 @@
}
var relativePath = pathContext.relative(path, from: testDirPath);
test(relativePath, () {
- var result = session.getParsedUnit2(path);
+ var result = session.getParsedUnit(path);
if (result is! ParsedUnitResult) {
fail('Could not parse $path');
}
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index 6ccdf32..337ad88 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -1,3 +1,20 @@
+## 2.1.0-dev
+* Changed `AnalysisResult.path` to be non-nullable.
+* Changed `ParsedLibraryResult.units` to be non-nullable.
+* Changed `ResolvedLibraryResult.element` to be non-nullable.
+* Changed `ResolvedLibraryResult.units` to be non-nullable.
+* Changed `ResolvedUnitResult.content` to be non-nullable.
+* Changed `ResolvedUnitResult.unit` to be non-nullable.
+* Deprecated and renamed `AnalysisSession.getXyz2()` into `getXyz()`.
+* Changed `AnalysisDriver.results` to `Stream<Object>`.
+ It used to always produce `ResolvedUnitResult`s, but sometimes its
+ `content` and `unit` were `null`, when the result actually had only errors.
+ Now it produces either `ResolvedUnitResult`, or `ErrorsResult`, or
+ some other results that might be added in the future.
+* Added `DartType.alias` with information about instantiated type alias.
+ The type alias element and arguments are present or absent together.
+* Deprecated `DartType.aliasElement` and `DartType.aliasArguments`.
+
## 2.0.0
* Removed deprecated `Scope.lookup2()`.
* Removed deprecated setters in API of AST.
diff --git a/pkg/analyzer/doc/tutorial/ast.md b/pkg/analyzer/doc/tutorial/ast.md
index 3e9e3fa..ed449d8 100644
--- a/pkg/analyzer/doc/tutorial/ast.md
+++ b/pkg/analyzer/doc/tutorial/ast.md
@@ -55,7 +55,7 @@
```dart
void processFile(AnalysisSession session, String path) {
- var result = session.getParsedUnit2(path);
+ var result = session.getParsedUnit(path);
if (result is ParsedUnitResult) {
CompilationUnit unit = result.unit;
}
@@ -67,7 +67,7 @@
```dart
void processFile(AnalysisSession session, String path) async {
- var result = await session.getResolvedUnit2(path);
+ var result = await session.getResolvedUnit(path);
if (result is ResolvedUnitResult) {
CompilationUnit unit = result.unit;
}
diff --git a/pkg/analyzer/doc/tutorial/element.md b/pkg/analyzer/doc/tutorial/element.md
index 6c5509f..912d65b 100644
--- a/pkg/analyzer/doc/tutorial/element.md
+++ b/pkg/analyzer/doc/tutorial/element.md
@@ -46,7 +46,7 @@
```dart
void analyzeSingleFile(AnalysisSession session, String path) async {
- var result = await session.getUnitElement2(path);
+ var result = await session.getUnitElement(path);
if (result is UnitElementResult) {
CompilationUnitElement element = result.element;
}
diff --git a/pkg/analyzer/example/analyze.dart b/pkg/analyzer/example/analyze.dart
index a94f27e..72acdf5 100644
--- a/pkg/analyzer/example/analyze.dart
+++ b/pkg/analyzer/example/analyze.dart
@@ -32,7 +32,7 @@
continue;
}
- final errorsResult = await context.currentSession.getErrors2(filePath);
+ final errorsResult = await context.currentSession.getErrors(filePath);
if (errorsResult is ErrorsResult) {
for (final error in errorsResult.errors) {
if (error.errorCode.type != ErrorType.TODO) {
diff --git a/pkg/analyzer/lib/dart/analysis/results.dart b/pkg/analyzer/lib/dart/analysis/results.dart
index 287c470..13500ba 100644
--- a/pkg/analyzer/lib/dart/analysis/results.dart
+++ b/pkg/analyzer/lib/dart/analysis/results.dart
@@ -17,9 +17,7 @@
abstract class AnalysisResult {
/// The absolute and normalized path of the file that was analyzed.
/// If [state] is not [ResultState.VALID], throws [StateError].
- ///
- /// TODO(migration): should not be nullable
- String? get path;
+ String get path;
/// Return the session used to compute this result.
/// If [state] is not [ResultState.VALID], throws [StateError].
@@ -164,9 +162,7 @@
abstract class ParsedLibraryResult
implements SomeParsedLibraryResult, AnalysisResult {
/// The parsed units of the library.
- ///
- /// TODO(migration): should not be null, probably empty list
- List<ParsedUnitResult>? get units;
+ List<ParsedUnitResult> get units;
/// Return the declaration of the [element], or `null` if the [element]
/// is synthetic. Throw [ArgumentError] if the [element] is not defined in
@@ -214,13 +210,13 @@
abstract class ResolvedLibraryResult
implements SomeResolvedLibraryResult, AnalysisResult {
/// The element representing this library.
- LibraryElement? get element;
+ LibraryElement get element;
/// The type provider used when resolving the library.
TypeProvider get typeProvider;
/// The resolved units of the library.
- List<ResolvedUnitResult>? get units;
+ List<ResolvedUnitResult> get units;
/// Return the declaration of the [element], or `null` if the [element]
/// is synthetic. Throw [ArgumentError] if the [element] is not defined in
@@ -235,7 +231,7 @@
abstract class ResolvedUnitResult
implements SomeResolvedUnitResult, AnalysisResultWithErrors {
/// The content of the file that was scanned, parsed and resolved.
- String? get content;
+ String get content;
/// Return `true` if the file exists.
bool get exists;
@@ -250,7 +246,7 @@
TypeSystem get typeSystem;
/// The fully resolved compilation unit for the [content].
- CompilationUnit? get unit;
+ CompilationUnit get unit;
}
/// An indication of whether an analysis result is valid, and if not why.
diff --git a/pkg/analyzer/lib/dart/analysis/session.dart b/pkg/analyzer/lib/dart/analysis/session.dart
index 680ba37..ade0e8e 100644
--- a/pkg/analyzer/lib/dart/analysis/session.dart
+++ b/pkg/analyzer/lib/dart/analysis/session.dart
@@ -35,47 +35,105 @@
///
/// If the file cannot be analyzed by this session, then the result will have
/// a result state indicating the nature of the problem.
+ Future<SomeErrorsResult> getErrors(String path);
+
+ /// Return a future that will complete with information about the errors
+ /// contained in the file with the given absolute, normalized [path].
+ ///
+ /// If the file cannot be analyzed by this session, then the result will have
+ /// a result state indicating the nature of the problem.
+ @Deprecated('Use getErrors() instead')
Future<SomeErrorsResult> getErrors2(String path);
/// Return information about the file at the given absolute, normalized
/// [path].
+ SomeFileResult getFile(String path);
+
+ /// Return information about the file at the given absolute, normalized
+ /// [path].
+ @Deprecated('Use getFile() instead')
SomeFileResult getFile2(String path);
/// Return a future that will complete with information about the library
/// element representing the library with the given [uri].
+ Future<SomeLibraryElementResult> getLibraryByUri(String uri);
+
+ /// Return a future that will complete with information about the library
+ /// element representing the library with the given [uri].
+ @Deprecated('Use getLibraryByUri() instead')
Future<SomeLibraryElementResult> getLibraryByUri2(String uri);
/// Return information about the results of parsing units of the library file
/// with the given absolute, normalized [path].
+ SomeParsedLibraryResult getParsedLibrary(String path);
+
+ /// Return information about the results of parsing units of the library file
+ /// with the given absolute, normalized [path].
+ @Deprecated('Use getParsedLibrary() instead')
SomeParsedLibraryResult getParsedLibrary2(String path);
/// Return information about the results of parsing units of the library file
/// with the given library [element].
+ SomeParsedLibraryResult getParsedLibraryByElement(LibraryElement element);
+
+ /// Return information about the results of parsing units of the library file
+ /// with the given library [element].
+ @Deprecated('Use getParsedLibraryByElement() instead')
SomeParsedLibraryResult getParsedLibraryByElement2(LibraryElement element);
/// Return information about the results of parsing the file with the given
/// absolute, normalized [path].
+ SomeParsedUnitResult getParsedUnit(String path);
+
+ /// Return information about the results of parsing the file with the given
+ /// absolute, normalized [path].
+ @Deprecated('Use getParsedUnit() instead')
SomeParsedUnitResult getParsedUnit2(String path);
/// Return a future that will complete with information about the results of
/// resolving all of the files in the library with the given absolute,
/// normalized [path].
+ Future<SomeResolvedLibraryResult> getResolvedLibrary(String path);
+
+ /// Return a future that will complete with information about the results of
+ /// resolving all of the files in the library with the given absolute,
+ /// normalized [path].
+ @Deprecated('Use getResolvedLibrary() instead')
Future<SomeResolvedLibraryResult> getResolvedLibrary2(String path);
/// Return a future that will complete with information about the results of
/// resolving all of the files in the library with the library [element].
///
/// Throw [ArgumentError] if the [element] was not produced by this session.
+ Future<SomeResolvedLibraryResult> getResolvedLibraryByElement(
+ LibraryElement element);
+
+ /// Return a future that will complete with information about the results of
+ /// resolving all of the files in the library with the library [element].
+ ///
+ /// Throw [ArgumentError] if the [element] was not produced by this session.
+ @Deprecated('Use getResolvedLibraryByElement() instead')
Future<SomeResolvedLibraryResult> getResolvedLibraryByElement2(
LibraryElement element);
/// Return a future that will complete with information about the results of
/// resolving the file with the given absolute, normalized [path].
+ Future<SomeResolvedUnitResult> getResolvedUnit(String path);
+
+ /// Return a future that will complete with information about the results of
+ /// resolving the file with the given absolute, normalized [path].
+ @Deprecated('Use getResolvedUnit() instead')
Future<SomeResolvedUnitResult> getResolvedUnit2(String path);
/// Return a future that will complete with information about the results of
/// building the element model for the file with the given absolute,
/// normalized [path].
+ Future<SomeUnitElementResult> getUnitElement(String path);
+
+ /// Return a future that will complete with information about the results of
+ /// building the element model for the file with the given absolute,
+ /// normalized [path].
+ @Deprecated('Use getUnitElement() instead')
Future<SomeUnitElementResult> getUnitElement2(String path);
}
diff --git a/pkg/analyzer/lib/dart/analysis/utilities.dart b/pkg/analyzer/lib/dart/analysis/utilities.dart
index 3fd296d..8cee120 100644
--- a/pkg/analyzer/lib/dart/analysis/utilities.dart
+++ b/pkg/analyzer/lib/dart/analysis/utilities.dart
@@ -115,7 +115,7 @@
{required String path, ResourceProvider? resourceProvider}) async {
AnalysisContext context =
_createAnalysisContext(path: path, resourceProvider: resourceProvider);
- return await context.currentSession.getResolvedUnit2(path);
+ return await context.currentSession.getResolvedUnit(path);
}
/// Return a newly create analysis context in which the file at the given [path]
diff --git a/pkg/analyzer/lib/dart/ast/ast.dart b/pkg/analyzer/lib/dart/ast/ast.dart
index ab82e26..2df5ebb 100644
--- a/pkg/analyzer/lib/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/dart/ast/ast.dart
@@ -1061,7 +1061,7 @@
/// [PostfixExpression] when the operator is an increment operator.
///
/// Clients may not extend, implement or mix-in this class.
-abstract class CompoundAssignmentExpression {
+abstract class CompoundAssignmentExpression implements Expression {
/// The element that is used to read the value.
///
/// If this node is not a compound assignment, this element is `null`.
@@ -2471,7 +2471,7 @@
/// Return `true` if the given [name] is visible only within the library in
/// which it is declared.
- static bool isPrivateName(String name) => name.startsWith('_');
+ static bool isPrivateName(String name) => name.isNotEmpty && name[0] == "_";
}
/// The basic structure of an if element.
diff --git a/pkg/analyzer/lib/dart/element/type.dart b/pkg/analyzer/lib/dart/element/type.dart
index 44efa9f..5e9079a 100644
--- a/pkg/analyzer/lib/dart/element/type.dart
+++ b/pkg/analyzer/lib/dart/element/type.dart
@@ -28,12 +28,19 @@
///
/// Clients may not extend, implement or mix-in this class.
abstract class DartType {
+ /// If this type is an instantiation of a type alias, information about
+ /// the alias element, and the type arguments.
+ /// Otherwise return `null`.
+ InstantiatedTypeAliasElement? get alias;
+
/// If this type is an instantiation of a type alias, return the type
/// arguments used for the instantiation. Otherwise return `null`.
+ @Deprecated('Use alias instead')
List<DartType>? get aliasArguments;
/// If this type is an instantiation of a type alias, return it.
/// Otherwise return `null`.
+ @Deprecated('Use alias instead')
TypeAliasElement? get aliasElement;
/// Return the name of this type as it should appear when presented to users
@@ -245,6 +252,17 @@
FunctionType instantiate(List<DartType> argumentTypes);
}
+/// Information about an instantiated [TypeAliasElement] and the type
+/// arguments with which it is instantiated.
+abstract class InstantiatedTypeAliasElement {
+ /// The alias element that is instantiated to produce a [DartType].
+ TypeAliasElement get element;
+
+ /// The type arguments with which the [element] was instantiated.
+ /// This list will be empty if the [element] is not generic.
+ List<DartType> get typeArguments;
+}
+
/// The type introduced by either a class or an interface, or a reference to
/// such a type.
///
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 6a6fa5a..0a2b2c8 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -146,6 +146,7 @@
CompileTimeErrorCode.DEFAULT_VALUE_ON_REQUIRED_PARAMETER,
CompileTimeErrorCode.DEFERRED_IMPORT_OF_EXTENSION,
CompileTimeErrorCode.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE,
+ CompileTimeErrorCode.DISALLOWED_TYPE_INSTANTIATION_EXPRESSION,
CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_DEFAULT,
CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_NAME,
CompileTimeErrorCode.DUPLICATE_DEFINITION,
@@ -454,6 +455,7 @@
CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR_MINUS,
CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER,
CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS,
+ CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_ANONYMOUS_FUNCTION,
CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_CONSTRUCTOR,
CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_EXTENSION,
CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION,
@@ -469,6 +471,7 @@
FfiCode.EMPTY_STRUCT,
FfiCode.EXTRA_ANNOTATION_ON_STRUCT_FIELD,
FfiCode.EXTRA_SIZE_ANNOTATION_CARRAY,
+ FfiCode.FFI_NATIVE_ONLY_STATIC,
FfiCode.FIELD_IN_STRUCT_WITH_INITIALIZER,
FfiCode.FIELD_INITIALIZER_IN_STRUCT,
FfiCode.FIELD_MUST_BE_EXTERNAL_IN_STRUCT,
diff --git a/pkg/analyzer/lib/src/context/builder.dart b/pkg/analyzer/lib/src/context/builder.dart
index 9bb60eb..ec0aaa7 100644
--- a/pkg/analyzer/lib/src/context/builder.dart
+++ b/pkg/analyzer/lib/src/context/builder.dart
@@ -5,387 +5,9 @@
import 'dart:collection';
import 'dart:core';
-import 'package:analyzer/dart/analysis/declared_variables.dart';
import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/src/analysis_options/analysis_options_provider.dart';
-import 'package:analyzer/src/context/context_root.dart';
-import 'package:analyzer/src/context/packages.dart';
-import 'package:analyzer/src/dart/analysis/byte_store.dart';
-import 'package:analyzer/src/dart/analysis/driver.dart'
- show AnalysisDriver, AnalysisDriverScheduler;
-import 'package:analyzer/src/dart/analysis/file_content_cache.dart';
-import 'package:analyzer/src/dart/analysis/performance_logger.dart';
-import 'package:analyzer/src/dart/sdk/sdk.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/sdk.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/hint/sdk_constraint_extractor.dart';
-import 'package:analyzer/src/summary/package_bundle_reader.dart';
-import 'package:analyzer/src/summary/summary_sdk.dart';
-import 'package:analyzer/src/task/options.dart';
-import 'package:analyzer/src/workspace/basic.dart';
-import 'package:analyzer/src/workspace/bazel.dart';
-import 'package:analyzer/src/workspace/gn.dart';
-import 'package:analyzer/src/workspace/package_build.dart';
-import 'package:analyzer/src/workspace/pub.dart';
-import 'package:analyzer/src/workspace/workspace.dart';
import 'package:yaml/yaml.dart';
-/// A utility class used to build an analysis context for a given directory.
-///
-/// The construction of analysis contexts is as follows:
-///
-/// 1. Determine how package: URI's are to be resolved. This follows the lookup
-/// algorithm defined by the [package specification][1].
-///
-/// 2. Using the results of step 1, look in each package for an embedder file
-/// (_embedder.yaml). If one exists then it defines the SDK. If multiple such
-/// files exist then use the first one found. Otherwise, use the default SDK.
-///
-/// 3. Look for an analysis options file (`analysis_options.yaml`) and process
-/// the options in the file.
-///
-/// 4. Create a new context. Initialize its source factory based on steps 1, 2
-/// and 3. Initialize its analysis options from step 4.
-///
-/// [1]: https://github.com/dart-lang/dart_enhancement_proposals/blob/master/Accepted/0005%20-%20Package%20Specification/DEP-pkgspec.md.
-class ContextBuilder {
- /// The [ResourceProvider] by which paths are converted into [Resource]s.
- final ResourceProvider resourceProvider;
-
- /// The manager used to manage the DartSdk's that have been created so that
- /// they can be shared across contexts.
- final DartSdkManager sdkManager;
-
- /// The options used by the context builder.
- final ContextBuilderOptions builderOptions;
-
- /// The scheduler used by any analysis drivers created through this interface.
- late final AnalysisDriverScheduler analysisDriverScheduler;
-
- /// The performance log used by any analysis drivers created through this
- /// interface.
- late final PerformanceLog performanceLog;
-
- /// If `true`, additional analysis data useful for testing is stored.
- bool retainDataForTesting = false;
-
- /// The byte store used by any analysis drivers created through this interface.
- late final ByteStore byteStore;
-
- /// Whether any analysis driver created through this interface should support
- /// indexing and search.
- bool enableIndex = false;
-
- /// Sometimes `BUILD` files are not preserved, and other files are created
- /// instead. But looking for them is expensive, so we want to avoid this
- /// in cases when `BUILD` files are always available.
- bool lookForBazelBuildFileSubstitutes = true;
-
- /// Initialize a newly created builder to be ready to build a context rooted in
- /// the directory with the given [rootDirectoryPath].
- ContextBuilder(this.resourceProvider, this.sdkManager,
- {ContextBuilderOptions? options})
- : builderOptions = options ?? ContextBuilderOptions();
-
- /// Return an analysis driver that is configured correctly to analyze code in
- /// the directory with the given [path].
- AnalysisDriver buildDriver(
- ContextRoot contextRoot,
- Workspace workspace, {
- void Function(AnalysisOptionsImpl)? updateAnalysisOptions,
- FileContentCache? fileContentCache,
- }) {
- String path = contextRoot.root;
-
- var options = getAnalysisOptions(path, workspace, contextRoot: contextRoot);
-
- if (updateAnalysisOptions != null) {
- updateAnalysisOptions(options);
- }
- //_processAnalysisOptions(context, optionMap);
-
- SummaryDataStore? summaryData;
- var librarySummaryPaths = builderOptions.librarySummaryPaths;
- if (librarySummaryPaths != null) {
- summaryData = SummaryDataStore(librarySummaryPaths);
- }
-
- final sf =
- createSourceFactoryFromWorkspace(workspace, summaryData: summaryData);
-
- AnalysisDriver driver = AnalysisDriver.tmp1(
- scheduler: analysisDriverScheduler,
- logger: performanceLog,
- resourceProvider: resourceProvider,
- byteStore: byteStore,
- sourceFactory: sf,
- analysisOptions: options,
- packages: createPackageMap(
- resourceProvider: resourceProvider,
- options: builderOptions,
- rootPath: path,
- ),
- enableIndex: enableIndex,
- externalSummaries: summaryData,
- retainDataForTesting: retainDataForTesting,
- fileContentCache: fileContentCache,
- );
-
- declareVariablesInDriver(driver);
- return driver;
- }
-
-// void _processAnalysisOptions(
-// AnalysisContext context, Map<String, YamlNode> optionMap) {
-// List<OptionsProcessor> optionsProcessors =
-// AnalysisEngine.instance.optionsPlugin.optionsProcessors;
-// try {
-// optionsProcessors.forEach(
-// (OptionsProcessor p) => p.optionsProcessed(context, optionMap));
-//
-// // Fill in lint rule defaults in case lints are enabled and rules are
-// // not specified in an options file.
-// if (context.analysisOptions.lint && !containsLintRuleEntry(optionMap)) {
-// setLints(context, linterPlugin.contributedRules);
-// }
-//
-// // Ask engine to further process options.
-// if (optionMap != null) {
-// configureContextOptions(context, optionMap);
-// }
-// } on Exception catch (e) {
-// optionsProcessors.forEach((OptionsProcessor p) => p.onError(e));
-// }
-// }
-
- SourceFactory createSourceFactory(String rootPath, Workspace workspace,
- {SummaryDataStore? summaryData}) {
- DartSdk sdk = findSdk(workspace);
- if (summaryData != null && sdk is SummaryBasedDartSdk) {
- summaryData.addBundle(null, sdk.bundle);
- }
- return workspace.createSourceFactory(sdk, summaryData);
- }
-
- SourceFactory createSourceFactoryFromWorkspace(Workspace workspace,
- {SummaryDataStore? summaryData}) {
- DartSdk sdk = findSdk(workspace);
- if (summaryData != null && sdk is SummaryBasedDartSdk) {
- summaryData.addBundle(null, sdk.bundle);
- }
- return workspace.createSourceFactory(sdk, summaryData);
- }
-
- /// Add any [declaredVariables] to the list of declared variables used by the
- /// given analysis [driver].
- void declareVariablesInDriver(AnalysisDriver driver) {
- var variables = builderOptions.declaredVariables;
- if (variables.isNotEmpty) {
- driver.declaredVariables = DeclaredVariables.fromMap(variables);
- driver.configure();
- }
- }
-
- /// Return the SDK that should be used to analyze code. Use the given
- /// [workspace] to locate the SDK.
- DartSdk findSdk(Workspace? workspace) {
- String? summaryPath = builderOptions.dartSdkSummaryPath;
- if (summaryPath != null) {
- return SummaryBasedDartSdk(summaryPath, true,
- resourceProvider: resourceProvider);
- }
-
- DartSdk folderSdk;
- {
- String sdkPath = sdkManager.defaultSdkDirectory;
- SdkDescription description = SdkDescription(sdkPath);
- folderSdk = sdkManager.getSdk(description, () {
- return FolderBasedDartSdk(
- resourceProvider,
- resourceProvider.getFolder(sdkPath),
- );
- });
- }
-
- if (workspace != null) {
- var partialSourceFactory = workspace.createSourceFactory(null, null);
- var embedderYamlSource = partialSourceFactory.forUri(
- 'package:sky_engine/_embedder.yaml',
- );
- if (embedderYamlSource != null) {
- var embedderYamlPath = embedderYamlSource.fullName;
- var libFolder = resourceProvider.getFile(embedderYamlPath).parent2;
- EmbedderYamlLocator locator =
- EmbedderYamlLocator.forLibFolder(libFolder);
- Map<Folder, YamlMap> embedderMap = locator.embedderYamls;
- if (embedderMap.isNotEmpty) {
- EmbedderSdk embedderSdk = EmbedderSdk(
- resourceProvider,
- embedderMap,
- languageVersion: folderSdk.languageVersion,
- );
- return embedderSdk;
- }
- }
- }
-
- return folderSdk;
- }
-
- /// Return the analysis options that should be used to analyze code in the
- /// directory with the given [path]. Use [verbosePrint] to echo verbose
- /// information about the analysis options selection process.
- AnalysisOptionsImpl getAnalysisOptions(String path, Workspace workspace,
- {void Function(String text)? verbosePrint, ContextRoot? contextRoot}) {
- void verbose(String text) {
- if (verbosePrint != null) {
- verbosePrint(text);
- }
- }
-
- SourceFactory sourceFactory = workspace.createSourceFactory(null, null);
- AnalysisOptionsProvider optionsProvider =
- AnalysisOptionsProvider(sourceFactory);
-
- AnalysisOptionsImpl options = AnalysisOptionsImpl();
-
- var optionsPath = builderOptions.defaultAnalysisOptionsFilePath;
- if (optionsPath != null) {
- var optionsFile = resourceProvider.getFile(optionsPath);
- try {
- contextRoot?.optionsFilePath = optionsFile.path;
- var optionsMap = optionsProvider.getOptionsFromFile(optionsFile);
- applyToAnalysisOptions(options, optionsMap);
- verbose('Loaded analysis options from ${optionsFile.path}');
- } catch (e) {
- // Ignore exceptions thrown while trying to load the options file.
- verbose('Exception: $e\n when loading ${optionsFile.path}');
- }
- } else {
- verbose('Using default analysis options');
- }
-
- var pubspecFile = _findPubspecFile(path);
- if (pubspecFile != null) {
- var extractor = SdkConstraintExtractor(pubspecFile);
- var sdkVersionConstraint = extractor.constraint();
- if (sdkVersionConstraint != null) {
- options.sdkVersionConstraint = sdkVersionConstraint;
- }
- }
-
- return options;
- }
-
- /// Return the `pubspec.yaml` file that should be used when analyzing code in
- /// the directory with the given [path], possibly `null`.
- File? _findPubspecFile(String path) {
- var folder = resourceProvider.getFolder(path);
- for (var current in folder.withAncestors) {
- var file = current.getChildAssumingFile('pubspec.yaml');
- if (file.exists) {
- return file;
- }
- }
- }
-
- /// Return [Packages] to analyze a resource with the [rootPath].
- static Packages createPackageMap({
- required ResourceProvider resourceProvider,
- required ContextBuilderOptions options,
- required String rootPath,
- }) {
- var configPath = options.defaultPackageFilePath;
- if (configPath != null) {
- var configFile = resourceProvider.getFile(configPath);
- return parsePackagesFile(resourceProvider, configFile);
- } else {
- var resource = resourceProvider.getResource(rootPath);
- return findPackagesFrom(resourceProvider, resource);
- }
- }
-
- /// If [packages] is provided, it will be used for the [Workspace],
- /// otherwise the packages file from [options] will be used, or discovered
- /// from [rootPath].
- ///
- /// TODO(scheglov) Make [packages] required, remove [options] and discovery.
- static Workspace createWorkspace({
- required ResourceProvider resourceProvider,
- required ContextBuilderOptions options,
- Packages? packages,
- required String rootPath,
- bool lookForBazelBuildFileSubstitutes = true,
- }) {
- packages ??= ContextBuilder.createPackageMap(
- resourceProvider: resourceProvider,
- options: options,
- rootPath: rootPath,
- );
- var packageMap = <String, List<Folder>>{};
- for (var package in packages.packages) {
- packageMap[package.name] = [package.libFolder];
- }
-
- if (_hasPackageFileInPath(resourceProvider, rootPath)) {
- // A Bazel or Gn workspace that includes a '.packages' file is treated
- // like a normal (non-Bazel/Gn) directory. But may still use
- // package:build or Pub.
- return PackageBuildWorkspace.find(
- resourceProvider, packageMap, rootPath) ??
- PubWorkspace.find(resourceProvider, packageMap, rootPath) ??
- BasicWorkspace.find(resourceProvider, packageMap, rootPath);
- }
- Workspace? workspace = BazelWorkspace.find(resourceProvider, rootPath,
- lookForBuildFileSubstitutes: lookForBazelBuildFileSubstitutes);
- workspace ??= GnWorkspace.find(resourceProvider, rootPath);
- workspace ??=
- PackageBuildWorkspace.find(resourceProvider, packageMap, rootPath);
- workspace ??= PubWorkspace.find(resourceProvider, packageMap, rootPath);
- workspace ??= BasicWorkspace.find(resourceProvider, packageMap, rootPath);
- return workspace;
- }
-
- /// Return `true` if either the directory at [rootPath] or a parent of that
- /// directory contains a `.packages` file.
- static bool _hasPackageFileInPath(
- ResourceProvider resourceProvider, String rootPath) {
- var folder = resourceProvider.getFolder(rootPath);
- return folder.withAncestors.any((current) {
- return current.getChildAssumingFile('.packages').exists;
- });
- }
-}
-
-/// Options used by a [ContextBuilder].
-class ContextBuilderOptions {
- /// The file path of the file containing the summary of the SDK that should be
- /// used to "analyze" the SDK. This option should only be specified by
- /// command-line tools such as 'dartanalyzer' or 'ddc'.
- String? dartSdkSummaryPath;
-
- /// The file path of the analysis options file that should be used in place of
- /// any file in the root directory or a parent of the root directory, or `null`
- /// if the normal lookup mechanism should be used.
- String? defaultAnalysisOptionsFilePath;
-
- /// A table mapping variable names to values for the declared variables.
- Map<String, String> declaredVariables = {};
-
- /// The file path of the .packages file that should be used in place of any
- /// file found using the normal (Package Specification DEP) lookup mechanism,
- /// or `null` if the normal lookup mechanism should be used.
- String? defaultPackageFilePath;
-
- /// A list of the paths of summary files that are to be used, or `null` if no
- /// summary information is available.
- List<String>? librarySummaryPaths;
-
- /// Initialize a newly created set of options
- ContextBuilderOptions();
-}
-
/// Given a package map, check in each package's lib directory for the existence
/// of an `_embedder.yaml` file. If the file contains a top level YamlMap, it
/// will be added to the [embedderYamls] map.
diff --git a/pkg/analyzer/lib/src/dart/analysis/context_builder.dart b/pkg/analyzer/lib/src/dart/analysis/context_builder.dart
index 0ca758d..3e2f98b 100644
--- a/pkg/analyzer/lib/src/dart/analysis/context_builder.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/context_builder.dart
@@ -7,9 +7,9 @@
import 'package:analyzer/dart/analysis/declared_variables.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/file_system/physical_file_system.dart';
-import 'package:analyzer/src/context/builder.dart' as old
- show ContextBuilder, ContextBuilderOptions;
-import 'package:analyzer/src/context/context_root.dart' as old;
+import 'package:analyzer/src/analysis_options/analysis_options_provider.dart';
+import 'package:analyzer/src/context/builder.dart' show EmbedderYamlLocator;
+import 'package:analyzer/src/context/packages.dart';
import 'package:analyzer/src/dart/analysis/byte_store.dart'
show ByteStore, MemoryByteStore;
import 'package:analyzer/src/dart/analysis/driver.dart'
@@ -18,8 +18,15 @@
import 'package:analyzer/src/dart/analysis/file_content_cache.dart';
import 'package:analyzer/src/dart/analysis/performance_logger.dart'
show PerformanceLog;
+import 'package:analyzer/src/dart/sdk/sdk.dart';
import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
-import 'package:analyzer/src/generated/sdk.dart' show DartSdkManager;
+import 'package:analyzer/src/generated/sdk.dart' show DartSdk;
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/hint/sdk_constraint_extractor.dart';
+import 'package:analyzer/src/summary/package_bundle_reader.dart';
+import 'package:analyzer/src/summary/summary_sdk.dart';
+import 'package:analyzer/src/task/options.dart';
+import 'package:analyzer/src/workspace/workspace.dart';
import 'package:cli_util/cli_util.dart';
/// An implementation of a context builder.
@@ -57,46 +64,57 @@
byteStore ??= MemoryByteStore();
performanceLog ??= PerformanceLog(StringBuffer());
- DartSdkManager sdkManager = DartSdkManager(sdkPath);
-
if (scheduler == null) {
scheduler = AnalysisDriverScheduler(performanceLog);
scheduler.start();
}
- // TODO(brianwilkerson) Move the required implementation from the old
- // ContextBuilder to this class and remove the old class.
- old.ContextBuilderOptions options = old.ContextBuilderOptions();
- if (declaredVariables != null) {
- options.declaredVariables = _toMap(declaredVariables);
- }
- if (sdkSummaryPath != null) {
- options.dartSdkSummaryPath = sdkSummaryPath;
- }
+ SummaryDataStore? summaryData;
if (librarySummaryPaths != null) {
- options.librarySummaryPaths = librarySummaryPaths;
+ summaryData = SummaryDataStore(librarySummaryPaths);
}
- options.defaultAnalysisOptionsFilePath = contextRoot.optionsFile?.path;
- options.defaultPackageFilePath = contextRoot.packagesFile?.path;
- old.ContextBuilder builder =
- old.ContextBuilder(resourceProvider, sdkManager, options: options);
- builder.analysisDriverScheduler = scheduler;
- builder.byteStore = byteStore;
- builder.enableIndex = enableIndex;
- builder.performanceLog = performanceLog;
- builder.retainDataForTesting = retainDataForTesting;
-
- old.ContextRoot oldContextRoot = old.ContextRoot(
- contextRoot.root.path, contextRoot.excludedPaths.toList(),
- pathContext: resourceProvider.pathContext);
- AnalysisDriver driver = builder.buildDriver(
- oldContextRoot,
- contextRoot.workspace,
- fileContentCache: fileContentCache,
- updateAnalysisOptions: updateAnalysisOptions,
+ var workspace = contextRoot.workspace;
+ var sdk = _createSdk(
+ workspace: workspace,
+ sdkPath: sdkPath,
+ sdkSummaryPath: sdkSummaryPath,
);
+ // TODO(scheglov) Ensure that "librarySummaryPaths" not null only
+ // when "sdkSummaryPath" is not null.
+ if (sdk is SummaryBasedDartSdk) {
+ summaryData?.addBundle(null, sdk.bundle);
+ }
+
+ var sourceFactory = workspace.createSourceFactory(sdk, summaryData);
+
+ var options = _getAnalysisOptions(contextRoot, sourceFactory);
+ if (updateAnalysisOptions != null) {
+ updateAnalysisOptions(options);
+ }
+
+ var driver = AnalysisDriver.tmp1(
+ scheduler: scheduler,
+ logger: performanceLog,
+ resourceProvider: resourceProvider,
+ byteStore: byteStore,
+ sourceFactory: sourceFactory,
+ analysisOptions: options,
+ packages: _createPackageMap(
+ contextRoot: contextRoot,
+ ),
+ enableIndex: enableIndex,
+ externalSummaries: summaryData,
+ retainDataForTesting: retainDataForTesting,
+ fileContentCache: fileContentCache,
+ );
+
+ if (declaredVariables != null) {
+ driver.declaredVariables = declaredVariables;
+ driver.configure();
+ }
+
// AnalysisDriver reports results into streams.
// We need to drain these streams to avoid memory leak.
if (drainStreams) {
@@ -111,13 +129,103 @@
return context;
}
- /// Convert the [declaredVariables] into a map for use with the old context
- /// builder.
- Map<String, String> _toMap(DeclaredVariables declaredVariables) {
- Map<String, String> map = <String, String>{};
- for (String name in declaredVariables.variableNames) {
- map[name] = declaredVariables.get(name)!;
+ /// Return [Packages] to analyze the [contextRoot].
+ ///
+ /// TODO(scheglov) Get [Packages] from [Workspace]?
+ Packages _createPackageMap({
+ required ContextRoot contextRoot,
+ }) {
+ var configFile = contextRoot.packagesFile;
+ if (configFile != null) {
+ return parsePackagesFile(resourceProvider, configFile);
+ } else {
+ return Packages.empty;
}
- return map;
+ }
+
+ /// Return the SDK that that should be used to analyze code.
+ DartSdk _createSdk({
+ required Workspace workspace,
+ String? sdkPath,
+ String? sdkSummaryPath,
+ }) {
+ if (sdkSummaryPath != null) {
+ return SummaryBasedDartSdk(sdkSummaryPath, true,
+ resourceProvider: resourceProvider);
+ }
+
+ var folderSdk = FolderBasedDartSdk(
+ resourceProvider,
+ resourceProvider.getFolder(sdkPath!),
+ );
+
+ {
+ // TODO(scheglov) We already had partial SourceFactory in ContextLocatorImpl.
+ var partialSourceFactory = workspace.createSourceFactory(null, null);
+ var embedderYamlSource = partialSourceFactory.forUri(
+ 'package:sky_engine/_embedder.yaml',
+ );
+ if (embedderYamlSource != null) {
+ var embedderYamlPath = embedderYamlSource.fullName;
+ var libFolder = resourceProvider.getFile(embedderYamlPath).parent2;
+ var locator = EmbedderYamlLocator.forLibFolder(libFolder);
+ var embedderMap = locator.embedderYamls;
+ if (embedderMap.isNotEmpty) {
+ return EmbedderSdk(
+ resourceProvider,
+ embedderMap,
+ languageVersion: folderSdk.languageVersion,
+ );
+ }
+ }
+ }
+
+ return folderSdk;
+ }
+
+ /// Return the `pubspec.yaml` file that should be used when analyzing code in
+ /// the [contextRoot], possibly `null`.
+ ///
+ /// TODO(scheglov) Get it from [Workspace]?
+ File? _findPubspecFile(ContextRoot contextRoot) {
+ for (var current in contextRoot.root.withAncestors) {
+ var file = current.getChildAssumingFile('pubspec.yaml');
+ if (file.exists) {
+ return file;
+ }
+ }
+ }
+
+ /// Return the analysis options that should be used to analyze code in the
+ /// [contextRoot].
+ ///
+ /// TODO(scheglov) We have already loaded it once in [ContextLocatorImpl].
+ AnalysisOptionsImpl _getAnalysisOptions(
+ ContextRoot contextRoot,
+ SourceFactory sourceFactory,
+ ) {
+ var options = AnalysisOptionsImpl();
+
+ var optionsFile = contextRoot.optionsFile;
+ if (optionsFile != null) {
+ try {
+ var provider = AnalysisOptionsProvider(sourceFactory);
+ var optionsMap = provider.getOptionsFromFile(optionsFile);
+ applyToAnalysisOptions(options, optionsMap);
+ } catch (e) {
+ // ignore
+ }
+ }
+
+ var pubspecFile = _findPubspecFile(contextRoot);
+ if (pubspecFile != null) {
+ var extractor = SdkConstraintExtractor(pubspecFile);
+ var sdkVersionConstraint = extractor.constraint();
+ if (sdkVersionConstraint != null) {
+ options.sdkVersionConstraint = sdkVersionConstraint;
+ }
+ }
+
+ return options;
}
}
diff --git a/pkg/analyzer/lib/src/dart/analysis/context_locator.dart b/pkg/analyzer/lib/src/dart/analysis/context_locator.dart
index c1dfa14..7927eca 100644
--- a/pkg/analyzer/lib/src/dart/analysis/context_locator.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/context_locator.dart
@@ -10,14 +10,16 @@
import 'package:analyzer/file_system/physical_file_system.dart'
show PhysicalResourceProvider;
import 'package:analyzer/src/analysis_options/analysis_options_provider.dart';
-import 'package:analyzer/src/context/builder.dart' as old;
-import 'package:analyzer/src/context/builder.dart';
import 'package:analyzer/src/context/packages.dart';
import 'package:analyzer/src/dart/analysis/context_root.dart';
import 'package:analyzer/src/task/options.dart';
import 'package:analyzer/src/util/file_paths.dart' as file_paths;
import 'package:analyzer/src/util/yaml.dart';
import 'package:analyzer/src/workspace/basic.dart';
+import 'package:analyzer/src/workspace/bazel.dart';
+import 'package:analyzer/src/workspace/gn.dart';
+import 'package:analyzer/src/workspace/package_build.dart';
+import 'package:analyzer/src/workspace/pub.dart';
import 'package:analyzer/src/workspace/workspace.dart';
import 'package:glob/glob.dart';
import 'package:path/path.dart';
@@ -366,12 +368,34 @@
packages = Packages.empty;
}
- return old.ContextBuilder.createWorkspace(
- resourceProvider: resourceProvider,
- packages: packages,
- options: ContextBuilderOptions(), // TODO(scheglov) remove it
- rootPath: folder.path,
- );
+ // TODO(scheglov) Can we use Packages instead?
+ var packageMap = <String, List<Folder>>{};
+ for (var package in packages.packages) {
+ packageMap[package.name] = [package.libFolder];
+ }
+
+ var rootPath = folder.path;
+
+ // TODO(scheglov) Do we need this?
+ if (_hasPackageFileInPath(rootPath)) {
+ // A Bazel or Gn workspace that includes a '.packages' file is treated
+ // like a normal (non-Bazel/Gn) directory. But may still use
+ // package:build or Pub.
+ return PackageBuildWorkspace.find(
+ resourceProvider, packageMap, rootPath) ??
+ PubWorkspace.find(resourceProvider, packageMap, rootPath) ??
+ BasicWorkspace.find(resourceProvider, packageMap, rootPath);
+ }
+
+ Workspace? workspace;
+ workspace = BazelWorkspace.find(resourceProvider, rootPath,
+ lookForBuildFileSubstitutes: false);
+ workspace ??= GnWorkspace.find(resourceProvider, rootPath);
+ workspace ??=
+ PackageBuildWorkspace.find(resourceProvider, packageMap, rootPath);
+ workspace ??= PubWorkspace.find(resourceProvider, packageMap, rootPath);
+ workspace ??= BasicWorkspace.find(resourceProvider, packageMap, rootPath);
+ return workspace;
}
File? _findDefaultOptionsFile(Workspace workspace) {
@@ -491,6 +515,15 @@
return _getFile(folder, file_paths.dotPackages);
}
+ /// Return `true` if either the directory at [rootPath] or a parent of that
+ /// directory contains a `.packages` file.
+ bool _hasPackageFileInPath(String rootPath) {
+ var folder = resourceProvider.getFolder(rootPath);
+ return folder.withAncestors.any((current) {
+ return current.getChildAssumingFile('.packages').exists;
+ });
+ }
+
/// Add to the given lists of [folders] and [files] all of the resources in
/// the given list of [paths] that exist and are not contained within one of
/// the folders.
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 79bc69f..ed78b2e 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -8,7 +8,6 @@
import 'package:analyzer/dart/analysis/analysis_context.dart' as api;
import 'package:analyzer/dart/analysis/declared_variables.dart';
import 'package:analyzer/dart/analysis/results.dart';
-import 'package:analyzer/dart/analysis/session.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/error/listener.dart';
@@ -81,7 +80,7 @@
/// TODO(scheglov) Clean up the list of implicitly analyzed files.
class AnalysisDriver implements AnalysisDriverGeneric {
/// The version of data format, should be incremented on every format change.
- static const int DATA_VERSION = 161;
+ static const int DATA_VERSION = 167;
/// The number of exception contexts allowed to write. Once this field is
/// zero, we stop writing any new exception contexts in this process.
@@ -201,10 +200,10 @@
final _partsToAnalyze = <String>{};
/// The controller for the [results] stream.
- final _resultController = StreamController<ResolvedUnitResult>();
+ final _resultController = StreamController<Object>();
/// The stream that will be written to when analysis results are produced.
- late final Stream<ResolvedUnitResult> _onResults;
+ late final Stream<Object> _onResults;
/// Resolution signatures of the most recently produced results for files.
final Map<String, String> _lastProducedSignatures = {};
@@ -383,6 +382,13 @@
/// an analysis result is produced for every added file prior to the next time
/// the analysis state transitions to "idle".
///
+ /// [ResolvedUnitResult]s are produced for:
+ /// 1. Files requested using [getResult2].
+ /// 2. Files passed to [addFile] which are also in [priorityFiles].
+ ///
+ /// [ErrorsResult]s are produced for:
+ /// 1. Files passed to [addFile] which are not in [priorityFiles].
+ ///
/// At least one analysis result is produced for every file passed to
/// [addFile] or [changeFile] prior to the next time the analysis state
/// transitions to "idle", unless the file is later removed from analysis
@@ -394,7 +400,7 @@
///
/// Results might be produced even for files that have never been added
/// using [addFile], for example when [getResult2] was called for a file.
- Stream<ResolvedUnitResult> get results => _onResults;
+ Stream<Object> get results => _onResults;
/// Return the search support for the driver.
Search get search => _search;
@@ -463,7 +469,6 @@
_unitElementRequestedParts.isNotEmpty) {
return AnalysisDriverPriority.general;
}
- clearLibraryContext();
return AnalysisDriverPriority.nothing;
}
@@ -994,11 +999,11 @@
}
// Notify the completers.
_requestedFiles.remove(path)!.forEach((completer) {
- completer.complete(result);
+ completer.complete(result.unitResult!);
});
// Remove from to be analyzed and produce it now.
_fileTracker.fileWasAnalyzed(path);
- _resultController.add(result);
+ _resultController.add(result.unitResult!);
} catch (exception, stackTrace) {
_reportException(path, exception, stackTrace);
_fileTracker.fileWasAnalyzed(path);
@@ -1123,7 +1128,7 @@
if (result == null) {
_partsToAnalyze.add(path);
} else {
- _resultController.add(result);
+ _resultController.add(result.unitResult!);
}
} catch (exception, stackTrace) {
_reportException(path, exception, stackTrace);
@@ -1144,12 +1149,12 @@
withUnit: false, skipIfSameSignature: true);
if (result == null) {
_partsToAnalyze.add(path);
- } else if (result == AnalysisResult._UNCHANGED) {
+ } else if (result.isUnchangedErrors) {
// We found that the set of errors is the same as we produced the
// last time, so we don't need to produce it again now.
} else {
- _resultController.add(result);
- _lastProducedSignatures[result.path!] = result._signature;
+ _resultController.add(result.errorsResult!);
+ _lastProducedSignatures[path] = result._signature;
}
} catch (exception, stackTrace) {
_reportException(path, exception, stackTrace);
@@ -1168,11 +1173,11 @@
withUnit: true, asIsIfPartWithoutLibrary: true)!;
// Notify the completers.
_requestedParts.remove(path)!.forEach((completer) {
- completer.complete(result);
+ completer.complete(result.unitResult!);
});
// Remove from to be analyzed and produce it now.
_partsToAnalyze.remove(path);
- _resultController.add(result);
+ _resultController.add(result.unitResult!);
} catch (exception, stackTrace) {
_reportException(path, exception, stackTrace);
_partsToAnalyze.remove(path);
@@ -1189,10 +1194,16 @@
String path = _partsToAnalyze.first;
_partsToAnalyze.remove(path);
try {
- var result = _computeAnalysisResult(path,
- withUnit: _priorityFiles.contains(path),
- asIsIfPartWithoutLibrary: true)!;
- _resultController.add(result);
+ var withUnit = _priorityFiles.contains(path);
+ if (withUnit) {
+ var result = _computeAnalysisResult(path,
+ withUnit: true, asIsIfPartWithoutLibrary: true)!;
+ _resultController.add(result.unitResult!);
+ } else {
+ var result = _computeAnalysisResult(path,
+ withUnit: false, asIsIfPartWithoutLibrary: true)!;
+ _resultController.add(result.errorsResult!);
+ }
} catch (exception, stackTrace) {
_reportException(path, exception, stackTrace);
_clearLibraryContextAfterException();
@@ -1294,8 +1305,9 @@
/// Return the cached or newly computed analysis result of the file with the
/// given [path].
///
- /// The result will have the fully resolved unit and will always be newly
- /// compute only if [withUnit] is `true`.
+ /// The [withUnit] flag control which result will be returned.
+ /// When `true`, [AnalysisResult.unitResult] will be set.
+ /// Otherwise [AnalysisResult.errorsResult] will be set.
///
/// Return `null` if the file is a part of an unknown library, so cannot be
/// analyzed yet. But [asIsIfPartWithoutLibrary] is `true`, then the file is
@@ -1305,7 +1317,7 @@
/// the resolved signature of the file in its library is the same as the one
/// that was the most recently produced to the client.
AnalysisResult? _computeAnalysisResult(String path,
- {bool withUnit = false,
+ {required bool withUnit,
bool asIsIfPartWithoutLibrary = false,
bool skipIfSameSignature = false}) {
FileState file = _fsState.getFileForPath(path);
@@ -1328,7 +1340,7 @@
if (skipIfSameSignature) {
assert(!withUnit);
if (_lastProducedSignatures[path] == signature) {
- return AnalysisResult._UNCHANGED;
+ return AnalysisResult.unchangedErrors(signature);
}
}
@@ -1388,7 +1400,7 @@
content: withUnit ? file.content : null,
resolvedUnit: withUnit ? resolvedUnit : null);
if (withUnit && _priorityFiles.contains(path)) {
- _priorityResults[path] = result;
+ _priorityResults[path] = result.unitResult!;
}
return result;
} catch (exception, stackTrace) {
@@ -1410,8 +1422,7 @@
return null;
}
- return ErrorsResultImpl(currentSession, path, analysisResult.uri,
- analysisResult.lineInfo, analysisResult.isPart, analysisResult.errors);
+ return analysisResult.errorsResult;
}
AnalysisDriverUnitIndex _computeIndex(String path) {
@@ -1660,7 +1671,9 @@
var unit = AnalysisDriverResolvedUnit.fromBuffer(bytes);
List<AnalysisError> errors = _getErrorsFromSerialized(file, unit.errors);
_updateHasErrorOrWarningFlag(file, errors);
- return AnalysisResult(
+ var index = unit.index!;
+ if (content != null && resolvedUnit != null) {
+ var resolvedUnitResult = ResolvedUnitResultImpl(
currentSession,
file.path,
file.uri,
@@ -1668,10 +1681,21 @@
content,
file.lineInfo,
file.isPart,
- signature,
resolvedUnit,
errors,
- unit.index);
+ );
+ return AnalysisResult.unit(signature, resolvedUnitResult, index);
+ } else {
+ var errorsResult = ErrorsResultImpl(
+ currentSession,
+ file.path,
+ file.uri,
+ file.lineInfo,
+ file.isPart,
+ errors,
+ );
+ return AnalysisResult.errors(signature, errorsResult, index);
+ }
}
/// Return [AnalysisError]s for the given [serialized] errors.
@@ -1720,21 +1744,19 @@
AnalysisResult _newMissingDartLibraryResult(
FileState file, String missingUri) {
// TODO(scheglov) Find a better way to report this.
- return AnalysisResult(
- currentSession,
- file.path,
- file.uri,
- file.exists,
- null,
- file.lineInfo,
- file.isPart,
- 'missing',
- null,
- [
- AnalysisError(file.source, 0, 0,
- CompileTimeErrorCode.MISSING_DART_LIBRARY, [missingUri])
- ],
- null);
+ var errorsResult = ErrorsResultImpl(
+ currentSession,
+ file.path,
+ file.uri,
+ file.lineInfo,
+ file.isPart,
+ [
+ AnalysisError(file.source, 0, 0,
+ CompileTimeErrorCode.MISSING_DART_LIBRARY, [missingUri])
+ ],
+ );
+ return AnalysisResult.errors(
+ 'missing', errorsResult, AnalysisDriverUnitIndexBuilder());
}
void _reportException(String path, Object exception, StackTrace stackTrace) {
@@ -2115,38 +2137,50 @@
/// The result of analyzing of a single file.
///
-/// These results are self-consistent, i.e. [content], [lineInfo], the
-/// resolved [unit] correspond to each other. All referenced elements, even
+/// These results are self-consistent, i.e. the file content, line info, the
+/// resolved unit correspond to each other. All referenced elements, even
/// external ones, are also self-consistent. But none of the results is
/// guaranteed to be consistent with the state of the files.
///
/// Every result is independent, and is not guaranteed to be consistent with
/// any previously returned result, even inside of the same library.
-class AnalysisResult extends ResolvedUnitResultImpl {
- static final _UNCHANGED = _UnchangedAnalysisResult();
-
+class AnalysisResult {
/// The signature of the result based on the content of the file, and the
/// transitive closure of files imported and exported by the library of
/// the requested file.
final String _signature;
+ final bool isUnchangedErrors;
+
+ /// Is not `null` if this result is a result with errors.
+ /// Otherwise is `null`, and usually [unitResult] is set.
+ final ErrorsResultImpl? errorsResult;
+
+ /// Is not `null` if this result is a result with a resolved unit.
+ /// Otherwise is `null`, and usually [errorsResult] is set.
+ final ResolvedUnitResultImpl? unitResult;
+
/// The index of the unit.
final AnalysisDriverUnitIndex? _index;
- AnalysisResult(
- AnalysisSession session,
- String path,
- Uri uri,
- bool exists,
- String? content,
- LineInfo lineInfo,
- bool isPart,
- this._signature,
- CompilationUnit? unit,
- List<AnalysisError> errors,
- this._index)
- : super(session, path, uri, exists, content, lineInfo, isPart, unit,
- errors);
+ AnalysisResult.errors(
+ this._signature, this.errorsResult, AnalysisDriverUnitIndex index)
+ : isUnchangedErrors = false,
+ unitResult = null,
+ _index = index;
+
+ AnalysisResult.unchangedErrors(this._signature)
+ : isUnchangedErrors = true,
+ errorsResult = null,
+ unitResult = null,
+ _index = null;
+
+ AnalysisResult.unit(this._signature, ResolvedUnitResultImpl unitResult,
+ AnalysisDriverUnitIndex index)
+ : isUnchangedErrors = false,
+ errorsResult = null,
+ unitResult = unitResult,
+ _index = index;
}
/// An object that watches for the creation and removal of analysis drivers.
@@ -2488,8 +2522,3 @@
return true;
}
}
-
-class _UnchangedAnalysisResult implements AnalysisResult {
- @override
- noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-}
diff --git a/pkg/analyzer/lib/src/dart/analysis/file_state.dart b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
index 40b742f..b21980f 100644
--- a/pkg/analyzer/lib/src/dart/analysis/file_state.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
@@ -414,12 +414,8 @@
/// Read the file content and ensure that all of the file properties are
/// consistent with the read content, including API signature.
///
- /// If [allowCached] is `true`, don't read the content of the file if it
- /// is already cached (in another [FileSystemState], because otherwise we
- /// would not create this new instance of [FileState] and refresh it).
- ///
/// Return `true` if the API signature changed since the last refresh.
- bool refresh({bool allowCached = false}) {
+ bool refresh() {
counterFileStateRefresh++;
var timerWasRunning = timerFileStateRefresh.isRunning;
@@ -429,10 +425,6 @@
_invalidateCurrentUnresolvedData();
- if (!allowCached) {
- _fsState.markFileForReading(path);
- }
-
{
var rawFileState = _fsState._fileContentCache.get(path);
_content = rawFileState.content;
@@ -862,7 +854,7 @@
_uriToFile[uri] = file;
_addFileWithPath(path, file);
_pathToCanonicalFile[path] = file;
- file.refresh(allowCached: true);
+ file.refresh();
}
return file;
}
@@ -908,7 +900,7 @@
packageLanguageVersion);
_uriToFile[uri] = file;
_addFileWithPath(path, file);
- file.refresh(allowCached: true);
+ file.refresh();
}
return Either2.t1(file);
}
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
index e10f9be..af4dab4 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
@@ -332,7 +332,6 @@
var enableTiming = _analysisOptions.enableTiming;
var nodeRegistry = NodeLintRegistry(enableTiming);
- var visitors = <AstVisitor>[];
var context = LinterContextImpl(
allUnits,
@@ -354,14 +353,9 @@
// Run lints that handle specific node types.
unit.accept(LinterVisitor(
- nodeRegistry, ExceptionHandlingDelegatingAstVisitor.logException));
-
- // Run visitor based lints.
- if (visitors.isNotEmpty) {
- AstVisitor visitor = ExceptionHandlingDelegatingAstVisitor(
- visitors, ExceptionHandlingDelegatingAstVisitor.logException);
- unit.accept(visitor);
- }
+ nodeRegistry,
+ LinterExceptionHandler(_analysisOptions.propagateLinterExceptions)
+ .logException));
}
void _computeVerifyErrors(FileState file, CompilationUnit unit) {
diff --git a/pkg/analyzer/lib/src/dart/analysis/results.dart b/pkg/analyzer/lib/src/dart/analysis/results.dart
index bcd371c..9db2ec6 100644
--- a/pkg/analyzer/lib/src/dart/analysis/results.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/results.dart
@@ -8,7 +8,6 @@
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type_provider.dart';
-import 'package:analyzer/dart/element/type_system.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/source/line_info.dart';
import 'package:analyzer/src/dart/element/type_system.dart';
@@ -18,7 +17,7 @@
final AnalysisSession session;
@override
- final String? path;
+ final String path;
@override
final Uri uri;
@@ -74,130 +73,17 @@
LibraryElementResultImpl(this.element);
}
-/// The implementation of [AnalysisResult] when not [ResultState.VALID].
-class NotValidAnalysisResultImpl implements AnalysisResult {
- @override
- final ResultState state;
-
- NotValidAnalysisResultImpl(this.state);
-
- @override
- String? get path {
- throw StateError('This result is not valid');
- }
-
- @override
- AnalysisSession get session {
- throw StateError('This result is not valid');
- }
-
- @override
- Uri get uri {
- throw StateError('This result is not valid');
- }
-}
-
-/// The implementation of [ErrorsResult] when not [ResultState.VALID].
-class NotValidErrorsResultImpl extends NotValidFileResultImpl
- implements ErrorsResult {
- NotValidErrorsResultImpl(ResultState state) : super(state);
-
- @override
- List<AnalysisError> get errors {
- throw StateError('This result is not valid');
- }
-}
-
-/// The implementation of [FileResult] when not [ResultState.VALID].
-class NotValidFileResultImpl extends NotValidAnalysisResultImpl
- implements FileResult {
- NotValidFileResultImpl(ResultState state) : super(state);
-
- @override
- bool get isPart {
- throw StateError('This result is not valid');
- }
-
- @override
- LineInfo get lineInfo {
- throw StateError('This result is not valid');
- }
-}
-
-/// The implementation of [ResolvedUnitResult] when not [ResultState.VALID].
-class NotValidResolvedUnitResultImpl extends NotValidFileResultImpl
- implements ResolvedUnitResult {
- NotValidResolvedUnitResultImpl(ResultState state) : super(state);
-
- @override
- String? get content {
- throw StateError('This result is not valid');
- }
-
- @override
- List<AnalysisError> get errors {
- throw StateError('This result is not valid');
- }
-
- @override
- bool get exists {
- throw StateError('This result is not valid');
- }
-
- @override
- LibraryElement get libraryElement {
- throw StateError('This result is not valid');
- }
-
- @override
- TypeProvider get typeProvider {
- throw StateError('This result is not valid');
- }
-
- @override
- TypeSystem get typeSystem {
- throw StateError('This result is not valid');
- }
-
- @override
- CompilationUnit? get unit {
- throw StateError('This result is not valid');
- }
-}
-
-/// The implementation of [UnitElementResult] when not [ResultState.VALID].
-class NotValidUnitElementResultImpl extends NotValidAnalysisResultImpl
- implements UnitElementResult {
- NotValidUnitElementResultImpl(ResultState state) : super(state);
-
- @override
- CompilationUnitElement get element {
- throw StateError('This result is not valid');
- }
-
- @override
- String get signature {
- throw StateError('This result is not valid');
- }
-}
-
class ParsedLibraryResultImpl extends AnalysisResultImpl
implements ParsedLibraryResult {
@override
- final List<ParsedUnitResult>? units;
+ final List<ParsedUnitResult> units;
ParsedLibraryResultImpl(
- AnalysisSession session, String? path, Uri uri, this.units)
+ AnalysisSession session, String path, Uri uri, this.units)
: super(session, path, uri);
- ParsedLibraryResultImpl.external(AnalysisSession session, Uri uri)
- : this(session, null, uri, null);
-
@override
ResultState get state {
- if (path == null) {
- return ResultState.NOT_A_FILE;
- }
return ResultState.VALID;
}
@@ -215,7 +101,7 @@
}
var elementPath = element.source!.fullName;
- var unitResult = units!.firstWhere(
+ var unitResult = units.firstWhere(
(r) => r.path == elementPath,
orElse: () {
var elementStr = element.getDisplayString(withNullability: true);
@@ -273,28 +159,22 @@
class ResolvedLibraryResultImpl extends AnalysisResultImpl
implements ResolvedLibraryResult {
@override
- final LibraryElement? element;
+ final LibraryElement element;
@override
- final List<ResolvedUnitResult>? units;
+ final List<ResolvedUnitResult> units;
ResolvedLibraryResultImpl(
- AnalysisSession session, String? path, Uri uri, this.element, this.units)
+ AnalysisSession session, String path, Uri uri, this.element, this.units)
: super(session, path, uri);
- ResolvedLibraryResultImpl.external(AnalysisSession session, Uri uri)
- : this(session, null, uri, null, null);
-
@override
ResultState get state {
- if (path == null) {
- return ResultState.NOT_A_FILE;
- }
return ResultState.VALID;
}
@override
- TypeProvider get typeProvider => element!.typeProvider;
+ TypeProvider get typeProvider => element.typeProvider;
@override
ElementDeclarationResult? getElementDeclaration(Element element) {
@@ -310,7 +190,7 @@
}
var elementPath = element.source!.fullName;
- var unitResult = units!.firstWhere(
+ var unitResult = units.firstWhere(
(r) => r.path == elementPath,
orElse: () {
var elementStr = element.getDisplayString(withNullability: true);
@@ -319,18 +199,13 @@
buffer.writeln(' is not defined in this library.');
// TODO(scheglov) https://github.com/dart-lang/sdk/issues/45430
buffer.writeln('elementPath: $elementPath');
- buffer.writeln('unitPaths: ${units!.map((e) => e.path).toList()}');
+ buffer.writeln('unitPaths: ${units.map((e) => e.path).toList()}');
throw ArgumentError('$buffer');
},
);
- var unit = unitResult.unit;
- if (unit == null) {
- throw StateError('The result has no unit');
- }
-
var locator = _DeclarationByElementLocator(element);
- unit.accept(locator);
+ unitResult.unit.accept(locator);
var declaration = locator.result;
if (declaration == null) {
@@ -347,10 +222,10 @@
final bool exists;
@override
- final String? content;
+ final String content;
@override
- final CompilationUnit? unit;
+ final CompilationUnit unit;
@override
final List<AnalysisError> errors;
@@ -369,10 +244,6 @@
@override
LibraryElement get libraryElement {
- final unit = this.unit;
- if (unit == null) {
- throw StateError('The result has no unit');
- }
return unit.declaredElement!.library;
}
diff --git a/pkg/analyzer/lib/src/dart/analysis/search.dart b/pkg/analyzer/lib/src/dart/analysis/search.dart
index 20df7ad..8d7a200 100644
--- a/pkg/analyzer/lib/src/dart/analysis/search.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/search.dart
@@ -381,7 +381,7 @@
var unitResult = await _driver.getResult2(unitPath);
if (unitResult is ResolvedUnitResult) {
var visitor = _ImportElementReferencesVisitor(element, unitElement);
- unitResult.unit!.accept(visitor);
+ unitResult.unit.accept(visitor);
results.addAll(visitor.results);
}
}
@@ -400,7 +400,7 @@
String unitPath = unitElement.source.fullName;
var unitResult = await _driver.getResult2(unitPath);
if (unitResult is ResolvedUnitResult) {
- CompilationUnit unit = unitResult.unit!;
+ CompilationUnit unit = unitResult.unit;
for (Directive directive in unit.directives) {
if (directive is PartOfDirective && directive.element == element) {
results.add(
@@ -433,9 +433,6 @@
return const <SearchResult>[];
}
var unit = unitResult.unit;
- if (unit == null) {
- return const <SearchResult>[];
- }
// Prepare the node.
var node = NodeLocator(element.nameOffset).searchWithin(unit);
@@ -487,7 +484,7 @@
var unitResult = await _driver.getResult2(unitPath);
if (unitResult is ResolvedUnitResult) {
var visitor = _LocalReferencesVisitor(element, unitElement);
- unitResult.unit!.accept(visitor);
+ unitResult.unit.accept(visitor);
results.addAll(visitor.results);
}
}
diff --git a/pkg/analyzer/lib/src/dart/analysis/session.dart b/pkg/analyzer/lib/src/dart/analysis/session.dart
index 288882e..5bc5a9c 100644
--- a/pkg/analyzer/lib/src/dart/analysis/session.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/session.dart
@@ -55,31 +55,55 @@
driver.AnalysisDriver getDriver() => _driver;
@override
- Future<SomeErrorsResult> getErrors2(String path) {
+ Future<SomeErrorsResult> getErrors(String path) {
_checkConsistency();
return _driver.getErrors2(path);
}
+ @Deprecated('Use getErrors() instead')
@override
- SomeFileResult getFile2(String path) {
+ Future<SomeErrorsResult> getErrors2(String path) {
+ return getErrors(path);
+ }
+
+ @override
+ SomeFileResult getFile(String path) {
_checkConsistency();
return _driver.getFileSync2(path);
}
+ @Deprecated('Use getFile() instead')
@override
- Future<SomeLibraryElementResult> getLibraryByUri2(String uri) {
+ SomeFileResult getFile2(String path) {
+ return getFile(path);
+ }
+
+ @override
+ Future<SomeLibraryElementResult> getLibraryByUri(String uri) {
_checkConsistency();
return _driver.getLibraryByUri2(uri);
}
+ @Deprecated('Use getLibraryByUri() instead')
@override
- SomeParsedLibraryResult getParsedLibrary2(String path) {
+ Future<SomeLibraryElementResult> getLibraryByUri2(String uri) {
+ return getLibraryByUri(uri);
+ }
+
+ @override
+ SomeParsedLibraryResult getParsedLibrary(String path) {
_checkConsistency();
return _driver.getParsedLibrary2(path);
}
+ @Deprecated('Use getParsedLibrary() instead')
@override
- SomeParsedLibraryResult getParsedLibraryByElement2(LibraryElement element) {
+ SomeParsedLibraryResult getParsedLibrary2(String path) {
+ return getParsedLibrary(path);
+ }
+
+ @override
+ SomeParsedLibraryResult getParsedLibraryByElement(LibraryElement element) {
_checkConsistency();
if (element.session != this) {
@@ -89,20 +113,38 @@
return _driver.getParsedLibraryByUri2(element.source.uri);
}
+ @Deprecated('Use getParsedLibraryByElement() instead')
@override
- SomeParsedUnitResult getParsedUnit2(String path) {
+ SomeParsedLibraryResult getParsedLibraryByElement2(LibraryElement element) {
+ return getParsedLibraryByElement(element);
+ }
+
+ @override
+ SomeParsedUnitResult getParsedUnit(String path) {
_checkConsistency();
return _driver.parseFileSync2(path);
}
+ @Deprecated('Use getParsedUnit() instead')
@override
- Future<SomeResolvedLibraryResult> getResolvedLibrary2(String path) {
+ SomeParsedUnitResult getParsedUnit2(String path) {
+ return getParsedUnit(path);
+ }
+
+ @override
+ Future<SomeResolvedLibraryResult> getResolvedLibrary(String path) {
_checkConsistency();
return _driver.getResolvedLibrary2(path);
}
+ @Deprecated('Use getResolvedLibrary() instead')
@override
- Future<SomeResolvedLibraryResult> getResolvedLibraryByElement2(
+ Future<SomeResolvedLibraryResult> getResolvedLibrary2(String path) {
+ return getResolvedLibrary(path);
+ }
+
+ @override
+ Future<SomeResolvedLibraryResult> getResolvedLibraryByElement(
LibraryElement element,
) {
_checkConsistency();
@@ -116,18 +158,38 @@
return _driver.getResolvedLibraryByUri2(element.source.uri);
}
+ @Deprecated('Use getResolvedLibraryByElement() instead')
@override
- Future<SomeResolvedUnitResult> getResolvedUnit2(String path) {
+ Future<SomeResolvedLibraryResult> getResolvedLibraryByElement2(
+ LibraryElement element,
+ ) {
+ return getResolvedLibraryByElement(element);
+ }
+
+ @override
+ Future<SomeResolvedUnitResult> getResolvedUnit(String path) {
_checkConsistency();
return _driver.getResult2(path);
}
+ @Deprecated('Use getResolvedUnit() instead')
@override
- Future<SomeUnitElementResult> getUnitElement2(String path) {
+ Future<SomeResolvedUnitResult> getResolvedUnit2(String path) {
+ return getResolvedUnit(path);
+ }
+
+ @override
+ Future<SomeUnitElementResult> getUnitElement(String path) {
_checkConsistency();
return _driver.getUnitElement2(path);
}
+ @Deprecated('Use getUnitElement() instead')
+ @override
+ Future<SomeUnitElementResult> getUnitElement2(String path) {
+ return getUnitElement(path);
+ }
+
/// Check to see that results from this session will be consistent, and throw
/// an [InconsistentAnalysisException] if they might not be.
void _checkConsistency() {
diff --git a/pkg/analyzer/lib/src/dart/analysis/session_helper.dart b/pkg/analyzer/lib/src/dart/analysis/session_helper.dart
index 020af5d..a7bc83a 100644
--- a/pkg/analyzer/lib/src/dart/analysis/session_helper.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/session_helper.dart
@@ -22,7 +22,7 @@
/// from the library with the given [libraryUri], or `null` if the library
/// does not export a class with such name.
Future<ClassElement?> getClass(String libraryUri, String className) async {
- var libraryResult = await session.getLibraryByUri2(libraryUri);
+ var libraryResult = await session.getLibraryByUri(libraryUri);
if (libraryResult is LibraryElementResult) {
var element = libraryResult.element.exportNamespace.get(className);
if (element is ClassElement) {
@@ -50,7 +50,7 @@
}
var unitPath = element.source!.fullName;
- return resolvedLibrary.units!.singleWhere((resolvedUnit) {
+ return resolvedLibrary.units.singleWhere((resolvedUnit) {
return resolvedUnit.path == unitPath;
});
}
@@ -60,7 +60,7 @@
/// library does not export a top-level accessor with such name.
Future<PropertyAccessorElement?> getTopLevelPropertyAccessor(
String uri, String name) async {
- var libraryResult = await session.getLibraryByUri2(uri);
+ var libraryResult = await session.getLibraryByUri(uri);
if (libraryResult is LibraryElementResult) {
var element = libraryResult.element.exportNamespace.get(name);
if (element is PropertyAccessorElement) {
@@ -74,7 +74,7 @@
Future<ResolvedLibraryResult?> _getResolvedLibrary(String path) async {
var result = _resolvedLibraries[path];
if (result == null) {
- var some = await session.getResolvedLibrary2(path);
+ var some = await session.getResolvedLibrary(path);
if (some is ResolvedLibraryResult) {
result = _resolvedLibraries[path] = some;
}
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index 874c8f5..9256fa8 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -5892,8 +5892,7 @@
final parent = this.parent;
if (parent is CompoundAssignmentExpression) {
- var assignment = parent as CompoundAssignmentExpression;
- element = assignment.writeElement ?? assignment.readElement;
+ element = parent.writeElement ?? parent.readElement;
}
if (element is ExecutableElement) {
diff --git a/pkg/analyzer/lib/src/dart/ast/utilities.dart b/pkg/analyzer/lib/src/dart/ast/utilities.dart
index 605628f..4387e37 100644
--- a/pkg/analyzer/lib/src/dart/ast/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/ast/utilities.dart
@@ -1302,38 +1302,19 @@
}
}
-/// A [DelegatingAstVisitor] that will additionally catch all exceptions from
-/// the delegates without stopping the visiting. A function must be provided
-/// that will be invoked for each such exception.
+/// Class capable of handling exceptions generated during linting.
///
/// Clients may not extend, implement or mix-in this class.
-class ExceptionHandlingDelegatingAstVisitor<T> extends DelegatingAstVisitor<T> {
- /// The function that will be executed for each exception that is thrown by
- /// one of the visit methods on the delegate.
- final ExceptionInDelegateHandler handler;
+class LinterExceptionHandler {
+ /// Indicates whether linter exceptions should be propagated to the caller (by
+ /// re-throwing them)
+ final bool propagateLinterExceptions;
- /// Initialize a newly created visitor to use each of the given delegate
- /// visitors to visit the nodes of an AST structure.
- ExceptionHandlingDelegatingAstVisitor(
- Iterable<AstVisitor<T>> delegates, this.handler)
- : super(delegates);
+ LinterExceptionHandler(this.propagateLinterExceptions);
- @override
- T? visitNode(AstNode node) {
- delegates.forEach((delegate) {
- try {
- node.accept(delegate);
- } catch (exception, stackTrace) {
- handler(node, delegate, exception, stackTrace);
- }
- });
- node.visitChildren(this);
- return null;
- }
-
- /// A function that can be used with instances of this class to log and then
- /// ignore any exceptions that are thrown by any of the delegates.
- static void logException(
+ /// A method that can be passed to the `LinterVisitor` constructor to handle
+ /// exceptions that occur during linting.
+ void logException(
AstNode node, Object visitor, dynamic exception, StackTrace stackTrace) {
StringBuffer buffer = StringBuffer();
buffer.write('Exception while using a ${visitor.runtimeType} to visit a ');
@@ -1351,6 +1332,9 @@
// TODO(39284): should this exception be silent?
AnalysisEngine.instance.instrumentationService.logException(
SilentException(buffer.toString(), exception, stackTrace));
+ if (propagateLinterExceptions) {
+ throw exception;
+ }
}
}
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 2bdca7a..549e1bc 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'dart:collection';
+import 'dart:typed_data';
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/analysis/session.dart';
@@ -14,6 +15,7 @@
import 'package:analyzer/dart/element/scope.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/error/error.dart';
+import 'package:analyzer/src/context/source.dart';
import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/dart/analysis/session.dart';
import 'package:analyzer/src/dart/ast/ast_factory.dart';
@@ -610,6 +612,42 @@
@override
bool get isDartCoreObject => !isMixin && supertype == null;
+ bool get isEnumLike {
+ // Must be a concrete class.
+ if (isAbstract || isMixin) {
+ return false;
+ }
+
+ // With only private non-factory constructors.
+ for (var constructor in constructors) {
+ if (constructor.isPublic || constructor.isFactory) {
+ return false;
+ }
+ }
+
+ // With 2+ static const fields with the type of this class.
+ var numberOfElements = 0;
+ for (var field in fields) {
+ if (field.isStatic && field.isConst && field.type == thisType) {
+ numberOfElements++;
+ }
+ }
+ if (numberOfElements < 2) {
+ return false;
+ }
+
+ // No subclasses in the library.
+ for (var unit in library.units) {
+ for (var class_ in unit.classes) {
+ if (class_.supertype?.element == this) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
@override
bool get isMixinApplication {
return hasModifier(Modifier.MIXIN_APPLICATION);
@@ -910,6 +948,10 @@
static ConstructorElement? getNamedConstructorFromList(
String name, List<ConstructorElement> constructors) {
+ if (name == 'new') {
+ // An unnamed constructor declared with `C.new(` is modeled as unnamed.
+ name = '';
+ }
for (ConstructorElement element in constructors) {
if (element.name == name) {
return element;
@@ -1367,7 +1409,7 @@
/// A concrete implementation of a [ConstructorElement].
class ConstructorElementImpl extends ExecutableElementImpl
with ConstructorElementMixin
- implements ConstructorElement {
+ implements ConstructorElement, HasMacroGenerationData {
/// The constructor to which this constructor is redirecting.
ConstructorElement? _redirectedConstructor;
@@ -1376,6 +1418,9 @@
List<ConstructorInitializer> _constantInitializers = const [];
@override
+ MacroGenerationData? macro;
+
+ @override
int? periodOffset;
@override
@@ -2010,9 +2055,6 @@
/// The length of the element's code, or `null` if the element is synthetic.
int? _codeLength;
- /// The language version for the library.
- LibraryLanguageVersion? _languageVersion;
-
/// Initialize a newly created element to have the given [name] at the given
/// [_nameOffset].
ElementImpl(String? name, this._nameOffset, {this.reference}) {
@@ -3435,6 +3477,13 @@
}
}
+/// This interface is implemented by [Element]s that can be added by macros.
+abstract class HasMacroGenerationData {
+ /// If this element was added by a macro, the code of a declaration that
+ /// was produced by the macro.
+ MacroGenerationData? macro;
+}
+
/// A concrete implementation of a [HideElementCombinator].
class HideElementCombinatorImpl implements HideElementCombinator {
@override
@@ -3575,6 +3624,9 @@
@override
final AnalysisSession session;
+ /// The language version for the library.
+ LibraryLanguageVersion? _languageVersion;
+
bool hasTypeProviderSystemSet = false;
@override
@@ -3958,6 +4010,64 @@
return getTypeFromParts(className, _definingCompilationUnit, _parts);
}
+ /// Indicates whether it is unnecessary to report an undefined identifier
+ /// error for an identifier reference with the given [name] and optional
+ /// [prefix].
+ ///
+ /// This method is intended to reduce spurious errors in circumstances where
+ /// an undefined identifier occurs as the result of a missing (most likely
+ /// code generated) file. It will only return `true` in a circumstance where
+ /// the current library is guaranteed to have at least one other error (due to
+ /// a missing part or import), so there is no risk that ignoring the undefined
+ /// identifier would cause an invalid program to be treated as valid.
+ bool shouldIgnoreUndefined({
+ required String? prefix,
+ required String name,
+ }) {
+ for (var importElement in imports) {
+ if (importElement.prefix?.name == prefix &&
+ importElement.importedLibrary?.isSynthetic != false) {
+ var showCombinators = importElement.combinators
+ .whereType<ShowElementCombinator>()
+ .toList();
+ if (prefix != null && showCombinators.isEmpty) {
+ return true;
+ }
+ for (var combinator in showCombinators) {
+ if (combinator.shownNames.contains(name)) {
+ return true;
+ }
+ }
+ }
+ }
+
+ if (prefix == null && name.startsWith(r'_$')) {
+ for (var partElement in parts) {
+ if (partElement.isSynthetic && isGeneratedSource(partElement.source)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /// Convenience wrapper around [shouldIgnoreUndefined] that calls it for a
+ /// given (possibly prefixed) identifier [node].
+ bool shouldIgnoreUndefinedIdentifier(Identifier node) {
+ if (node is PrefixedIdentifier) {
+ return shouldIgnoreUndefined(
+ prefix: node.prefix.name,
+ name: node.identifier.name,
+ );
+ }
+
+ return shouldIgnoreUndefined(
+ prefix: null,
+ name: (node as SimpleIdentifier).name,
+ );
+ }
+
@override
T toLegacyElementIfOptOut<T extends Element>(T element) {
if (isNonNullableByDefault) return element;
@@ -4049,8 +4159,36 @@
visitor.visitLocalVariableElement(this);
}
+/// Information about a macro-produced [Element].
+class MacroGenerationData {
+ /// The sequential id of this macro-produced element, for an element created
+ /// for a declaration that was macro-generated later this value is greater.
+ ///
+ /// This is different from [ElementImpl.id], which is also incrementing,
+ /// but shows the order in which elements were built from declarations,
+ /// not the order of declarations, and we process all field declarations
+ /// before method declarations.
+ final int id;
+
+ /// The code that was produced by the macro. It is used to compose full
+ /// code of a unit to display to the user, so that new declarations are
+ /// added to the unit or existing classes.
+ ///
+ /// When a class is generated, its code might have some members, or might
+ /// be empty, and new elements might be macro-generated into it.
+ final String code;
+
+ /// When we build elements from macro-produced code, we remember informative
+ /// data, such as offsets - to store it into bytes. This field is set to
+ /// an empty list when reading from bytes.
+ final Uint8List informative;
+
+ MacroGenerationData(this.id, this.code, this.informative);
+}
+
/// A concrete implementation of a [MethodElement].
-class MethodElementImpl extends ExecutableElementImpl implements MethodElement {
+class MethodElementImpl extends ExecutableElementImpl
+ implements MethodElement, HasMacroGenerationData {
/// Is `true` if this method is `operator==`, and there is no explicit
/// type specified for its formal parameter, in this method or in any
/// overridden methods other than the one declared in `Object`.
@@ -4060,6 +4198,9 @@
/// this variable is not a subject of type inference, or there was no error.
TopLevelInferenceError? typeInferenceError;
+ @override
+ MacroGenerationData? macro;
+
/// Initialize a newly created method element to have the given [name] at the
/// given [offset].
MethodElementImpl(String name, int offset) : super(name, offset);
@@ -4863,11 +5004,14 @@
/// A concrete implementation of a [PropertyAccessorElement].
class PropertyAccessorElementImpl extends ExecutableElementImpl
- implements PropertyAccessorElement {
+ implements PropertyAccessorElement, HasMacroGenerationData {
/// The variable associated with this accessor.
@override
late PropertyInducingElement variable;
+ @override
+ MacroGenerationData? macro;
+
/// Initialize a newly created property accessor element to have the given
/// [name] and [offset].
PropertyAccessorElementImpl(String name, int offset) : super(name, offset);
@@ -5423,23 +5567,29 @@
parameters: type.parameters,
returnType: type.returnType,
nullabilitySuffix: resultNullability,
- aliasElement: this,
- aliasArguments: typeArguments,
+ alias: InstantiatedTypeAliasElementImpl(
+ element: this,
+ typeArguments: typeArguments,
+ ),
);
} else if (type is InterfaceType) {
return InterfaceTypeImpl(
element: type.element,
typeArguments: type.typeArguments,
nullabilitySuffix: resultNullability,
- aliasElement: this,
- aliasArguments: typeArguments,
+ alias: InstantiatedTypeAliasElementImpl(
+ element: this,
+ typeArguments: typeArguments,
+ ),
);
} else if (type is TypeParameterType) {
return TypeParameterTypeImpl(
element: type.element,
nullabilitySuffix: resultNullability,
- aliasElement: this,
- aliasArguments: typeArguments,
+ alias: InstantiatedTypeAliasElementImpl(
+ element: this,
+ typeArguments: typeArguments,
+ ),
);
} else {
return (type as TypeImpl).withNullability(resultNullability);
diff --git a/pkg/analyzer/lib/src/dart/element/generic_inferrer.dart b/pkg/analyzer/lib/src/dart/element/generic_inferrer.dart
index b05ab3d..f4077d4 100644
--- a/pkg/analyzer/lib/src/dart/element/generic_inferrer.dart
+++ b/pkg/analyzer/lib/src/dart/element/generic_inferrer.dart
@@ -583,7 +583,7 @@
if (typeElement != null && typeElement.hasOptionalTypeArgs) {
return;
}
- var typeAliasElement = type.aliasElement;
+ var typeAliasElement = type.alias?.element;
if (typeAliasElement != null &&
typeAliasElement.hasOptionalTypeArgs) {
return;
diff --git a/pkg/analyzer/lib/src/dart/element/replace_top_bottom_visitor.dart b/pkg/analyzer/lib/src/dart/element/replace_top_bottom_visitor.dart
index 5709733..2db9a85 100644
--- a/pkg/analyzer/lib/src/dart/element/replace_top_bottom_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/element/replace_top_bottom_visitor.dart
@@ -53,8 +53,9 @@
}
}
- if (type.aliasElement != null) {
- return _typeAliasInstantiation(type, variance);
+ var alias = type.alias;
+ if (alias != null) {
+ return _instantiatedTypeAlias(type, alias, variance);
} else if (type is InterfaceType) {
return _interfaceType(type, variance);
} else if (type is FunctionType) {
@@ -83,6 +84,34 @@
);
}
+ DartType _instantiatedTypeAlias(
+ DartType type,
+ InstantiatedTypeAliasElement alias,
+ Variance variance,
+ ) {
+ var aliasElement = alias.element;
+ var aliasArguments = alias.typeArguments;
+
+ var typeParameters = aliasElement.typeParameters;
+ assert(typeParameters.length == aliasArguments.length);
+
+ var newTypeArguments = <DartType>[];
+ for (var i = 0; i < typeParameters.length; i++) {
+ var typeParameter = typeParameters[i] as TypeParameterElementImpl;
+ newTypeArguments.add(
+ process(
+ aliasArguments[i],
+ typeParameter.variance.combine(variance),
+ ),
+ );
+ }
+
+ return aliasElement.instantiate(
+ typeArguments: newTypeArguments,
+ nullabilitySuffix: type.nullabilitySuffix,
+ );
+ }
+
DartType _interfaceType(InterfaceType type, Variance variance) {
var typeParameters = type.element.typeParameters;
if (typeParameters.isEmpty) {
@@ -105,30 +134,6 @@
);
}
- DartType _typeAliasInstantiation(DartType type, Variance variance) {
- var aliasElement = type.aliasElement!;
- var aliasArguments = type.aliasArguments!;
-
- var typeParameters = aliasElement.typeParameters;
- assert(typeParameters.length == aliasArguments.length);
-
- var newTypeArguments = <DartType>[];
- for (var i = 0; i < typeParameters.length; i++) {
- var typeParameter = typeParameters[i] as TypeParameterElementImpl;
- newTypeArguments.add(
- process(
- aliasArguments[i],
- typeParameter.variance.combine(variance),
- ),
- );
- }
-
- return aliasElement.instantiate(
- typeArguments: newTypeArguments,
- nullabilitySuffix: type.nullabilitySuffix,
- );
- }
-
/// Runs an instance of the visitor on the given [type] and returns the
/// resulting type. If the type contains no instances of Top or Bottom, the
/// original type object is returned to avoid unnecessary allocation.
diff --git a/pkg/analyzer/lib/src/dart/element/replacement_visitor.dart b/pkg/analyzer/lib/src/dart/element/replacement_visitor.dart
index c1c1a79..638ad0f 100644
--- a/pkg/analyzer/lib/src/dart/element/replacement_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/element/replacement_visitor.dart
@@ -29,13 +29,14 @@
DartType? createFunctionType({
required FunctionType type,
- required List<DartType>? newAliasArguments,
+ required InstantiatedTypeAliasElement? newAlias,
required List<TypeParameterElement>? newTypeParameters,
required List<ParameterElement>? newParameters,
required DartType? newReturnType,
required NullabilitySuffix? newNullability,
}) {
- if (newNullability == null &&
+ if (newAlias == null &&
+ newNullability == null &&
newReturnType == null &&
newParameters == null) {
return null;
@@ -46,8 +47,7 @@
parameters: newParameters ?? type.parameters,
returnType: newReturnType ?? type.returnType,
nullabilitySuffix: newNullability ?? type.nullabilitySuffix,
- aliasElement: type.aliasElement,
- aliasArguments: newAliasArguments ?? type.aliasArguments,
+ alias: newAlias ?? type.alias,
);
}
@@ -74,11 +74,11 @@
DartType? createInterfaceType({
required InterfaceType type,
- required List<DartType>? newAliasArguments,
+ required InstantiatedTypeAliasElement? newAlias,
required List<DartType>? newTypeArguments,
required NullabilitySuffix? newNullability,
}) {
- if (newAliasArguments == null &&
+ if (newAlias == null &&
newTypeArguments == null &&
newNullability == null) {
return null;
@@ -88,8 +88,7 @@
element: type.element,
typeArguments: newTypeArguments ?? type.typeArguments,
nullabilitySuffix: newNullability ?? type.nullabilitySuffix,
- aliasElement: type.aliasElement,
- aliasArguments: newAliasArguments ?? type.aliasArguments,
+ alias: newAlias ?? type.alias,
);
}
@@ -136,8 +135,7 @@
element: type.element,
nullabilitySuffix: newNullability ?? type.nullabilitySuffix,
promotedBound: newPromotedBound ?? promotedBound,
- aliasElement: type.aliasElement,
- aliasArguments: type.aliasArguments,
+ alias: type.alias,
);
}
@@ -152,8 +150,7 @@
return TypeParameterTypeImpl(
element: type.element,
nullabilitySuffix: newNullability,
- aliasElement: type.aliasElement,
- aliasArguments: type.aliasArguments,
+ alias: type.alias,
);
}
@@ -215,16 +212,24 @@
var newReturnType = visitType(node.returnType);
- List<DartType>? newAliasArguments;
- var aliasArguments = node.aliasArguments;
- if (aliasArguments != null) {
+ InstantiatedTypeAliasElement? newAlias;
+ var alias = node.alias;
+ if (alias != null) {
+ List<DartType>? newArguments;
+ var aliasArguments = alias.typeArguments;
for (var i = 0; i < aliasArguments.length; i++) {
var substitution = aliasArguments[i].accept(this);
if (substitution != null) {
- newAliasArguments ??= aliasArguments.toList(growable: false);
- newAliasArguments[i] = substitution;
+ newArguments ??= aliasArguments.toList(growable: false);
+ newArguments[i] = substitution;
}
}
+ if (newArguments != null) {
+ newAlias = InstantiatedTypeAliasElementImpl(
+ element: alias.element,
+ typeArguments: newArguments,
+ );
+ }
}
changeVariance();
@@ -253,7 +258,7 @@
return createFunctionType(
type: node,
- newAliasArguments: newAliasArguments,
+ newAlias: newAlias,
newTypeParameters: newTypeParameters,
newParameters: newParameters,
newReturnType: newReturnType,
@@ -351,13 +356,20 @@
DartType? visitInterfaceType(InterfaceType type) {
var newNullability = visitNullability(type);
- var aliasElement = type.aliasElement;
- var newAliasArguments = aliasElement != null
- ? _typeArguments(
- aliasElement.typeParameters,
- type.aliasArguments,
- )
- : null;
+ InstantiatedTypeAliasElement? newAlias;
+ var alias = type.alias;
+ if (alias != null) {
+ var newArguments = _typeArguments(
+ alias.element.typeParameters,
+ alias.typeArguments,
+ );
+ if (newArguments != null) {
+ newAlias = InstantiatedTypeAliasElementImpl(
+ element: alias.element,
+ typeArguments: newArguments,
+ );
+ }
+ }
var newTypeArguments = _typeArguments(
type.element.typeParameters,
@@ -366,7 +378,7 @@
return createInterfaceType(
type: type,
- newAliasArguments: newAliasArguments,
+ newAlias: newAlias,
newTypeArguments: newTypeArguments,
newNullability: newNullability,
);
@@ -453,12 +465,8 @@
List<DartType>? _typeArguments(
List<TypeParameterElement> parameters,
- List<DartType>? arguments,
+ List<DartType> arguments,
) {
- if (arguments == null) {
- return null;
- }
-
if (arguments.length != parameters.length) {
return null;
}
diff --git a/pkg/analyzer/lib/src/dart/element/scope.dart b/pkg/analyzer/lib/src/dart/element/scope.dart
index 1f15606..4df2190 100644
--- a/pkg/analyzer/lib/src/dart/element/scope.dart
+++ b/pkg/analyzer/lib/src/dart/element/scope.dart
@@ -4,7 +4,6 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/scope.dart';
-import 'package:analyzer/src/context/source.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/resolver/scope.dart' as impl;
@@ -104,38 +103,6 @@
_element.units.forEach(_addUnitElements);
}
- bool shouldIgnoreUndefined({
- required String? prefix,
- required String name,
- }) {
- for (var importElement in _element.imports) {
- if (importElement.prefix?.name == prefix &&
- importElement.importedLibrary?.isSynthetic != false) {
- var showCombinators = importElement.combinators
- .whereType<ShowElementCombinator>()
- .toList();
- if (prefix != null && showCombinators.isEmpty) {
- return true;
- }
- for (var combinator in showCombinators) {
- if (combinator.shownNames.contains(name)) {
- return true;
- }
- }
- }
- }
-
- if (prefix == null && name.startsWith(r'_$')) {
- for (var partElement in _element.parts) {
- if (partElement.isSynthetic && isGeneratedSource(partElement.source)) {
- return true;
- }
- }
- }
-
- return false;
- }
-
void _addExtension(ExtensionElement element) {
_addGetter(element);
if (!extensions.contains(element)) {
diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart
index a123137..846f845 100644
--- a/pkg/analyzer/lib/src/dart/element/type.dart
+++ b/pkg/analyzer/lib/src/dart/element/type.dart
@@ -109,13 +109,12 @@
required List<ParameterElement> parameters,
required DartType returnType,
required NullabilitySuffix nullabilitySuffix,
- TypeAliasElement? aliasElement,
- List<DartType>? aliasArguments,
+ InstantiatedTypeAliasElement? alias,
}) : typeFormals = typeFormals,
parameters = _sortNamedParameters(parameters),
returnType = returnType,
nullabilitySuffix = nullabilitySuffix,
- super(null, aliasElement: aliasElement, aliasArguments: aliasArguments);
+ super(null, alias: alias);
@override
int get hashCode {
@@ -297,8 +296,7 @@
parameters: parameters,
returnType: returnType,
nullabilitySuffix: nullabilitySuffix,
- aliasElement: aliasElement,
- aliasArguments: aliasArguments,
+ alias: alias,
);
}
@@ -610,6 +608,19 @@
}
}
+class InstantiatedTypeAliasElementImpl implements InstantiatedTypeAliasElement {
+ @override
+ final TypeAliasElement element;
+
+ @override
+ final List<DartType> typeArguments;
+
+ InstantiatedTypeAliasElementImpl({
+ required this.element,
+ required this.typeArguments,
+ });
+}
+
/// A concrete implementation of an [InterfaceType].
class InterfaceTypeImpl extends TypeImpl implements InterfaceType {
@override
@@ -631,12 +642,10 @@
required ClassElement element,
required this.typeArguments,
required this.nullabilitySuffix,
- TypeAliasElement? aliasElement,
- List<DartType>? aliasArguments,
+ InstantiatedTypeAliasElement? alias,
}) : super(
element,
- aliasElement: aliasElement,
- aliasArguments: aliasArguments,
+ alias: alias,
);
@override
@@ -1615,19 +1624,26 @@
/// representing the declared type of elements in the element model.
abstract class TypeImpl implements DartType {
@override
- final List<DartType>? aliasArguments;
-
- @override
- final TypeAliasElement? aliasElement;
+ InstantiatedTypeAliasElement? alias;
/// The element representing the declaration of this type, or `null` if the
/// type has not, or cannot, be associated with an element.
final Element? _element;
/// Initialize a newly created type to be declared by the given [element].
- TypeImpl(this._element, {this.aliasElement, this.aliasArguments})
- : assert(aliasElement == null && aliasArguments == null ||
- aliasElement != null && aliasArguments != null);
+ TypeImpl(this._element, {this.alias});
+
+ @Deprecated('Use alias instead')
+ @override
+ List<DartType>? get aliasArguments {
+ return alias?.typeArguments;
+ }
+
+ @Deprecated('Use alias instead')
+ @override
+ TypeAliasElement? get aliasElement {
+ return alias?.element;
+ }
@deprecated
@override
@@ -1774,12 +1790,10 @@
required TypeParameterElement element,
required this.nullabilitySuffix,
this.promotedBound,
- TypeAliasElement? aliasElement,
- List<DartType>? aliasArguments,
+ InstantiatedTypeAliasElement? alias,
}) : super(
element,
- aliasElement: aliasElement,
- aliasArguments: aliasArguments,
+ alias: alias,
);
@override
diff --git a/pkg/analyzer/lib/src/dart/element/type_algebra.dart b/pkg/analyzer/lib/src/dart/element/type_algebra.dart
index 326f73a..9057b2c 100644
--- a/pkg/analyzer/lib/src/dart/element/type_algebra.dart
+++ b/pkg/analyzer/lib/src/dart/element/type_algebra.dart
@@ -444,9 +444,13 @@
var returnType = type.returnType.accept(inner);
- var aliasArguments = type.aliasArguments;
- var newAliasArguments =
- aliasArguments != null ? _mapList(aliasArguments) : null;
+ var alias = type.alias;
+ var newAlias = alias != null
+ ? InstantiatedTypeAliasElementImpl(
+ element: alias.element,
+ typeArguments: _mapList(alias.typeArguments),
+ )
+ : null;
if (useCounter == before) return type;
@@ -455,8 +459,7 @@
parameters: parameters,
returnType: returnType,
nullabilitySuffix: type.nullabilitySuffix,
- aliasElement: type.aliasElement,
- aliasArguments: newAliasArguments,
+ alias: newAlias,
);
}
diff --git a/pkg/analyzer/lib/src/dart/element/type_demotion.dart b/pkg/analyzer/lib/src/dart/element/type_demotion.dart
index 4b1cc1a..4839abe 100644
--- a/pkg/analyzer/lib/src/dart/element/type_demotion.dart
+++ b/pkg/analyzer/lib/src/dart/element/type_demotion.dart
@@ -38,8 +38,7 @@
return TypeParameterTypeImpl(
element: type.element,
nullabilitySuffix: newNullability ?? type.nullabilitySuffix,
- aliasElement: type.aliasElement,
- aliasArguments: type.aliasArguments,
+ alias: type.alias,
);
}
}
diff --git a/pkg/analyzer/lib/src/dart/element/type_system.dart b/pkg/analyzer/lib/src/dart/element/type_system.dart
index a299c7d..711f2ab 100644
--- a/pkg/analyzer/lib/src/dart/element/type_system.dart
+++ b/pkg/analyzer/lib/src/dart/element/type_system.dart
@@ -628,7 +628,7 @@
appendParameters(type.returnType);
type.parameters.map((p) => p.type).forEach(appendParameters);
// TODO(scheglov) https://github.com/dart-lang/sdk/issues/44218
- type.aliasArguments?.forEach(appendParameters);
+ type.alias?.typeArguments.forEach(appendParameters);
} else if (type is InterfaceType) {
type.typeArguments.forEach(appendParameters);
}
diff --git a/pkg/analyzer/lib/src/dart/error/ffi_code.dart b/pkg/analyzer/lib/src/dart/error/ffi_code.dart
index 639a3f3..d8600d8 100644
--- a/pkg/analyzer/lib/src/dart/error/ffi_code.dart
+++ b/pkg/analyzer/lib/src/dart/error/ffi_code.dart
@@ -69,6 +69,14 @@
/**
* No parameters.
*/
+ static const FfiCode FFI_NATIVE_ONLY_STATIC = FfiCode(
+ name: 'FFI_NATIVE_ONLY_STATIC',
+ message: "FfiNative annotations can only be used on static functions.",
+ correction: "Change the method to static.");
+
+ /**
+ * No parameters.
+ */
static const FfiCode FIELD_IN_STRUCT_WITH_INITIALIZER = FfiCode(
name: 'FIELD_IN_STRUCT_WITH_INITIALIZER',
message:
diff --git a/pkg/analyzer/lib/src/dart/micro/analysis_context.dart b/pkg/analyzer/lib/src/dart/micro/analysis_context.dart
index 4d79d83..ef663ca 100644
--- a/pkg/analyzer/lib/src/dart/micro/analysis_context.dart
+++ b/pkg/analyzer/lib/src/dart/micro/analysis_context.dart
@@ -181,18 +181,18 @@
}
@override
- Future<SomeLibraryElementResult> getLibraryByUri2(String uriStr) async {
+ Future<SomeLibraryElementResult> getLibraryByUri(String uriStr) async {
var element = analysisContext.fileResolver.getLibraryByUri(uriStr: uriStr);
return LibraryElementResultImpl(element);
}
@override
- Future<SomeResolvedLibraryResult> getResolvedLibrary2(String path) async {
+ Future<SomeResolvedLibraryResult> getResolvedLibrary(String path) async {
return analysisContext.fileResolver.resolveLibrary(path: path);
}
@override
- Future<SomeResolvedUnitResult> getResolvedUnit2(String path) async {
+ Future<SomeResolvedUnitResult> getResolvedUnit(String path) async {
return analysisContext.fileResolver.resolve(path: path);
}
diff --git a/pkg/analyzer/lib/src/dart/micro/library_analyzer.dart b/pkg/analyzer/lib/src/dart/micro/library_analyzer.dart
index 2d5a144..327af6e 100644
--- a/pkg/analyzer/lib/src/dart/micro/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/micro/library_analyzer.dart
@@ -332,7 +332,6 @@
ErrorReporter errorReporter = _getErrorReporter(file);
var nodeRegistry = NodeLintRegistry(_analysisOptions.enableTiming);
- var visitors = <AstVisitor>[];
final workspacePackage = _getPackage(currentUnit.unit);
var context = LinterContextImpl(
allUnits,
@@ -350,14 +349,9 @@
// Run lints that handle specific node types.
unit.accept(LinterVisitor(
- nodeRegistry, ExceptionHandlingDelegatingAstVisitor.logException));
-
- // Run visitor based lints.
- if (visitors.isNotEmpty) {
- AstVisitor visitor = ExceptionHandlingDelegatingAstVisitor(
- visitors, ExceptionHandlingDelegatingAstVisitor.logException);
- unit.accept(visitor);
- }
+ nodeRegistry,
+ LinterExceptionHandler(_analysisOptions.propagateLinterExceptions)
+ .logException));
}
void _computeVerifyErrors(FileState file, CompilationUnit unit) {
diff --git a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
index 2608588..d52742b 100644
--- a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
+++ b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
@@ -39,6 +39,7 @@
import 'package:analyzer/src/util/performance/operation_performance.dart';
import 'package:analyzer/src/workspace/workspace.dart';
import 'package:collection/collection.dart';
+import 'package:meta/meta.dart';
import 'package:yaml/yaml.dart';
const M = 1024 * 1024 /*1 MiB*/;
@@ -109,7 +110,8 @@
/// It is used to allow assists and fixes without resolving the same file
/// multiple times, as we compute more than one assist, or fixes when there
/// are more than one error on a line.
- final Map<String, ResolvedLibraryResult> _cachedResults = {};
+ @visibleForTesting
+ final Map<String, ResolvedLibraryResult> cachedResults = {};
FileResolver(
PerformanceLog logger,
@@ -164,7 +166,7 @@
}
// Forget all results, anything is potentially affected.
- _cachedResults.clear();
+ cachedResults.clear();
// Remove this file and all files that transitively depend on it.
var removedFiles = <FileState>[];
@@ -208,7 +210,7 @@
result.forEach((filePath) {
var resolved = resolve(path: filePath);
var collector = ReferencesCollector(element);
- resolved.unit?.accept(collector);
+ resolved.unit.accept(collector);
var offsets = collector.offsets;
if (offsets.isNotEmpty) {
references.add(CiderSearchMatch(filePath, offsets));
@@ -445,24 +447,16 @@
}
}
- var libraryUnit = resolveLibrary(
+ var libraryResult = resolveLibrary(
completionLine: completionLine,
completionColumn: completionColumn,
path: libraryFile.path,
- completionPath: path,
+ completionPath: completionLine != null ? path : null,
performance: performance,
);
- var result = libraryUnit.units!
- .firstWhereOrNull((element) => element.path == path);
- // TODO(scheglov) Fix and remove.
- if (result == null) {
- throw StateError('''
-libraryFile.path: ${libraryFile.path}
-path: $path
-units: ${libraryUnit.units!.map((e) => '(${e.uri} = ${e.path})').toList()}
-''');
- }
- return result;
+ return libraryResult.units.firstWhere(
+ (unitResult) => unitResult.path == path,
+ );
});
}
@@ -478,7 +472,7 @@
performance ??= OperationPerformanceImpl('<default>');
- var cachedResult = _cachedResults[path];
+ var cachedResult = cachedResults[path];
if (cachedResult != null) {
return cachedResult;
}
@@ -513,7 +507,7 @@
);
});
- testView?.addResolvedFile(path);
+ testView?.addResolvedLibrary(path);
late Map<FileState, UnitAnalysisResult> results;
@@ -570,7 +564,11 @@
var libraryUnit = resolvedUnits.first;
var result = ResolvedLibraryResultImpl(contextObjects!.analysisSession,
path, libraryUnit.uri, libraryUnit.libraryElement, resolvedUnits);
- _cachedResults[path] = result;
+
+ if (completionPath == null) {
+ cachedResults[path] = result;
+ }
+
return result;
});
}
@@ -764,13 +762,13 @@
}
class FileResolverTestView {
- /// The paths of files which were resolved.
+ /// The paths of libraries which were resolved.
///
- /// The file path is added every time when it is resolved.
- final List<String> resolvedFiles = [];
+ /// The library path is added every time when it is resolved.
+ final List<String> resolvedLibraries = [];
- void addResolvedFile(String path) {
- resolvedFiles.add(path);
+ void addResolvedLibrary(String path) {
+ resolvedLibraries.add(path);
}
}
diff --git a/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart
index 84260a2..76697c1 100644
--- a/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart
@@ -13,6 +13,7 @@
import 'package:analyzer/src/dart/ast/extensions.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/dart/resolver/extension_member_resolver.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/resolver.dart';
@@ -25,13 +26,17 @@
/// The resolver driving this participant.
final ResolverVisitor _resolver;
+ /// Helper for extension method resolution.
+ final ExtensionMemberResolver _extensionResolver;
+
final bool _isNonNullableByDefault;
/// The type representing the type 'type'.
final InterfaceType _typeType;
FunctionReferenceResolver(this._resolver, this._isNonNullableByDefault)
- : _typeType = _resolver.typeProvider.typeType;
+ : _extensionResolver = _resolver.extensionResolver,
+ _typeType = _resolver.typeProvider.typeType;
ErrorReporter get _errorReporter => _resolver.errorReporter;
@@ -43,192 +48,44 @@
node.typeArguments?.accept(_resolver);
if (function is SimpleIdentifierImpl) {
- var element = _resolver.nameScope.lookup(function.name).getter;
-
- // Classes and type aliases are checked first so as to include a
- // PropertyAccess parent check, which does not need to be done for
- // functions.
- if (element is ClassElement || element is TypeAliasElement) {
- // A type-instantiated constructor tearoff like `C<int>.name` or
- // `prefix.C<int>.name` is initially represented as a [PropertyAccess]
- // with a [FunctionReference] target.
- if (node.parent is PropertyAccess) {
- _resolveConstructorReference(node);
- return;
- } else if (element is ClassElement) {
- function.staticElement = element;
- _resolveDirectTypeLiteral(node, function, element);
- return;
- } else if (element is TypeAliasElement) {
- function.staticElement = element;
- _resolveTypeAlias(node: node, element: element, typeAlias: function);
- return;
- }
- } else if (element is ExecutableElement) {
- function.staticElement = element;
- _resolve(node: node, name: element.name, rawType: element.type);
- return;
- } else if (element is VariableElement) {
- var functionType = element.type;
- if (functionType is FunctionType) {
- function.accept(_resolver);
- _resolve(node: node, name: element.name ?? '', rawType: functionType);
- return;
- }
- }
- }
-
- // TODO(srawlins): Handle `function` being a [SuperExpression].
-
- if (function is PrefixedIdentifierImpl) {
- var prefixElement =
- _resolver.nameScope.lookup(function.prefix.name).getter;
- function.prefix.staticElement = prefixElement;
- if (prefixElement is PrefixElement) {
- var functionName = function.identifier.name;
- var functionElement = prefixElement.scope.lookup(functionName).getter;
- if (functionElement == null) {
- _errorReporter.reportErrorForNode(
- CompileTimeErrorCode.UNDEFINED_PREFIXED_NAME,
- function.identifier,
- [function.identifier.name, function.prefix.name],
- );
- function.staticType = DynamicTypeImpl.instance;
- node.staticType = DynamicTypeImpl.instance;
- return;
- } else {
- functionElement = _resolver.toLegacyElement(functionElement);
- _resolveReceiverPrefix(
- node, prefixElement, function, functionElement);
- return;
- }
- } else if (prefixElement is VariableElement) {
- function.prefix.staticType = prefixElement.type;
- } else if (prefixElement is PropertyAccessorElement) {
- function.prefix.staticType = prefixElement.returnType;
- }
-
- var methodElement = _resolveTypeProperty(
- receiver: function.prefix,
- receiverElement: prefixElement,
- name: function.identifier,
- nameErrorEntity: function,
- );
-
- if (methodElement is MethodElement) {
- function.identifier.staticElement = methodElement;
- function.staticType = methodElement.type;
- _resolve(
- node: node,
- name: function.identifier.name,
- rawType: methodElement.type,
- );
- return;
- }
-
- // TODO(srawlins): Need to report cases where [methodElement] is not
- // generic. The 'test_instanceGetter_explicitReceiver' test case needs to
- // be updated to handle this.
+ _resolveSimpleIdentifierFunction(node, function);
+ } else if (function is PrefixedIdentifierImpl) {
+ _resolvePrefixedIdentifierFunction(node, function);
+ } else if (function is PropertyAccessImpl) {
+ _resolvePropertyAccessFunction(node, function);
+ } else {
+ // TODO(srawlins): Handle `function` being a [SuperExpression].
function.accept(_resolver);
- node.staticType = DynamicTypeImpl.instance;
- return;
+ _resolveDisallowedExpression(node, node.function.staticType);
}
-
- if (function is PropertyAccessImpl) {
- function.accept(_resolver);
- var target = function.target;
- DartType targetType;
- if (target is SuperExpressionImpl) {
- targetType = target.typeOrThrow;
- } else if (target is ThisExpressionImpl) {
- targetType = target.typeOrThrow;
- } else if (target is SimpleIdentifierImpl) {
- var targetElement = _resolver.nameScope.lookup(target.name).getter;
- if (targetElement is VariableElement) {
- targetType = targetElement.type;
- } else if (targetElement is PropertyAccessorElement) {
- targetType = targetElement.returnType;
- } else {
- // TODO(srawlins): Can we get here?
- node.staticType = DynamicTypeImpl.instance;
- return;
- }
- } else if (target is PrefixedIdentifierImpl) {
- var prefixElement =
- _resolver.nameScope.lookup(target.prefix.name).getter;
- if (prefixElement is PrefixElement) {
- var prefixName = target.identifier.name;
- var targetElement = prefixElement.scope.lookup(prefixName).getter;
-
- var methodElement = _resolveTypeProperty(
- receiver: target,
- receiverElement: targetElement,
- name: function.propertyName,
- nameErrorEntity: function,
- );
-
- if (methodElement == null) {
- // TODO(srawlins): Can we get here?
- node.staticType = DynamicTypeImpl.instance;
- return;
- } else {
- _resolveReceiverPrefix(node, prefixElement, target, methodElement);
- return;
- }
- } else {
- // TODO(srawlins): Can we get here?
- node.staticType = DynamicTypeImpl.instance;
- return;
- }
- } else {
- // TODO(srawlins): Can we get here?
- node.staticType = DynamicTypeImpl.instance;
- return;
- }
-
- var propertyElement = _resolver.typePropertyResolver
- .resolve(
- receiver: function.realTarget,
- receiverType: targetType,
- name: function.propertyName.name,
- propertyErrorEntity: function.propertyName,
- nameErrorEntity: function,
- )
- .getter;
-
- var functionType = function.typeOrThrow;
- if (functionType is FunctionType && propertyElement != null) {
- _resolve(
- node: node,
- name: propertyElement.name,
- rawType: functionType,
- );
- return;
- }
-
- // TODO(srawlins): Handle type variables bound to function type, like
- // `T extends void Function<U>(U)`.
- }
-
- // TODO(srawlins): Enumerate and handle all cases that fall through to
- // here; ultimately it should just be a case of "unknown identifier."
- function.accept(_resolver);
- node.staticType = DynamicTypeImpl.instance;
}
List<DartType> _checkTypeArguments(
TypeArgumentList typeArgumentList,
- String name,
+ String? name,
List<TypeParameterElement> typeParameters,
CompileTimeErrorCode errorCode,
) {
if (typeArgumentList.arguments.length != typeParameters.length) {
- _errorReporter.reportErrorForNode(
- errorCode,
- typeArgumentList,
- [name, typeParameters.length, typeArgumentList.arguments.length],
- );
+ if (name == null &&
+ errorCode ==
+ CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION) {
+ errorCode = CompileTimeErrorCode
+ .WRONG_NUMBER_OF_TYPE_ARGUMENTS_ANONYMOUS_FUNCTION;
+ _errorReporter.reportErrorForNode(
+ errorCode,
+ typeArgumentList,
+ [typeParameters.length, typeArgumentList.arguments.length],
+ );
+ } else {
+ assert(name != null);
+ _errorReporter.reportErrorForNode(
+ errorCode,
+ typeArgumentList,
+ [name, typeParameters.length, typeArgumentList.arguments.length],
+ );
+ }
return List.filled(typeParameters.length, DynamicTypeImpl.instance);
} else {
return typeArgumentList.arguments
@@ -237,22 +94,68 @@
}
}
+ void _reportInvalidAccessToStaticMember(
+ SimpleIdentifier nameNode,
+ ExecutableElement element, {
+ required bool implicitReceiver,
+ }) {
+ if (_resolver.enclosingExtension != null) {
+ _resolver.errorReporter.reportErrorForNode(
+ CompileTimeErrorCode
+ .UNQUALIFIED_REFERENCE_TO_STATIC_MEMBER_OF_EXTENDED_TYPE,
+ nameNode,
+ [element.enclosingElement.displayName],
+ );
+ } else if (implicitReceiver) {
+ _resolver.errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER,
+ nameNode,
+ [element.enclosingElement.displayName],
+ );
+ } else {
+ _resolver.errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.INSTANCE_ACCESS_TO_STATIC_MEMBER,
+ nameNode,
+ [
+ nameNode.name,
+ element.kind.displayName,
+ element.enclosingElement.displayName,
+ ],
+ );
+ }
+ }
+
/// Resolves [node]'s static type, as an instantiated function type, and type
/// argument types, using [rawType] as the uninstantiated function type.
void _resolve({
required FunctionReferenceImpl node,
- required String name,
- required FunctionType rawType,
+ required DartType? rawType,
+ String? name,
}) {
- var typeArguments = _checkTypeArguments(
- // `node.typeArguments`, coming from the parser, is never null.
- node.typeArguments!, name, rawType.typeFormals,
- CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION,
- );
+ if (rawType == null) {
+ node.staticType = DynamicTypeImpl.instance;
+ }
- var invokeType = rawType.instantiate(typeArguments);
- node.typeArgumentTypes = typeArguments;
- node.staticType = invokeType;
+ if (rawType is TypeParameterTypeImpl) {
+ // If the type of the function is a type parameter, the tearoff is
+ // disallowed, reported in [_resolveDisallowedExpression]. Use the type
+ // parameter's bound here in an attempt to assign the intended types.
+ rawType = rawType.element.bound;
+ }
+
+ if (rawType is FunctionType) {
+ var typeArguments = _checkTypeArguments(
+ // `node.typeArguments`, coming from the parser, is never null.
+ node.typeArguments!, name, rawType.typeFormals,
+ CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION,
+ );
+
+ var invokeType = rawType.instantiate(typeArguments);
+ node.typeArgumentTypes = typeArguments;
+ node.staticType = invokeType;
+ } else {
+ node.staticType = DynamicTypeImpl.instance;
+ }
}
void _resolveConstructorReference(FunctionReferenceImpl node) {
@@ -277,14 +180,220 @@
_resolveTypeLiteral(node: node, instantiatedType: type, name: name);
}
+ /// Resolves [node] as a type instantiation on an illegal expression.
+ ///
+ /// This function attempts to give [node] a static type, to continue working
+ /// with what the user may be intending.
+ void _resolveDisallowedExpression(
+ FunctionReferenceImpl node, DartType? rawType) {
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.DISALLOWED_TYPE_INSTANTIATION_EXPRESSION,
+ node.function,
+ [],
+ );
+ _resolve(node: node, rawType: rawType);
+ }
+
+ void _resolveExtensionOverride(
+ FunctionReferenceImpl node,
+ PropertyAccessImpl function,
+ ExtensionOverride override,
+ ) {
+ var propertyName = function.propertyName;
+ var result =
+ _extensionResolver.getOverrideMember(override, propertyName.name);
+ var member = _resolver.toLegacyElement(result.getter);
+
+ if (member == null) {
+ node.staticType = DynamicTypeImpl.instance;
+ return;
+ }
+
+ if (member.isStatic) {
+ _resolver.errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.EXTENSION_OVERRIDE_ACCESS_TO_STATIC_MEMBER,
+ function.propertyName,
+ );
+ // Continue to resolve type.
+ }
+
+ if (function.isCascaded) {
+ _resolver.errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.EXTENSION_OVERRIDE_WITH_CASCADE,
+ override.extensionName,
+ );
+ // Continue to resolve type.
+ }
+
+ if (member is PropertyAccessorElement) {
+ function.accept(_resolver);
+ _resolveDisallowedExpression(node, member.returnType);
+ return;
+ }
+
+ _resolve(node: node, rawType: member.type, name: propertyName.name);
+ }
+
+ void _resolvePrefixedIdentifierFunction(
+ FunctionReferenceImpl node, PrefixedIdentifierImpl function) {
+ var prefixElement = _resolver.nameScope.lookup(function.prefix.name).getter;
+
+ if (prefixElement == null) {
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.UNDEFINED_IDENTIFIER,
+ function.prefix,
+ [function.name],
+ );
+ function.staticType = DynamicTypeImpl.instance;
+ node.staticType = DynamicTypeImpl.instance;
+ return;
+ }
+
+ function.prefix.staticElement = prefixElement;
+ if (prefixElement is PrefixElement) {
+ var functionName = function.identifier.name;
+ var functionElement = prefixElement.scope.lookup(functionName).getter;
+ if (functionElement == null) {
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.UNDEFINED_PREFIXED_NAME,
+ function.identifier,
+ [function.identifier.name, function.prefix.name],
+ );
+ function.staticType = DynamicTypeImpl.instance;
+ node.staticType = DynamicTypeImpl.instance;
+ return;
+ } else {
+ functionElement = _resolver.toLegacyElement(functionElement);
+ _resolveReceiverPrefix(node, prefixElement, function, functionElement);
+ return;
+ }
+ }
+
+ DartType? prefixType;
+ if (prefixElement is VariableElement) {
+ prefixType = prefixElement.type;
+ } else if (prefixElement is PropertyAccessorElement) {
+ prefixType = prefixElement.returnType;
+ }
+
+ function.prefix.staticType = prefixType;
+ if (prefixType != null && prefixType.isDynamic) {
+ // TODO(srawlins): Report error. See spec text: "We do not allow dynamic
+ // explicit instantiation."
+ node.staticType = DynamicTypeImpl.instance;
+ return;
+ }
+
+ var methodElement = _resolveTypeProperty(
+ receiver: function.prefix,
+ receiverElement: prefixElement,
+ name: function.identifier,
+ nameErrorEntity: function,
+ );
+
+ if (methodElement is MethodElement) {
+ function.identifier.staticElement = methodElement;
+ function.staticType = methodElement.type;
+ _resolve(
+ node: node,
+ rawType: methodElement.type,
+ name: function.identifier.name,
+ );
+ return;
+ }
+
+ if (methodElement is PropertyAccessorElement) {
+ function.accept(_resolver);
+ _resolveDisallowedExpression(node, methodElement.returnType);
+ return;
+ }
+
+ function.accept(_resolver);
+ node.staticType = DynamicTypeImpl.instance;
+ }
+
+ void _resolvePropertyAccessFunction(
+ FunctionReferenceImpl node, PropertyAccessImpl function) {
+ function.accept(_resolver);
+ var target = function.realTarget;
+
+ DartType targetType;
+ if (target is SuperExpressionImpl) {
+ targetType = target.typeOrThrow;
+ } else if (target is ThisExpressionImpl) {
+ targetType = target.typeOrThrow;
+ } else if (target is SimpleIdentifierImpl) {
+ var targetElement = _resolver.nameScope.lookup(target.name).getter;
+ if (targetElement is VariableElement) {
+ targetType = targetElement.type;
+ } else if (targetElement is PropertyAccessorElement) {
+ targetType = targetElement.returnType;
+ } else {
+ // TODO(srawlins): Can we get here?
+ node.staticType = DynamicTypeImpl.instance;
+ return;
+ }
+ } else if (target is PrefixedIdentifierImpl) {
+ var prefixElement = _resolver.nameScope.lookup(target.prefix.name).getter;
+ if (prefixElement is PrefixElement) {
+ var prefixName = target.identifier.name;
+ var targetElement = prefixElement.scope.lookup(prefixName).getter;
+
+ var methodElement = _resolveTypeProperty(
+ receiver: target,
+ receiverElement: targetElement,
+ name: function.propertyName,
+ nameErrorEntity: function,
+ );
+
+ if (methodElement == null) {
+ // TODO(srawlins): Can we get here?
+ node.staticType = DynamicTypeImpl.instance;
+ return;
+ } else {
+ _resolveReceiverPrefix(node, prefixElement, target, methodElement);
+ return;
+ }
+ } else {
+ // TODO(srawlins): Can we get here?
+ node.staticType = DynamicTypeImpl.instance;
+ return;
+ }
+ } else if (target is ExtensionOverrideImpl) {
+ _resolveExtensionOverride(node, function, target);
+ return;
+ } else {
+ targetType = target.typeOrThrow;
+ }
+
+ var propertyElement = _resolver.typePropertyResolver
+ .resolve(
+ receiver: function.realTarget,
+ receiverType: targetType,
+ name: function.propertyName.name,
+ propertyErrorEntity: function.propertyName,
+ nameErrorEntity: function,
+ )
+ .getter;
+
+ if (propertyElement is TypeParameterElement) {
+ _resolveDisallowedExpression(node, propertyElement!.type);
+ return;
+ }
+
+ _resolve(
+ node: node,
+ rawType: function.staticType,
+ name: propertyElement?.name,
+ );
+ }
+
void _resolveReceiverPrefix(
FunctionReferenceImpl node,
PrefixElement prefixElement,
PrefixedIdentifier prefix,
Element element,
) {
- // TODO(srawlins): Handle `loadLibrary`, as in `p.loadLibrary<int>;`.
-
if (element is MultiplyDefinedElement) {
MultiplyDefinedElement multiply = element;
element = multiply.conflictingElements[0];
@@ -315,8 +424,8 @@
node.function.accept(_resolver);
_resolve(
node: node,
- name: element.name,
rawType: node.function.typeOrThrow as FunctionType,
+ name: element.name,
);
return;
}
@@ -326,6 +435,118 @@
node.staticType = DynamicTypeImpl.instance;
}
+ void _resolveSimpleIdentifierFunction(
+ FunctionReferenceImpl node, SimpleIdentifierImpl function) {
+ var element = _resolver.nameScope.lookup(function.name).getter;
+
+ if (element == null) {
+ DartType receiverType;
+ var enclosingClass = _resolver.enclosingClass;
+ if (enclosingClass != null) {
+ receiverType = enclosingClass.thisType;
+ } else {
+ var enclosingExtension = _resolver.enclosingExtension;
+ if (enclosingExtension != null) {
+ receiverType = enclosingExtension.extendedType;
+ } else {
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.UNDEFINED_IDENTIFIER,
+ function,
+ [function.name],
+ );
+ function.staticType = DynamicTypeImpl.instance;
+ node.staticType = DynamicTypeImpl.instance;
+ return;
+ }
+ }
+
+ var result = _resolver.typePropertyResolver.resolve(
+ receiver: null,
+ receiverType: receiverType,
+ name: function.name,
+ propertyErrorEntity: function,
+ nameErrorEntity: function,
+ );
+
+ var method = result.getter;
+ if (method != null) {
+ if (method.isStatic) {
+ _reportInvalidAccessToStaticMember(function, method,
+ implicitReceiver: true);
+ // Continue to assign types.
+ }
+
+ if (method is PropertyAccessorElement) {
+ _resolveDisallowedExpression(node, method.returnType);
+ return;
+ }
+
+ function.staticElement = method;
+ function.staticType = method.type;
+ _resolve(node: node, rawType: method.type, name: function.name);
+ return;
+ } else {
+ _resolver.errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.UNDEFINED_METHOD,
+ function,
+ [function.name, enclosingClass],
+ );
+ function.staticType = DynamicTypeImpl.instance;
+ node.staticType = DynamicTypeImpl.instance;
+ return;
+ }
+ }
+
+ // Classes and type aliases are checked first so as to include a
+ // PropertyAccess parent check, which does not need to be done for
+ // functions.
+ if (element is ClassElement || element is TypeAliasElement) {
+ // A type-instantiated constructor tearoff like `C<int>.name` or
+ // `prefix.C<int>.name` is initially represented as a [PropertyAccess]
+ // with a [FunctionReference] target.
+ if (node.parent is PropertyAccess) {
+ _resolveConstructorReference(node);
+ return;
+ } else if (element is ClassElement) {
+ function.staticElement = element;
+ _resolveDirectTypeLiteral(node, function, element);
+ return;
+ } else if (element is TypeAliasElement) {
+ function.staticElement = element;
+ _resolveTypeAlias(node: node, element: element, typeAlias: function);
+ return;
+ }
+ } else if (element is MethodElement) {
+ function.staticElement = element;
+ function.staticType = element.type;
+ _resolve(node: node, rawType: element.type, name: element.name);
+ return;
+ } else if (element is FunctionElement) {
+ function.staticElement = element;
+ function.staticType = element.type;
+ _resolve(node: node, rawType: element.type, name: element.name);
+ return;
+ } else if (element is PropertyAccessorElement) {
+ function.staticElement = element;
+ function.staticType = element.returnType;
+ _resolveDisallowedExpression(node, element.returnType);
+ return;
+ } else if (element is ExecutableElement) {
+ function.staticElement = element;
+ function.staticType = element.type;
+ _resolveDisallowedExpression(node, element.type);
+ return;
+ } else if (element is VariableElement) {
+ function.staticElement = element;
+ function.staticType = element.type;
+ _resolveDisallowedExpression(node, element.type);
+ return;
+ } else {
+ _resolveDisallowedExpression(node, DynamicTypeImpl.instance);
+ return;
+ }
+ }
+
/// Returns the element that represents the property named [propertyName] on
/// [classElement].
ExecutableElement? _resolveStaticElement(
@@ -410,7 +631,7 @@
'Unexpected receiverElement type: ${receiverElement.runtimeType}');
return null;
}
- return _resolver.typePropertyResolver
+ var methodElement = _resolver.typePropertyResolver
.resolve(
receiver: receiver,
receiverType: receiverType,
@@ -419,5 +640,10 @@
nameErrorEntity: nameErrorEntity,
)
.getter;
+ if (methodElement != null && methodElement.isStatic) {
+ _reportInvalidAccessToStaticMember(name, methodElement,
+ implicitReceiver: false);
+ }
+ return methodElement;
}
}
diff --git a/pkg/analyzer/lib/src/dart/resolver/instance_creation_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/instance_creation_expression_resolver.dart
new file mode 100644
index 0000000..cf4574c
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/resolver/instance_creation_expression_resolver.dart
@@ -0,0 +1,152 @@
+// 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.
+
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/element/member.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+
+/// A resolver for [InstanceCreationExpression] nodes.
+///
+/// This resolver is responsible for rewriting a given
+/// [InstanceCreationExpression] as a [MethodInvocation] if the parsed
+/// [ConstructorName]'s `type` resolves to a [FunctionReference] or
+/// [ConstructorReference], instead of a [TypeName].
+class InstanceCreationExpressionResolver {
+ /// The resolver driving this participant.
+ final ResolverVisitor _resolver;
+
+ InstanceCreationExpressionResolver(this._resolver);
+
+ void resolve(InstanceCreationExpressionImpl node) {
+ // The parser can parse certain code as [InstanceCreationExpression] when it
+ // might be an invocation of a method on a [FunctionReference] or
+ // [ConstructorReference]. In such a case, it is this resolver's
+ // responsibility to rewrite. For example, given:
+ //
+ // a.m<int>.apply();
+ //
+ // the parser will give an InstanceCreationExpression (`a.m<int>.apply()`)
+ // with a name of `a.m<int>.apply` (ConstructorName) with a type of
+ // `a.m<int>` (TypeName with a name of `a.m` (PrefixedIdentifier) and
+ // typeArguments of `<int>`) and a name of `apply` (SimpleIdentifier). If
+ // `a.m<int>` is actually a function reference, then the
+ // InstanceCreationExpression needs to be rewritten as a MethodInvocation
+ // with a target of `a.m<int>` (a FunctionReference) and a name of `apply`.
+ if (node.keyword == null) {
+ var typeNameTypeArguments = node.constructorName.type.typeArguments;
+ if (typeNameTypeArguments != null) {
+ // This could be a method call on a function reference or a constructor
+ // reference.
+ _resolveWithTypeNameWithTypeArguments(node, typeNameTypeArguments);
+ return;
+ }
+ }
+
+ _resolveInstanceCreationExpression(node);
+ }
+
+ void _inferArgumentTypes(covariant InstanceCreationExpressionImpl node) {
+ var constructorName = node.constructorName;
+ var typeName = constructorName.type;
+ var typeArguments = typeName.typeArguments;
+ var elementToInfer = _resolver.inferenceHelper.constructorElementToInfer(
+ constructorName: constructorName,
+ definingLibrary: _resolver.definingLibrary,
+ );
+ FunctionType? inferred;
+
+ // If the constructor is generic, we'll have a ConstructorMember that
+ // substitutes in type arguments (possibly `dynamic`) from earlier in
+ // resolution.
+ //
+ // Otherwise we'll have a ConstructorElement, and we can skip inference
+ // because there's nothing to infer in a non-generic type.
+ if (elementToInfer != null) {
+ // TODO(leafp): Currently, we may re-infer types here, since we
+ // sometimes resolve multiple times. We should really check that we
+ // have not already inferred something. However, the obvious ways to
+ // check this don't work, since we may have been instantiated
+ // to bounds in an earlier phase, and we *do* want to do inference
+ // in that case.
+
+ // Get back to the uninstantiated generic constructor.
+ // TODO(jmesserly): should we store this earlier in resolution?
+ // Or look it up, instead of jumping backwards through the Member?
+ var rawElement = elementToInfer.element;
+ var constructorType = elementToInfer.asType;
+
+ inferred = _resolver.inferenceHelper.inferArgumentTypesForGeneric(
+ node, constructorType, typeArguments,
+ isConst: node.isConst, errorNode: node.constructorName);
+
+ if (inferred != null) {
+ var arguments = node.argumentList;
+ InferenceContext.setType(arguments, inferred);
+ // Fix up the parameter elements based on inferred method.
+ arguments.correspondingStaticParameters =
+ ResolverVisitor.resolveArgumentsToParameters(
+ arguments, inferred.parameters, null);
+
+ constructorName.type.type = inferred.returnType;
+
+ // Update the static element as well. This is used in some cases, such
+ // as computing constant values. It is stored in two places.
+ var constructorElement = ConstructorMember.from(
+ rawElement,
+ inferred.returnType as InterfaceType,
+ );
+ constructorName.staticElement = constructorElement;
+ }
+ }
+
+ if (inferred == null) {
+ var constructorElement = constructorName.staticElement;
+ if (constructorElement != null) {
+ var type = constructorElement.type;
+ type = _resolver.toLegacyTypeIfOptOut(type) as FunctionType;
+ InferenceContext.setType(node.argumentList, type);
+ }
+ }
+ }
+
+ void _resolveInstanceCreationExpression(InstanceCreationExpressionImpl node) {
+ var whyNotPromotedList = <WhyNotPromotedGetter>[];
+ node.constructorName.accept(_resolver);
+ _inferArgumentTypes(node);
+ _resolver.visitArgumentList(node.argumentList,
+ whyNotPromotedList: whyNotPromotedList);
+ node.accept(_resolver.elementResolver);
+ node.accept(_resolver.typeAnalyzer);
+ _resolver.checkForArgumentTypesNotAssignableInList(
+ node.argumentList, whyNotPromotedList);
+ }
+
+ /// Resolve [node] which has a [TypeName] with type arguments (given as
+ /// [typeNameTypeArguments]).
+ ///
+ /// The instance creation expression may actually be a method call on a
+ /// type-instantiated function reference or constructor reference.
+ void _resolveWithTypeNameWithTypeArguments(
+ InstanceCreationExpressionImpl node,
+ TypeArgumentListImpl typeNameTypeArguments,
+ ) {
+ var typeNameName = node.constructorName.type.name;
+ if (typeNameName is SimpleIdentifierImpl) {
+ // TODO(srawlins): Lookup the name and potentially rewrite `node` as a
+ // [MethodInvocation].
+ _resolveInstanceCreationExpression(node);
+ return;
+ } else if (typeNameName is PrefixedIdentifierImpl) {
+ // TODO(srawlins): Lookup the name and potentially rewrite `node` as a
+ // [MethodInvocation].
+ _resolveInstanceCreationExpression(node);
+ } else {
+ assert(
+ false, 'Unexpected typeNameName type: ${typeNameName.runtimeType}');
+ _resolveInstanceCreationExpression(node);
+ }
+ }
+}
diff --git a/pkg/analyzer/lib/src/dart/resolver/legacy_type_asserter.dart b/pkg/analyzer/lib/src/dart/resolver/legacy_type_asserter.dart
index 94c39d7..7be20ef 100644
--- a/pkg/analyzer/lib/src/dart/resolver/legacy_type_asserter.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/legacy_type_asserter.dart
@@ -144,7 +144,7 @@
return;
}
- type.aliasArguments?.forEach(_assertLegacyType);
+ type.alias?.typeArguments.forEach(_assertLegacyType);
if (type is TypeParameterType) {
_assertLegacyType(type.bound);
diff --git a/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
index 7485e6e..5c7a513 100644
--- a/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
@@ -10,12 +10,12 @@
import 'package:analyzer/src/dart/ast/ast_factory.dart';
import 'package:analyzer/src/dart/ast/extensions.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
+import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type_system.dart';
import 'package:analyzer/src/dart/resolver/extension_member_resolver.dart';
import 'package:analyzer/src/dart/resolver/invocation_inference_helper.dart';
-import 'package:analyzer/src/dart/resolver/scope.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/migratable_ast_info_provider.dart';
import 'package:analyzer/src/generated/resolver.dart';
@@ -42,7 +42,7 @@
final InheritanceManager3 _inheritance;
/// The element for the library containing the compilation unit being visited.
- final LibraryElement _definingLibrary;
+ final LibraryElementImpl _definingLibrary;
/// The URI of [_definingLibrary].
final Uri _definingLibraryUri;
@@ -271,7 +271,7 @@
}) {
_setDynamicResolution(node, whyNotPromotedList: whyNotPromotedList);
- if (nameScope.shouldIgnoreUndefined2(prefix: prefix, name: name)) {
+ if (_definingLibrary.shouldIgnoreUndefined(prefix: prefix, name: name)) {
return;
}
@@ -282,19 +282,6 @@
);
}
- void _reportUndefinedMethod(
- MethodInvocationImpl node,
- String name,
- ClassElement typeReference,
- List<WhyNotPromotedGetter> whyNotPromotedList) {
- _setDynamicResolution(node, whyNotPromotedList: whyNotPromotedList);
- _resolver.errorReporter.reportErrorForNode(
- CompileTimeErrorCode.UNDEFINED_METHOD,
- node.methodName,
- [name, typeReference.displayName],
- );
- }
-
void _reportUseOfVoidType(MethodInvocationImpl node, AstNode errorNode,
List<WhyNotPromotedGetter> whyNotPromotedList) {
_setDynamicResolution(node, whyNotPromotedList: whyNotPromotedList);
@@ -779,7 +766,26 @@
return;
}
- _reportUndefinedMethod(node, name, receiver, whyNotPromotedList);
+ _setDynamicResolution(node, whyNotPromotedList: whyNotPromotedList);
+ if (nameNode.name == 'new') {
+ // Attempting to invoke the unnamed constructor via `C.new(`.
+ if (_resolver.isConstructorTearoffsEnabled) {
+ _resolver.errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.NEW_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT,
+ nameNode,
+ [receiver.displayName],
+ );
+ } else {
+ // [ParserErrorCode.EXPERIMENT_NOT_ENABLED] is reported by the parser.
+ // Do not report extra errors.
+ }
+ } else {
+ _resolver.errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.UNDEFINED_METHOD,
+ node.methodName,
+ [name, receiver.displayName],
+ );
+ }
}
/// If the given [type] is a type parameter, replace with its bound.
diff --git a/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart
index e2d5336..10c9f96 100644
--- a/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart
@@ -13,7 +13,6 @@
import 'package:analyzer/src/dart/element/type_system.dart';
import 'package:analyzer/src/dart/resolver/extension_member_resolver.dart';
import 'package:analyzer/src/dart/resolver/resolution_result.dart';
-import 'package:analyzer/src/dart/resolver/scope.dart';
import 'package:analyzer/src/error/assignment_verifier.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/resolver.dart';
@@ -590,7 +589,7 @@
if (hasRead && readElement == null || hasWrite && writeElement == null) {
if (!forAnnotation &&
- !_resolver.nameScope.shouldIgnoreUndefined2(
+ !_resolver.definingLibrary.shouldIgnoreUndefined(
prefix: target.name,
name: identifier.name,
)) {
diff --git a/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart b/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
index 6a03d38..f08fb8d 100644
--- a/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
@@ -56,6 +56,7 @@
/// 3. Resolve all [TypeName]s - set elements and types.
/// 4. Resolve all [GenericFunctionType]s - set their types.
class ResolutionVisitor extends RecursiveAstVisitor<void> {
+ LibraryElementImpl _libraryElement;
final TypeProvider _typeProvider;
final CompilationUnitElementImpl _unitElement;
final bool _isNonNullableByDefault;
@@ -102,13 +103,14 @@
);
var typeNameResolver = TypeNameResolver(
- libraryElement.typeSystem,
+ libraryElement,
typeProvider,
isNonNullableByDefault,
errorReporter,
);
return ResolutionVisitor._(
+ libraryElement,
typeProvider,
unitElement,
isNonNullableByDefault,
@@ -122,6 +124,7 @@
}
ResolutionVisitor._(
+ this._libraryElement,
this._typeProvider,
this._unitElement,
this._isNonNullableByDefault,
@@ -1211,7 +1214,7 @@
// If the type is not an InterfaceType, then visitTypeName() sets the type
// to be a DynamicTypeImpl
Identifier name = typeName.name;
- if (!_nameScope.shouldIgnoreUndefined(name)) {
+ if (!_libraryElement.shouldIgnoreUndefinedIdentifier(name)) {
_errorReporter.reportErrorForNode(errorCode, name, [name.name]);
}
}
diff --git a/pkg/analyzer/lib/src/dart/resolver/scope.dart b/pkg/analyzer/lib/src/dart/resolver/scope.dart
index 95850f3..845c8e1 100644
--- a/pkg/analyzer/lib/src/dart/resolver/scope.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/scope.dart
@@ -352,35 +352,6 @@
}
extension ScopeExtension on Scope {
- /// Return `true` if the fact that the given [node] is not defined should be
- /// ignored (from the perspective of error reporting).
- bool shouldIgnoreUndefined(Identifier node) {
- if (node is PrefixedIdentifier) {
- return shouldIgnoreUndefined2(
- prefix: node.prefix.name,
- name: node.identifier.name,
- );
- }
-
- return shouldIgnoreUndefined2(
- prefix: null,
- name: (node as SimpleIdentifier).name,
- );
- }
-
- /// Return `true` if the fact that the identifier with the given [prefix]
- /// (might be `null`) and [name] is not defined should be ignored (from the
- /// perspective of error reporting).
- bool shouldIgnoreUndefined2({
- required String? prefix,
- required String name,
- }) {
- return _enclosingLibraryScope.shouldIgnoreUndefined(
- prefix: prefix,
- name: name,
- );
- }
-
List<ExtensionElement> get extensions {
return _enclosingLibraryScope.extensions;
}
diff --git a/pkg/analyzer/lib/src/dart/resolver/simple_identifier_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/simple_identifier_resolver.dart
index a3e5943..4c872f9 100644
--- a/pkg/analyzer/lib/src/dart/resolver/simple_identifier_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/simple_identifier_resolver.dart
@@ -14,7 +14,6 @@
import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart';
import 'package:analyzer/src/dart/resolver/invocation_inference_helper.dart';
import 'package:analyzer/src/dart/resolver/property_element_resolver.dart';
-import 'package:analyzer/src/dart/resolver/scope.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/resolver.dart';
@@ -203,7 +202,8 @@
CompileTimeErrorCode.UNDEFINED_IDENTIFIER_AWAIT,
node,
);
- } else if (!_resolver.nameScope.shouldIgnoreUndefined(node)) {
+ } else if (!_resolver.definingLibrary
+ .shouldIgnoreUndefinedIdentifier(node)) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.UNDEFINED_IDENTIFIER,
node,
diff --git a/pkg/analyzer/lib/src/dart/resolver/type_name_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/type_name_resolver.dart
index 4acea06..3f3c167 100644
--- a/pkg/analyzer/lib/src/dart/resolver/type_name_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/type_name_resolver.dart
@@ -16,7 +16,6 @@
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type_system.dart';
-import 'package:analyzer/src/dart/resolver/scope.dart';
import 'package:analyzer/src/diagnostic/diagnostic_factory.dart';
import 'package:analyzer/src/error/codes.dart';
@@ -24,6 +23,7 @@
///
/// The client must set [nameScope] before calling [resolveTypeName].
class TypeNameResolver {
+ final LibraryElementImpl _libraryElement;
final TypeSystemImpl typeSystem;
final DartType dynamicType;
final bool isNonNullableByDefault;
@@ -56,9 +56,10 @@
/// If [resolveTypeName] reported an error, this flag is set to `true`.
bool hasErrorReported = false;
- TypeNameResolver(this.typeSystem, TypeProvider typeProvider,
+ TypeNameResolver(this._libraryElement, TypeProvider typeProvider,
this.isNonNullableByDefault, this.errorReporter)
- : dynamicType = typeProvider.dynamicType;
+ : typeSystem = _libraryElement.typeSystem,
+ dynamicType = typeProvider.dynamicType;
bool get _genericMetadataIsEnabled =>
enclosingClass!.library.featureSet.isEnabled(Feature.generic_metadata);
@@ -285,7 +286,7 @@
void _resolveToElement(TypeNameImpl node, Element? element) {
if (element == null) {
node.type = dynamicType;
- if (!nameScope.shouldIgnoreUndefined(node.name)) {
+ if (!_libraryElement.shouldIgnoreUndefinedIdentifier(node.name)) {
_ErrorHelper(errorReporter).reportNullOrNonTypeElement(node, null);
}
return;
diff --git a/pkg/analyzer/lib/src/dart/resolver/typed_literal_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/typed_literal_resolver.dart
index ee009b4..e781de9 100644
--- a/pkg/analyzer/lib/src/dart/resolver/typed_literal_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/typed_literal_resolver.dart
@@ -37,7 +37,7 @@
TypeSystemImpl typeSystem, TypeProviderImpl typeProvider,
{MigratableAstInfoProvider migratableAstInfoProvider =
const MigratableAstInfoProvider()}) {
- var library = resolver.definingLibrary as LibraryElementImpl;
+ var library = resolver.definingLibrary;
var analysisOptions = library.context.analysisOptions;
var analysisOptionsImpl = analysisOptions as AnalysisOptionsImpl;
return TypedLiteralResolver._(
diff --git a/pkg/analyzer/lib/src/error/best_practices_verifier.dart b/pkg/analyzer/lib/src/error/best_practices_verifier.dart
index a1d8739..bfa745d 100644
--- a/pkg/analyzer/lib/src/error/best_practices_verifier.dart
+++ b/pkg/analyzer/lib/src/error/best_practices_verifier.dart
@@ -755,7 +755,7 @@
// not report synthetic `dynamic` in place of an unresolved type.
if ((type.element == _nullType.element ||
(type.isDynamic && name == 'dynamic')) &&
- type.aliasElement == null) {
+ type.alias == null) {
_errorReporter.reportErrorForNode(
HintCode.UNNECESSARY_QUESTION_MARK, node, [name]);
}
@@ -1048,7 +1048,7 @@
...element.typeParameters.map((tp) => tp.bound),
];
for (var type in signatureTypes) {
- var aliasElement = type?.aliasElement;
+ var aliasElement = type?.alias?.element;
if (aliasElement != null && aliasElement.hasInternal) {
_errorReporter.reportErrorForNode(
HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT_INDIRECTLY,
diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart
index a5fdaf2..fb2881f 100644
--- a/pkg/analyzer/lib/src/error/codes.dart
+++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -10505,6 +10505,18 @@
/**
* No parameters.
*/
+ static const CompileTimeErrorCode DISALLOWED_TYPE_INSTANTIATION_EXPRESSION =
+ CompileTimeErrorCode(
+ 'DISALLOWED_TYPE_INSTANTIATION_EXPRESSION',
+ 'Only a generic type, generic function, generic instance method, or '
+ 'generic constructor can be type instantiated.',
+ correction:
+ 'Try instantiating the type(s) of a generic type, generic '
+ 'function, generic instance method, or generic constructor.');
+
+ /**
+ * No parameters.
+ */
// #### Description
//
// The analyzer produces this diagnostic when the static type of the
@@ -14632,6 +14644,22 @@
/**
* Parameters:
+ * 0: the number of type parameters that were declared
+ * 1: the number of type arguments provided
+ */
+ static const CompileTimeErrorCode
+ WRONG_NUMBER_OF_TYPE_ARGUMENTS_ANONYMOUS_FUNCTION = CompileTimeErrorCode(
+ 'WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION',
+ "This function is declared with {0} type parameters, "
+ "but {1} type arguments were given.",
+ correction:
+ "Try adjusting the number of type arguments to match the number "
+ "of type parameters.",
+ hasPublishedDocs: true,
+ uniqueName: 'WRONG_NUMBER_OF_TYPE_ARGUMENTS_ANONYMOUS_FUNCTION');
+
+ /**
+ * Parameters:
* 0: the name of the class being instantiated
* 1: the name of the constructor being invoked
*/
diff --git a/pkg/analyzer/lib/src/error/type_arguments_verifier.dart b/pkg/analyzer/lib/src/error/type_arguments_verifier.dart
index e4a6930..55d66ce 100644
--- a/pkg/analyzer/lib/src/error/type_arguments_verifier.dart
+++ b/pkg/analyzer/lib/src/error/type_arguments_verifier.dart
@@ -210,10 +210,10 @@
List<TypeParameterElement> typeParameters;
List<DartType> typeArguments;
- var aliasElement = type.aliasElement;
- if (aliasElement != null) {
- typeParameters = aliasElement.typeParameters;
- typeArguments = type.aliasArguments!;
+ var alias = type.alias;
+ if (alias != null) {
+ typeParameters = alias.element.typeParameters;
+ typeArguments = alias.typeArguments;
} else if (type is InterfaceType) {
typeParameters = type.element.typeParameters;
typeArguments = type.typeArguments;
@@ -277,8 +277,9 @@
// Prepare type arguments for checking for super-bounded.
type = _typeSystem.replaceTopAndBottom(type);
- if (type.aliasElement != null) {
- typeArguments = type.aliasArguments!;
+ alias = type.alias;
+ if (alias != null) {
+ typeArguments = alias.typeArguments;
} else if (type is InterfaceType) {
typeArguments = type.typeArguments;
} else {
@@ -422,9 +423,9 @@
bool _isMissingTypeArguments(AstNode node, DartType type, Element? element,
Expression? inferenceContextNode) {
List<DartType> typeArguments;
- var aliasElement = type.aliasElement;
- if (aliasElement != null) {
- typeArguments = type.aliasArguments!;
+ var alias = type.alias;
+ if (alias != null) {
+ typeArguments = alias.typeArguments;
} else if (type is InterfaceType) {
typeArguments = type.typeArguments;
} else {
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index cc5fc13..2a378e11 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -498,7 +498,8 @@
var declaration = node.thisOrAncestorOfType<ClassDeclaration>();
var superclassName = declaration?.extendsClause?.superclass.name;
if (superclassName != null &&
- _resolver.nameScope.shouldIgnoreUndefined(superclassName)) {
+ _resolver.definingLibrary
+ .shouldIgnoreUndefinedIdentifier(superclassName)) {
return;
}
var argumentList = node.argumentList;
diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart
index 7f04b64..c678842 100644
--- a/pkg/analyzer/lib/src/generated/engine.dart
+++ b/pkg/analyzer/lib/src/generated/engine.dart
@@ -281,6 +281,10 @@
/// This option is experimental and subject to change.
bool implicitDynamic = true;
+ /// Indicates whether linter exceptions should be propagated to the caller (by
+ /// re-throwing them)
+ bool propagateLinterExceptions = false;
+
/// A flag indicating whether inference failures are allowed, off by default.
///
/// This option is experimental and subject to change.
@@ -319,6 +323,7 @@
if (options is AnalysisOptionsImpl) {
implicitCasts = options.implicitCasts;
implicitDynamic = options.implicitDynamic;
+ propagateLinterExceptions = options.propagateLinterExceptions;
strictInference = options.strictInference;
strictRawTypes = options.strictRawTypes;
}
@@ -382,6 +387,7 @@
// Append boolean flags.
buffer.addBool(implicitCasts);
buffer.addBool(implicitDynamic);
+ buffer.addBool(propagateLinterExceptions);
buffer.addBool(strictInference);
buffer.addBool(strictRawTypes);
buffer.addBool(useFastaParser);
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index b4880fb..3ad6c31 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -518,8 +518,9 @@
_withEnclosingExecutable(element, () {
_checkForInvalidModifierOnBody(
node.body, CompileTimeErrorCode.INVALID_MODIFIER_ON_CONSTRUCTOR);
- _checkForConstConstructorWithNonFinalField(node, element);
- _checkForConstConstructorWithNonConstSuper(node);
+ if (!_checkForConstConstructorWithNonConstSuper(node)) {
+ _checkForConstConstructorWithNonFinalField(node, element);
+ }
_constructorFieldsVerifier.verify(node);
_checkForRedirectingConstructorErrorCodes(node);
_checkForMultipleSuperInitializers(node);
@@ -1851,23 +1852,40 @@
/// are no invocations of non-'const' super constructors, and that there are
/// no instance variables mixed in.
///
+ /// Return `true` if an error is reported here, and the caller should stop
+ /// checking the constructor for constant-related errors.
+ ///
/// See [CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER], and
/// [CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD].
- void _checkForConstConstructorWithNonConstSuper(
+ bool _checkForConstConstructorWithNonConstSuper(
ConstructorDeclaration constructor) {
if (!_enclosingExecutable.isConstConstructor) {
- return;
+ return false;
}
// OK, const factory, checked elsewhere
if (constructor.factoryKeyword != null) {
- return;
+ return false;
}
// check for mixins
var instanceFields = <FieldElement>[];
for (var mixin in _enclosingClass!.mixins) {
- instanceFields.addAll(mixin.element.fields
- .where((field) => !field.isStatic && !field.isSynthetic));
+ instanceFields.addAll(mixin.element.fields.where((field) {
+ if (field.isStatic) {
+ return false;
+ }
+ if (field.isSynthetic) {
+ return false;
+ }
+ // From the abstract and external fields specification:
+ // > An abstract instance variable declaration D is treated as an
+ // > abstract getter declaration and possibly an abstract setter
+ // > declaration. The setter is included if and only if D is non-final.
+ if (field.isAbstract && field.isFinal) {
+ return false;
+ }
+ return true;
+ }));
}
if (instanceFields.length == 1) {
var field = instanceFields.single;
@@ -1875,7 +1893,7 @@
CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD,
constructor.returnType,
["'${field.enclosingElement.name}.${field.name}'"]);
- return;
+ return true;
} else if (instanceFields.length > 1) {
var fieldNames = instanceFields
.map((field) => "'${field.enclosingElement.name}.${field.name}'")
@@ -1884,7 +1902,7 @@
CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELDS,
constructor.returnType,
[fieldNames]);
- return;
+ return true;
}
// try to find and check super constructor invocation
@@ -1892,26 +1910,26 @@
if (initializer is SuperConstructorInvocation) {
var element = initializer.staticElement;
if (element == null || element.isConst) {
- return;
+ return false;
}
errorReporter.reportErrorForNode(
CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER,
initializer,
[element.enclosingElement.displayName]);
- return;
+ return true;
}
}
// no explicit super constructor invocation, check default constructor
var supertype = _enclosingClass!.supertype;
if (supertype == null) {
- return;
+ return false;
}
if (supertype.isDartCoreObject) {
- return;
+ return false;
}
var unnamedConstructor = supertype.element.unnamedConstructor;
if (unnamedConstructor == null || unnamedConstructor.isConst) {
- return;
+ return false;
}
// default constructor is not 'const', report problem
@@ -1919,6 +1937,7 @@
CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER,
constructor.returnType,
[supertype]);
+ return true;
}
/// Verify that if the given [constructor] declaration is 'const' then there
@@ -1935,10 +1954,6 @@
if (!classElement.hasNonFinalField) {
return;
}
- // TODO(brianwilkerson) Stop generating
- // CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD when either
- // CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER or
- // CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD is also generated.
errorReporter.reportErrorForName(
CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD,
constructor);
diff --git a/pkg/analyzer/lib/src/generated/ffi_verifier.dart b/pkg/analyzer/lib/src/generated/ffi_verifier.dart
index 8382b13..576627a 100644
--- a/pkg/analyzer/lib/src/generated/ffi_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/ffi_verifier.dart
@@ -23,6 +23,7 @@
static const _dartFfiLibraryName = 'dart.ffi';
static const _isLeafParamName = 'isLeaf';
static const _opaqueClassName = 'Opaque';
+ static const _ffiNativeName = 'FfiNative';
static const List<String> _primitiveIntegerNativeTypes = [
'Int8',
@@ -76,8 +77,8 @@
inCompound = true;
compound = node;
if (node.declaredElement!.isEmptyStruct) {
- _errorReporter
- .reportErrorForNode(FfiCode.EMPTY_STRUCT, node, [node.name]);
+ _errorReporter.reportErrorForNode(
+ FfiCode.EMPTY_STRUCT, node.name, [node.name.name]);
}
if (className == _structClassName) {
_validatePackedAnnotation(node.metadata);
@@ -155,6 +156,12 @@
}
@override
+ void visitFunctionDeclaration(FunctionDeclaration node) {
+ _checkFfiNative(node);
+ super.visitFunctionDeclaration(node);
+ }
+
+ @override
void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
var element = node.staticElement;
if (element is MethodElement) {
@@ -196,6 +203,12 @@
}
@override
+ void visitMethodDeclaration(MethodDeclaration node) {
+ _checkFfiNative(node);
+ super.visitMethodDeclaration(node);
+ }
+
+ @override
void visitMethodInvocation(MethodInvocation node) {
var element = node.methodName.staticElement;
if (element is MethodElement) {
@@ -256,6 +269,38 @@
super.visitPropertyAccess(node);
}
+ void _checkFfiNative(Declaration node) {
+ NodeList<Annotation> annotations = node.metadata;
+ if (annotations.isEmpty) {
+ return;
+ }
+
+ for (Annotation annotation in annotations) {
+ if (annotation.name.name == _ffiNativeName) {
+ // All FFI Natives must be static.
+ final isStatic = (node is FunctionDeclaration) ||
+ ((node is MethodDeclaration) && node.isStatic);
+ if (!isStatic) {
+ _errorReporter.reportErrorForNode(
+ FfiCode.FFI_NATIVE_ONLY_STATIC, node);
+ }
+ // Leaf call FFI Natives can't use Handles.
+ ArgumentList? argumentList = annotation.arguments;
+ if (argumentList != null) {
+ NodeList<Expression> arguments = argumentList.arguments;
+ TypeArgumentList? typeArgumentList = annotation.typeArguments;
+ if (typeArgumentList != null) {
+ NodeList<TypeAnnotation> typeArguments = typeArgumentList.arguments;
+ if (typeArguments.isNotEmpty && typeArguments[0].type != null) {
+ _validateFfiLeafCallUsesNoHandles(
+ arguments, typeArguments[0].type!, node);
+ }
+ }
+ }
+ }
+ }
+ }
+
/// Returns `true` if [nativeType] is a C type that has a size.
bool _isSized(DartType nativeType) {
switch (_primitiveNativeType(nativeType)) {
@@ -499,7 +544,8 @@
_errorReporter.reportErrorForNode(
FfiCode.MUST_BE_A_SUBTYPE, node, [TPrime, F, 'asFunction']);
}
- _validateFfiLeafCallUsesNoHandles(node, TPrime, node);
+ _validateFfiLeafCallUsesNoHandles(
+ node.argumentList.arguments, TPrime, node);
}
_validateIsLeafIsConst(node);
}
@@ -592,8 +638,7 @@
}
void _validateFfiLeafCallUsesNoHandles(
- MethodInvocation node, DartType nativeType, AstNode errorNode) {
- final args = node.argumentList.arguments;
+ NodeList<Expression> args, DartType nativeType, AstNode errorNode) {
if (args.isNotEmpty) {
for (final arg in args) {
if (arg is NamedExpression) {
@@ -670,6 +715,8 @@
} else if (declaredType.isCompoundSubtype) {
final clazz = (declaredType as InterfaceType).element;
if (clazz.isEmptyStruct) {
+ // TODO(brianwilkerson) There are no tests for this branch. Ensure
+ // that the diagnostic is correct and add tests.
_errorReporter
.reportErrorForNode(FfiCode.EMPTY_STRUCT, node, [clazz.name]);
}
@@ -705,8 +752,13 @@
final DartType T = node.typeArgumentTypes![0];
if (!_isValidFfiNativeFunctionType(T)) {
- _errorReporter.reportErrorForNode(
- FfiCode.MUST_BE_A_NATIVE_FUNCTION_TYPE, node, [T, 'fromFunction']);
+ AstNode errorNode = node.methodName;
+ var typeArgument = node.typeArguments?.arguments[0];
+ if (typeArgument != null) {
+ errorNode = typeArgument;
+ }
+ _errorReporter.reportErrorForNode(FfiCode.MUST_BE_A_NATIVE_FUNCTION_TYPE,
+ errorNode, [T, 'fromFunction']);
return;
}
@@ -765,7 +817,7 @@
/// `DynamicLibrary.lookupFunction<S, F>()`.
void _validateLookupFunction(MethodInvocation node) {
final typeArguments = node.typeArguments?.arguments;
- if (typeArguments?.length != 2) {
+ if (typeArguments == null || typeArguments.length != 2) {
// There are other diagnostics reported against the invocation and the
// diagnostics generated below might be inaccurate, so don't report them.
return;
@@ -775,18 +827,19 @@
final DartType S = argTypes[0];
final DartType F = argTypes[1];
if (!_isValidFfiNativeFunctionType(S)) {
- final AstNode errorNode = typeArguments![0];
+ final AstNode errorNode = typeArguments[0];
_errorReporter.reportErrorForNode(FfiCode.MUST_BE_A_NATIVE_FUNCTION_TYPE,
errorNode, [S, 'lookupFunction']);
return;
}
if (!_validateCompatibleFunctionTypes(F, S)) {
- final AstNode errorNode = typeArguments![1];
+ final AstNode errorNode = typeArguments[1];
_errorReporter.reportErrorForNode(
FfiCode.MUST_BE_A_SUBTYPE, errorNode, [S, F, 'lookupFunction']);
}
_validateIsLeafIsConst(node);
- _validateFfiLeafCallUsesNoHandles(node, S, typeArguments![0]);
+ _validateFfiLeafCallUsesNoHandles(
+ node.argumentList.arguments, S, typeArguments[0]);
}
/// Validate that none of the [annotations] are from `dart:ffi`.
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 112f2e7..6a09580 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -21,8 +21,7 @@
import 'package:analyzer/src/dart/ast/extensions.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
-import 'package:analyzer/src/dart/element/member.dart'
- show ConstructorMember, Member;
+import 'package:analyzer/src/dart/element/member.dart' show Member;
import 'package:analyzer/src/dart/element/nullability_eliminator.dart';
import 'package:analyzer/src/dart/element/scope.dart';
import 'package:analyzer/src/dart/element/type.dart';
@@ -38,6 +37,7 @@
import 'package:analyzer/src/dart/resolver/function_expression_invocation_resolver.dart';
import 'package:analyzer/src/dart/resolver/function_expression_resolver.dart';
import 'package:analyzer/src/dart/resolver/function_reference_resolver.dart';
+import 'package:analyzer/src/dart/resolver/instance_creation_expression_resolver.dart';
import 'package:analyzer/src/dart/resolver/invocation_inference_helper.dart';
import 'package:analyzer/src/dart/resolver/lexical_lookup.dart';
import 'package:analyzer/src/dart/resolver/method_invocation_resolver.dart';
@@ -210,10 +210,6 @@
@override
final TypeSystemImpl typeSystem;
- /// The element representing the function containing the current node, or
- /// `null` if the current node is not contained in a function.
- ExecutableElement? _enclosingFunction;
-
/// The helper for tracking if the current location has access to `this`.
final ThisAccessTracker _thisAccessTracker = ThisAccessTracker.unit();
@@ -253,6 +249,9 @@
late final FunctionReferenceResolver _functionReferenceResolver;
+ late final InstanceCreationExpressionResolver
+ _instanceCreationExpressionResolver;
+
/// Initialize a newly created visitor to resolve the nodes in an AST node.
///
/// The [definingLibrary] is the element for the library containing the node
@@ -269,7 +268,7 @@
/// breaking change).
ResolverVisitor(
InheritanceManager3 inheritanceManager,
- LibraryElement definingLibrary,
+ LibraryElementImpl definingLibrary,
Source source,
TypeProvider typeProvider,
AnalysisErrorListener errorListener,
@@ -280,7 +279,7 @@
inheritanceManager,
definingLibrary,
source,
- definingLibrary.typeSystem as TypeSystemImpl,
+ definingLibrary.typeSystem,
typeProvider,
errorListener,
featureSet ??
@@ -292,7 +291,7 @@
ResolverVisitor._(
this.inheritance,
- LibraryElement definingLibrary,
+ LibraryElementImpl definingLibrary,
Source source,
this.typeSystem,
TypeProvider typeProvider,
@@ -373,13 +372,12 @@
typeAnalyzer = StaticTypeAnalyzer(this, migrationResolutionHooks);
_functionReferenceResolver =
FunctionReferenceResolver(this, _isNonNullableByDefault);
+ _instanceCreationExpressionResolver =
+ InstanceCreationExpressionResolver(this);
}
- /// Return the element representing the function containing the current node,
- /// or `null` if the current node is not contained in a function.
- ///
- /// @return the element representing the function containing the current node
- ExecutableElement? get enclosingFunction => _enclosingFunction;
+ bool get isConstructorTearoffsEnabled =>
+ _featureSet.isEnabled(Feature.constructor_tearoffs);
/// Return the object providing promoted or declared types of variables.
LocalVariableTypeProvider get localVariableTypeProvider {
@@ -1218,13 +1216,10 @@
@override
void visitConstructorDeclaration(ConstructorDeclaration node) {
- var outerFunction = _enclosingFunction;
- _enclosingFunction = node.declaredElement;
-
flowAnalysis!.topLevelDeclaration_enter(node, node.parameters);
flowAnalysis!.executableDeclaration_enter(node, node.parameters, false);
- var returnType = _enclosingFunction!.type.returnType;
+ var returnType = node.declaredElement!.type.returnType;
InferenceContext.setType(node.body, returnType);
super.visitConstructorDeclaration(node);
@@ -1240,8 +1235,6 @@
flowAnalysis!.executableDeclaration_exit(node.body, false);
flowAnalysis!.topLevelDeclaration_exit();
nullSafetyDeadCodeVerifier.flowEnd(node);
-
- _enclosingFunction = outerFunction;
}
@override
@@ -1442,9 +1435,6 @@
@override
void visitFunctionDeclaration(FunctionDeclaration node) {
- var outerFunction = _enclosingFunction;
- _enclosingFunction = node.declaredElement;
-
bool isLocal = node.parent is FunctionDeclarationStatement;
if (isLocal) {
@@ -1459,7 +1449,7 @@
isLocal,
);
- var functionType = _enclosingFunction!.type;
+ var functionType = node.declaredElement!.type;
InferenceContext.setType(node.functionExpression, functionType);
super.visitFunctionDeclaration(node);
@@ -1484,7 +1474,6 @@
}
nullSafetyDeadCodeVerifier.flowEnd(node);
- _enclosingFunction = outerFunction;
node.accept(elementResolver);
// Note: no need to call the typeAnalyzer since it does not override
// visitFunctionDeclaration
@@ -1498,6 +1487,8 @@
@override
void visitFunctionExpression(covariant FunctionExpressionImpl node) {
+ // Note: we have to update _enclosingFunction because we don't make use of
+ // super.visitFunctionExpression.
var outerFunction = _enclosingFunction;
_enclosingFunction = node.declaredElement;
@@ -1677,15 +1668,7 @@
@override
void visitInstanceCreationExpression(
covariant InstanceCreationExpressionImpl node) {
- var whyNotPromotedList = <Map<DartType, NonPromotionReason> Function()>[];
- node.constructorName.accept(this);
- _inferArgumentTypesForInstanceCreate(node);
- visitArgumentList(node.argumentList,
- whyNotPromotedList: whyNotPromotedList);
- node.accept(elementResolver);
- node.accept(typeAnalyzer);
- checkForArgumentTypesNotAssignableInList(
- node.argumentList, whyNotPromotedList);
+ _instanceCreationExpressionResolver.resolve(node);
}
@override
@@ -1715,13 +1698,10 @@
@override
void visitMethodDeclaration(MethodDeclaration node) {
- var outerFunction = _enclosingFunction;
- _enclosingFunction = node.declaredElement;
-
flowAnalysis!.topLevelDeclaration_enter(node, node.parameters);
flowAnalysis!.executableDeclaration_enter(node, node.parameters, false);
- DartType returnType = _enclosingFunction!.returnType;
+ DartType returnType = node.declaredElement!.returnType;
InferenceContext.setType(node.body, returnType);
super.visitMethodDeclaration(node);
@@ -1737,7 +1717,6 @@
flowAnalysis!.topLevelDeclaration_exit();
nullSafetyDeadCodeVerifier.flowEnd(node);
- _enclosingFunction = outerFunction;
node.accept(elementResolver);
// Note: no need to call the typeAnalyzer since it does not override
// visitMethodDeclaration.
@@ -2176,72 +2155,6 @@
return typeProvider.futureOrType(type);
}
- void _inferArgumentTypesForInstanceCreate(
- covariant InstanceCreationExpressionImpl node) {
- var constructorName = node.constructorName;
-
- var typeName = constructorName.type;
- var typeArguments = typeName.typeArguments;
-
- var elementToInfer = inferenceHelper.constructorElementToInfer(
- constructorName: constructorName,
- definingLibrary: definingLibrary,
- );
-
- FunctionType? inferred;
- // If the constructor is generic, we'll have a ConstructorMember that
- // substitutes in type arguments (possibly `dynamic`) from earlier in
- // resolution.
- //
- // Otherwise we'll have a ConstructorElement, and we can skip inference
- // because there's nothing to infer in a non-generic type.
- if (elementToInfer != null) {
- // TODO(leafp): Currently, we may re-infer types here, since we
- // sometimes resolve multiple times. We should really check that we
- // have not already inferred something. However, the obvious ways to
- // check this don't work, since we may have been instantiated
- // to bounds in an earlier phase, and we *do* want to do inference
- // in that case.
-
- // Get back to the uninstantiated generic constructor.
- // TODO(jmesserly): should we store this earlier in resolution?
- // Or look it up, instead of jumping backwards through the Member?
- var rawElement = elementToInfer.element;
- var constructorType = elementToInfer.asType;
-
- inferred = inferenceHelper.inferArgumentTypesForGeneric(
- node, constructorType, typeArguments,
- isConst: node.isConst, errorNode: node.constructorName);
-
- if (inferred != null) {
- var arguments = node.argumentList;
- InferenceContext.setType(arguments, inferred);
- // Fix up the parameter elements based on inferred method.
- arguments.correspondingStaticParameters =
- resolveArgumentsToParameters(arguments, inferred.parameters, null);
-
- constructorName.type.type = inferred.returnType;
-
- // Update the static element as well. This is used in some cases, such
- // as computing constant values. It is stored in two places.
- var constructorElement = ConstructorMember.from(
- rawElement,
- inferred.returnType as InterfaceType,
- );
- constructorName.staticElement = constructorElement;
- }
- }
-
- if (inferred == null) {
- var constructorElement = constructorName.staticElement;
- if (constructorElement != null) {
- var type = constructorElement.type;
- type = toLegacyTypeIfOptOut(type) as FunctionType;
- InferenceContext.setType(node.argumentList, type);
- }
- }
- }
-
/// Continues resolution of a [FunctionExpressionInvocation] that was created
/// from a rewritten [MethodInvocation]. The target function is already
/// resolved.
@@ -2387,7 +2300,7 @@
ResolverVisitorForMigration(
InheritanceManager3 inheritanceManager,
- LibraryElement definingLibrary,
+ LibraryElementImpl definingLibrary,
Source source,
TypeProvider typeProvider,
AnalysisErrorListener errorListener,
@@ -2457,7 +2370,7 @@
static const _nameScopeProperty = 'nameScope';
/// The element for the library containing the compilation unit being visited.
- final LibraryElement definingLibrary;
+ final LibraryElementImpl definingLibrary;
/// The source representing the compilation unit being visited.
final Source source;
@@ -2487,6 +2400,10 @@
/// visited, or `null` if we are not in the scope of an extension.
ExtensionElement? enclosingExtension;
+ /// The element representing the function containing the current node, or
+ /// `null` if the current node is not contained in a function.
+ ExecutableElement? _enclosingFunction;
+
/// Initialize a newly created visitor to resolve the nodes in a compilation
/// unit.
///
@@ -2511,6 +2428,12 @@
),
nameScope = nameScope ?? LibraryScope(definingLibrary);
+ /// Return the element representing the function containing the current node,
+ /// or `null` if the current node is not contained in a function.
+ ///
+ /// @return the element representing the function containing the current node
+ ExecutableElement? get enclosingFunction => _enclosingFunction;
+
/// Return the implicit label scope in which the current node is being
/// resolved.
ImplicitLabelScope get implicitLabelScope => _implicitLabelScope;
@@ -2644,6 +2567,8 @@
@override
void visitConstructorDeclaration(ConstructorDeclaration node) {
+ var outerFunction = _enclosingFunction;
+ _enclosingFunction = node.declaredElement;
Scope outerScope = nameScope;
try {
ConstructorElement element = node.declaredElement!;
@@ -2673,6 +2598,7 @@
visitConstructorDeclarationInScope(node);
} finally {
nameScope = outerScope;
+ _enclosingFunction = outerFunction;
}
}
@@ -2851,6 +2777,9 @@
@override
void visitFunctionDeclaration(FunctionDeclaration node) {
+ var outerFunction = _enclosingFunction;
+ _enclosingFunction = node.declaredElement;
+
node.metadata.accept(this);
Scope outerScope = nameScope;
try {
@@ -2862,6 +2791,7 @@
visitFunctionDeclarationInScope(node);
} finally {
nameScope = outerScope;
+ _enclosingFunction = outerFunction;
}
}
@@ -2882,6 +2812,8 @@
return;
}
+ var outerFunction = _enclosingFunction;
+ _enclosingFunction = node.declaredElement;
Scope outerScope = nameScope;
try {
ExecutableElement element = node.declaredElement!;
@@ -2892,6 +2824,7 @@
super.visitFunctionExpression(node);
} finally {
nameScope = outerScope;
+ _enclosingFunction = outerFunction;
}
}
@@ -3018,6 +2951,9 @@
@override
void visitMethodDeclaration(MethodDeclaration node) {
+ var outerFunction = _enclosingFunction;
+ _enclosingFunction = node.declaredElement;
+
node.metadata.accept(this);
Scope outerScope = nameScope;
try {
@@ -3029,6 +2965,7 @@
visitMethodDeclarationInScope(node);
} finally {
nameScope = outerScope;
+ _enclosingFunction = outerFunction;
}
}
@@ -3214,10 +3151,6 @@
/// Instances of the class `VariableResolverVisitor` are used to resolve
/// [SimpleIdentifier]s to local variables and formal parameters.
class VariableResolverVisitor extends ScopedVisitor {
- /// The method or function that we are currently visiting, or `null` if we are
- /// not inside a method or function.
- ExecutableElement? _enclosingFunction;
-
/// The container with information about local variables.
final LocalVariableInfo _localVariableInfo = LocalVariableInfo();
@@ -3234,7 +3167,7 @@
/// [nameScope] is the scope used to resolve identifiers in the node that will
/// first be visited. If `null` or unspecified, a new [LibraryScope] will be
/// created based on [definingLibrary] and [typeProvider].
- VariableResolverVisitor(LibraryElement definingLibrary, Source source,
+ VariableResolverVisitor(LibraryElementImpl definingLibrary, Source source,
TypeProvider typeProvider, AnalysisErrorListener errorListener,
{Scope? nameScope})
: super(definingLibrary, source, typeProvider as TypeProviderImpl,
@@ -3243,14 +3176,8 @@
@override
void visitConstructorDeclaration(ConstructorDeclaration node) {
- var outerFunction = _enclosingFunction;
- try {
- (node.body as FunctionBodyImpl).localVariableInfo = _localVariableInfo;
- _enclosingFunction = node.declaredElement;
- super.visitConstructorDeclaration(node);
- } finally {
- _enclosingFunction = outerFunction;
- }
+ (node.body as FunctionBodyImpl).localVariableInfo = _localVariableInfo;
+ super.visitConstructorDeclaration(node);
}
@override
@@ -3258,28 +3185,16 @@
@override
void visitFunctionDeclaration(FunctionDeclaration node) {
- var outerFunction = _enclosingFunction;
- try {
- (node.functionExpression.body as FunctionBodyImpl).localVariableInfo =
- _localVariableInfo;
- _enclosingFunction = node.declaredElement;
- super.visitFunctionDeclaration(node);
- } finally {
- _enclosingFunction = outerFunction;
- }
+ (node.functionExpression.body as FunctionBodyImpl).localVariableInfo =
+ _localVariableInfo;
+ super.visitFunctionDeclaration(node);
}
@override
void visitFunctionExpression(FunctionExpression node) {
if (node.parent is! FunctionDeclaration) {
- var outerFunction = _enclosingFunction;
- try {
- (node.body as FunctionBodyImpl).localVariableInfo = _localVariableInfo;
- _enclosingFunction = node.declaredElement;
- super.visitFunctionExpression(node);
- } finally {
- _enclosingFunction = outerFunction;
- }
+ (node.body as FunctionBodyImpl).localVariableInfo = _localVariableInfo;
+ super.visitFunctionExpression(node);
} else {
super.visitFunctionExpression(node);
}
@@ -3290,14 +3205,8 @@
@override
void visitMethodDeclaration(MethodDeclaration node) {
- var outerFunction = _enclosingFunction;
- try {
- (node.body as FunctionBodyImpl).localVariableInfo = _localVariableInfo;
- _enclosingFunction = node.declaredElement;
- super.visitMethodDeclaration(node);
- } finally {
- _enclosingFunction = outerFunction;
- }
+ (node.body as FunctionBodyImpl).localVariableInfo = _localVariableInfo;
+ super.visitMethodDeclaration(node);
}
@override
diff --git a/pkg/analyzer/lib/src/generated/testing/element_factory.dart b/pkg/analyzer/lib/src/generated/testing/element_factory.dart
index 6045950..ed9b4f8 100644
--- a/pkg/analyzer/lib/src/generated/testing/element_factory.dart
+++ b/pkg/analyzer/lib/src/generated/testing/element_factory.dart
@@ -106,9 +106,11 @@
static ConstructorElementImpl constructorElement(
ClassElement definingClass, String? name, bool isConst,
[List<DartType> argumentTypes = const []]) {
- ConstructorElementImpl constructor = name == null
- ? ConstructorElementImpl("", -1)
- : ConstructorElementImpl(name, 0);
+ var offset = name == null ? -1 : 0;
+ // An unnamed constructor declared with `C.new(` is modeled as unnamed.
+ var constructor = name == null || name == 'new'
+ ? ConstructorElementImpl('', offset)
+ : ConstructorElementImpl(name, offset);
if (name != null) {
if (name.isEmpty) {
constructor.nameEnd = definingClass.name.length;
diff --git a/pkg/analyzer/lib/src/lint/linter_visitor.dart b/pkg/analyzer/lib/src/lint/linter_visitor.dart
index df3f994..0794a4c 100644
--- a/pkg/analyzer/lib/src/lint/linter_visitor.dart
+++ b/pkg/analyzer/lib/src/lint/linter_visitor.dart
@@ -4,6 +4,7 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/lint/linter.dart';
import 'package:analyzer/src/services/lint.dart';
@@ -16,7 +17,9 @@
final NodeLintRegistry registry;
final LintRuleExceptionHandler exceptionHandler;
- LinterVisitor(this.registry, this.exceptionHandler);
+ LinterVisitor(this.registry, [LintRuleExceptionHandler? exceptionHandler])
+ : exceptionHandler =
+ exceptionHandler ?? LinterExceptionHandler(true).logException;
@override
void visitAdjacentStrings(AdjacentStrings node) {
diff --git a/pkg/analyzer/lib/src/macro/api/code.dart b/pkg/analyzer/lib/src/macro/api/code.dart
new file mode 100644
index 0000000..a3fed07
--- /dev/null
+++ b/pkg/analyzer/lib/src/macro/api/code.dart
@@ -0,0 +1,62 @@
+// 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.
+
+/// Combines [parts] into a [String].
+/// Must only contain [Code] or [String] instances.
+String _combineParts(List<Object> parts) {
+ var buffer = StringBuffer();
+
+ void write(Object part) {
+ if (part is String) {
+ buffer.write(part);
+ } else if (part is Code) {
+ buffer.write(part.code);
+ } else if (part is Iterable<Object>) {
+ part.forEach(write);
+ } else {
+ throw UnsupportedError(
+ 'Only String, Code, and List(s) of them are '
+ 'allowed but got ${part.runtimeType}',
+ );
+ }
+ }
+
+ write(parts);
+ return buffer.toString();
+}
+
+/// The representation of a piece of code.
+abstract class Code {
+ String get code;
+
+ @override
+ String toString() => code;
+}
+
+/// A piece of code representing a syntactically valid declaration.
+class Declaration extends Code {
+ @override
+ final String code;
+
+ Declaration(this.code);
+
+ /// Creates a [Declaration] from [parts], which must be of type [Code],
+ /// [String], or [Iterable]s of them.
+ factory Declaration.fromParts(List<Object> parts) =>
+ Declaration(_combineParts(parts));
+}
+
+/// A piece of code that can't be parsed into a valid language construct in its
+/// current form. No validation or parsing is performed.
+class Fragment extends Code {
+ @override
+ final String code;
+
+ Fragment(this.code);
+
+ /// Creates a [Fragment] from [parts], which must be of type [Code],
+ /// [String], or [Iterable]s of them.
+ factory Fragment.fromParts(List<Object> parts) =>
+ Fragment(_combineParts(parts));
+}
diff --git a/pkg/analyzer/lib/src/macro/api/macro.dart b/pkg/analyzer/lib/src/macro/api/macro.dart
new file mode 100644
index 0000000..78eb6c0
--- /dev/null
+++ b/pkg/analyzer/lib/src/macro/api/macro.dart
@@ -0,0 +1,78 @@
+// 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.
+
+import 'package:analyzer/dart/ast/ast.dart' as ast;
+import 'package:analyzer/src/macro/api/code.dart';
+
+/// The api used by [DeclarationMacro]s to contribute new declarations to the
+/// current class.
+///
+/// Note that this is available to macros that run directly on classes, as well
+/// as macros that run on any members of a class.
+abstract class ClassDeclarationBuilder implements DeclarationBuilder {
+ /// Adds a new declaration to the surrounding class.
+ void addToClass(Declaration declaration);
+}
+
+/// The interface for [DeclarationMacro]s that can be applied to classes.
+abstract class ClassDeclarationMacro implements DeclarationMacro {
+ void visitClassDeclaration(
+ ast.ClassDeclaration declaration, ClassDeclarationBuilder builder);
+}
+
+/// The api used by [DeclarationMacro]s to contribute new declarations to the
+/// current library.
+abstract class DeclarationBuilder {
+ /// Adds a new regular declaration to the surrounding library.
+ ///
+ /// Note that type declarations are not supported.
+ void addToLibrary(Declaration declaration);
+
+ /// Return the [Code] of the [node].
+ Code typeAnnotationCode(ast.TypeAnnotation node);
+}
+
+/// The marker interface for macros that are allowed to contribute new
+/// declarations to the program, including both top level and class level
+/// declarations.
+///
+/// These macros run after [TypeMacro] macros, but before [DefinitionMacro]
+/// macros.
+///
+/// These macros can resolve type annotations to specific declarations, and
+/// inspect type hierarchies, but they cannot inspect the declarations on those
+/// type annotations, since new declarations could still be added in this phase.
+abstract class DeclarationMacro implements Macro {}
+
+/// The marker interface for macros that are only allowed to implement or wrap
+/// existing declarations in the program. They cannot introduce any new
+/// declarations that are visible to the program, but are allowed to add
+/// declarations that only they can see.
+///
+/// These macros run after all other types of macros.
+///
+/// These macros can fully reflect on the program since the static shape is
+/// fully defined by the time they run.
+abstract class DefinitionMacro implements Macro {}
+
+/// The interface for [DeclarationMacro]s that can be applied to fields.
+abstract class FieldDeclarationMacro implements DeclarationMacro {
+ void visitFieldDeclaration(
+ ast.FieldDeclaration declaration,
+ ClassDeclarationBuilder builder,
+ );
+}
+
+/// The marker interface for all types of macros.
+abstract class Macro {}
+
+/// The marker interface for macros that are allowed to contribute new type
+/// declarations into the program.
+///
+/// These macros run before all other types of macros.
+///
+/// In exchange for the power to add new type declarations, these macros have
+/// limited introspections capabilities, since new types can be added in this
+/// phase you cannot follow type references back to their declarations.
+abstract class TypeMacro implements Macro {}
diff --git a/pkg/analyzer/lib/src/macro/builders/data_class.dart b/pkg/analyzer/lib/src/macro/builders/data_class.dart
new file mode 100644
index 0000000..664f5d8
--- /dev/null
+++ b/pkg/analyzer/lib/src/macro/builders/data_class.dart
@@ -0,0 +1,89 @@
+// 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.
+
+import 'package:analyzer/dart/ast/ast.dart' as ast;
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/macro/api/code.dart';
+import 'package:analyzer/src/macro/api/macro.dart';
+
+class AutoConstructorMacro implements ClassDeclarationMacro {
+ const AutoConstructorMacro();
+
+ @override
+ void visitClassDeclaration(
+ ast.ClassDeclaration node,
+ ClassDeclarationBuilder builder,
+ ) {
+ // TODO(scheglov) Should we provide the element as a parameter?
+ var classElement = node.declaredElement!;
+ var typeSystem = classElement.library.typeSystem;
+
+ if (classElement.unnamedConstructor != null) {
+ throw ArgumentError(
+ 'Cannot generate a constructor because one already exists',
+ );
+ }
+
+ var fieldsCode = classElement.fields.map((field) {
+ var isNullable = typeSystem.isNullable(field.type);
+ var requiredKeyword = isNullable ? '' : 'required ';
+ return '${requiredKeyword}this.${field.name}';
+ }).join(', ');
+
+ // TODO(scheglov) super constructor
+
+ builder.addToClass(
+ Declaration('${classElement.name}({$fieldsCode});'),
+ );
+ }
+}
+
+class HashCodeMacro implements ClassDeclarationMacro {
+ const HashCodeMacro();
+
+ @override
+ void visitClassDeclaration(
+ ast.ClassDeclaration node,
+ ClassDeclarationBuilder builder,
+ ) {
+ var expression = node.declaredElement!.allFields
+ .map((e) => '${e.name}.hashCode')
+ .join(' ^ ');
+ builder.addToClass(
+ Declaration('''
+@override
+int get hashCode => $expression;'''),
+ );
+ }
+}
+
+class ToStringMacro implements ClassDeclarationMacro {
+ const ToStringMacro();
+
+ @override
+ void visitClassDeclaration(
+ ast.ClassDeclaration node,
+ ClassDeclarationBuilder builder,
+ ) {
+ var classElement = node.declaredElement!;
+ var fieldsCode = classElement.allFields.map((field) {
+ var name = field.name;
+ return '$name: \$$name';
+ }).join(', ');
+ builder.addToClass(
+ Declaration('''
+@override
+String toString() => '${classElement.name}($fieldsCode)';'''),
+ );
+ }
+}
+
+extension on ClassElement {
+ Iterable<FieldElement> get allFields sync* {
+ for (ClassElement? class_ = this; class_ != null;) {
+ yield* class_.fields.where((e) => !e.isSynthetic);
+ class_ = class_.supertype?.element;
+ }
+ }
+}
diff --git a/pkg/analyzer/lib/src/macro/builders/observable.dart b/pkg/analyzer/lib/src/macro/builders/observable.dart
new file mode 100644
index 0000000..6857d34
--- /dev/null
+++ b/pkg/analyzer/lib/src/macro/builders/observable.dart
@@ -0,0 +1,48 @@
+// 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.
+
+import 'package:analyzer/dart/ast/ast.dart' as ast;
+import 'package:analyzer/src/macro/api/code.dart';
+import 'package:analyzer/src/macro/api/macro.dart';
+
+class ObservableMacro implements FieldDeclarationMacro {
+ const ObservableMacro();
+
+ @override
+ void visitFieldDeclaration(
+ ast.FieldDeclaration node,
+ ClassDeclarationBuilder builder,
+ ) {
+ var typeNode = node.fields.type;
+ if (typeNode == null) {
+ throw ArgumentError('@observable can only annotate typed fields.');
+ }
+ var typeCode = builder.typeAnnotationCode(typeNode);
+
+ var fields = node.fields.variables;
+ for (var field in fields) {
+ var name = field.name.name;
+ if (!name.startsWith('_')) {
+ throw ArgumentError(
+ '@observable can only annotate private fields, and it will create '
+ 'public getters and setters for them, but the public field '
+ '$name was annotated.',
+ );
+ }
+ var publicName = name.substring(1);
+
+ var getter = Declaration(
+ '$typeCode get $publicName => $name;',
+ );
+ builder.addToClass(getter);
+
+ var setter = Declaration('''
+set $publicName($typeCode val) {
+ print('Setting $publicName to \${val}');
+ $name = val;
+}''');
+ builder.addToClass(setter);
+ }
+ }
+}
diff --git a/pkg/analyzer/lib/src/macro/impl/macro.dart b/pkg/analyzer/lib/src/macro/impl/macro.dart
new file mode 100644
index 0000000..73e10f7
--- /dev/null
+++ b/pkg/analyzer/lib/src/macro/impl/macro.dart
@@ -0,0 +1,108 @@
+// 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.
+
+import 'dart:typed_data';
+
+import 'package:analyzer/dart/analysis/utilities.dart';
+import 'package:analyzer/dart/ast/ast.dart' as ast;
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/ast/ast.dart' as ast;
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/macro/api/code.dart';
+import 'package:analyzer/src/macro/api/macro.dart';
+import 'package:analyzer/src/summary2/informative_data.dart';
+
+class ClassDeclarationBuilderImpl extends DeclarationBuilderImpl
+ implements ClassDeclarationBuilder {
+ final DeclarationCollector _collector;
+ final ast.ClassDeclarationImpl node;
+
+ ClassDeclarationBuilderImpl(this._collector, this.node);
+
+ @override
+ void addToClass(Declaration declaration) {
+ var declarationCode = declaration.code.trim();
+
+ // TODO(scheglov) feature set
+ // TODO(scheglov) throw if errors?
+ var parseResult = parseString(
+ content: 'class ${node.name.name} { $declarationCode }',
+ );
+ var parsedDeclarations = parseResult.unit.declarations;
+ var parsedClass = parsedDeclarations.single as ast.ClassDeclaration;
+ var parsedMember = parsedClass.members.single;
+ _rebaseOffsets(parsedMember);
+
+ node.members.add(parsedMember);
+ _collector._add(parsedMember, declaration);
+ }
+
+ /// We parsed [node] in the context of some synthetic code string, its
+ /// current offsets only have meaning relative to the begin offset of the
+ /// [node]. So, we update offsets accordingly.
+ static void _rebaseOffsets(ast.AstNode node) {
+ var baseOffset = node.offset;
+ for (Token? t = node.beginToken;
+ t != null && t != node.endToken;
+ t = t.next) {
+ t.offset -= baseOffset;
+ }
+ }
+}
+
+class DeclarationBuilderImpl implements DeclarationBuilder {
+ @override
+ void addToLibrary(Declaration declaration) {
+ // TODO: implement addToLibrary
+ }
+
+ @override
+ Code typeAnnotationCode(ast.TypeAnnotation node) {
+ return Fragment(node.toSource());
+ }
+}
+
+class DeclarationCollector {
+ final Map<ast.AstNode, _CollectedDeclaration> _declarations = {};
+ int _nextId = 0;
+
+ /// Elements for nodes in [_declarations] were built.
+ /// Move information from [_CollectedDeclaration] into elements.
+ void updateElements() {
+ for (var entry in _declarations.entries) {
+ var node = entry.key;
+ if (node is ast.Declaration) {
+ var element = node.declaredElement;
+ if (element is HasMacroGenerationData) {
+ var collectedDeclaration = entry.value;
+ (element as HasMacroGenerationData).macro = MacroGenerationData(
+ collectedDeclaration.id,
+ collectedDeclaration.declaration.code,
+ collectedDeclaration.informative,
+ );
+ }
+ }
+ }
+ }
+
+ void _add(ast.AstNode node, Declaration declaration) {
+ _declarations[node] = _CollectedDeclaration(
+ _nextId++,
+ declaration,
+ writeDeclarationInformative(node),
+ );
+ }
+}
+
+class _CollectedDeclaration {
+ final int id;
+ final Declaration declaration;
+ final Uint8List informative;
+
+ _CollectedDeclaration(
+ this.id,
+ this.declaration,
+ this.informative,
+ );
+}
diff --git a/pkg/analyzer/lib/src/summary2/bundle_reader.dart b/pkg/analyzer/lib/src/summary2/bundle_reader.dart
index cccbbb3..51a33b6 100644
--- a/pkg/analyzer/lib/src/summary2/bundle_reader.dart
+++ b/pkg/analyzer/lib/src/summary2/bundle_reader.dart
@@ -493,12 +493,24 @@
offset: resolutionOffset,
);
- InformativeDataApplier(_elementFactory, _unitsInformativeBytes)
- .applyTo(libraryElement);
+ _declareDartCoreDynamicNever();
+
+ InformativeDataApplier(_elementFactory).applyTo(
+ _unitsInformativeBytes,
+ libraryElement,
+ );
return libraryElement;
}
+ /// These elements are implicitly declared in `dart:core`.
+ void _declareDartCoreDynamicNever() {
+ if (_reference.name == 'dart:core') {
+ _reference.getChild('dynamic').element = DynamicElementImpl.instance;
+ _reference.getChild('Never').element = NeverElementImpl.instance;
+ }
+ }
+
ClassElementImpl _readClassElement(
CompilationUnitElementImpl unitElement,
Reference unitReference,
@@ -580,6 +592,7 @@
element.setLinkedData(reference, linkedData);
ConstructorElementFlags.read(_reader, element);
element.parameters = _readParameters(element, reference);
+ _readMacro(element, element);
return element;
});
}
@@ -840,6 +853,20 @@
return LibraryLanguageVersion(package: package, override: override);
}
+ void _readMacro(Element element, HasMacroGenerationData hasMacro) {
+ if (_reader.readBool()) {
+ hasMacro.macro = MacroGenerationData(
+ _reader.readUInt30(),
+ _reader.readStringUtf8(),
+ Uint8List(0),
+ );
+ InformativeDataApplier(_elementFactory).applyToDeclaration(
+ element,
+ _reader.readUint8List(),
+ );
+ }
+ }
+
List<MethodElementImpl> _readMethods(
CompilationUnitElementImpl unitElement,
ElementImpl enclosingElement,
@@ -863,6 +890,7 @@
element.typeParameters = _readTypeParameters();
element.parameters = _readParameters(element, reference);
element.typeInferenceError = _readTopLevelInferenceError();
+ _readMacro(element, element);
return element;
});
}
@@ -989,6 +1017,7 @@
element.setLinkedData(reference, linkedData);
element.parameters = _readParameters(element, reference);
+ _readMacro(element, element);
return element;
}
@@ -1525,23 +1554,29 @@
parameters: type.parameters,
returnType: type.returnType,
nullabilitySuffix: type.nullabilitySuffix,
- aliasElement: aliasElement,
- aliasArguments: aliasArguments,
+ alias: InstantiatedTypeAliasElementImpl(
+ element: aliasElement,
+ typeArguments: aliasArguments,
+ ),
);
} else if (type is InterfaceType) {
return InterfaceTypeImpl(
element: type.element,
typeArguments: type.typeArguments,
nullabilitySuffix: type.nullabilitySuffix,
- aliasElement: aliasElement,
- aliasArguments: aliasArguments,
+ alias: InstantiatedTypeAliasElementImpl(
+ element: aliasElement,
+ typeArguments: aliasArguments,
+ ),
);
} else if (type is TypeParameterType) {
return TypeParameterTypeImpl(
element: type.element,
nullabilitySuffix: type.nullabilitySuffix,
- aliasElement: aliasElement,
- aliasArguments: aliasArguments,
+ alias: InstantiatedTypeAliasElementImpl(
+ element: aliasElement,
+ typeArguments: aliasArguments,
+ ),
);
} else if (type is VoidType) {
// TODO(scheglov) add support for `void` aliasing
diff --git a/pkg/analyzer/lib/src/summary2/bundle_writer.dart b/pkg/analyzer/lib/src/summary2/bundle_writer.dart
index 528b9d2..5fd0bf8 100644
--- a/pkg/analyzer/lib/src/summary2/bundle_writer.dart
+++ b/pkg/analyzer/lib/src/summary2/bundle_writer.dart
@@ -164,6 +164,7 @@
_resolutionSink.localElements.declareAll(element.parameters);
try {
_writeList(element.parameters, _writeParameterElement);
+ _writeMacro(element.macro);
if (element.isConst || element.isFactory) {
_resolutionSink.writeElement(element.redirectedConstructor);
_resolutionSink._writeNodeList(element.constantInitializers);
@@ -280,6 +281,15 @@
}
}
+ void _writeMacro(MacroGenerationData? macro) {
+ _sink.writeBool(macro != null);
+ if (macro != null) {
+ _sink.writeUInt30(macro.id);
+ _sink.writeStringUtf8(macro.code);
+ _sink.writeUint8List(macro.informative);
+ }
+ }
+
void _writeMethodElement(MethodElement element) {
element as MethodElementImpl;
_sink.writeUInt30(_resolutionSink.offset);
@@ -293,6 +303,8 @@
_sink._writeTopLevelInferenceError(element.typeInferenceError);
_resolutionSink.writeType(element.returnType);
});
+
+ _writeMacro(element.macro);
}
void _writeMixinElement(ClassElement element) {
@@ -367,7 +379,9 @@
_resolutionSink._writeAnnotationList(element.metadata);
_resolutionSink.writeType(element.returnType);
+
_writeList(element.parameters, _writeParameterElement);
+ _writeMacro(element.macro);
}
void _writeReferences(List<Reference> references) {
@@ -706,10 +720,10 @@
}
void _writeTypeAliasElementArguments(DartType type) {
- var aliasElement = type.aliasElement;
- _writeElement(aliasElement);
- if (aliasElement != null) {
- _writeTypeList(type.aliasArguments!);
+ var alias = type.alias;
+ _writeElement(alias?.element);
+ if (alias != null) {
+ _writeTypeList(alias.typeArguments);
}
}
diff --git a/pkg/analyzer/lib/src/summary2/element_builder.dart b/pkg/analyzer/lib/src/summary2/element_builder.dart
index 3737f6e..b5b366b 100644
--- a/pkg/analyzer/lib/src/summary2/element_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/element_builder.dart
@@ -89,6 +89,19 @@
}
}
+ /// Build elements for [members] and add into the [element].
+ void buildMacroClassMembers(
+ ClassElementImpl element,
+ List<ClassMember> members,
+ ) {
+ var holder = _buildClassMembers(element, members);
+
+ element.accessors.addAll(holder.propertyAccessors);
+ element.constructors.addAll(holder.constructors);
+ element.fields.addAll(holder.properties.whereType<FieldElementImpl>());
+ element.methods.addAll(holder.methods);
+ }
+
@override
void visitClassDeclaration(covariant ClassDeclarationImpl node) {
var nameNode = node.name;
@@ -159,6 +172,10 @@
) {
var nameNode = node.name ?? node.returnType;
var name = node.name?.name ?? '';
+ if (name == 'new') {
+ // An unnamed constructor declared with `C.new(` is modeled as unnamed.
+ name = '';
+ }
var nameOffset = nameNode.offset;
var element = ConstructorElementImpl(name, nameOffset);
@@ -868,7 +885,7 @@
}
_EnclosingContext _buildClassMembers(
- ElementImpl element, NodeList<ClassMember> members) {
+ ElementImpl element, List<ClassMember> members) {
var hasConstConstructor = members.any((e) {
return e is ConstructorDeclaration && e.constKeyword != null;
});
@@ -884,29 +901,9 @@
var element = node.declaredElement as ClassElementImpl;
var holder = _buildClassMembers(element, node.members);
element.accessors = holder.propertyAccessors;
+ element.constructors = holder.constructors;
element.fields = holder.properties.whereType<FieldElement>().toList();
element.methods = holder.methods;
-
- var constructors = holder.constructors;
- if (constructors.isEmpty) {
- var containerRef = element.reference!.getChild('@constructor');
- constructors = [
- ConstructorElementImpl('', -1)
- ..isSynthetic = true
- ..reference = containerRef.getChild(''),
- ];
- }
- element.constructors = constructors;
-
- // We have all fields and constructors.
- // Now we can resolve field formal parameters.
- for (var constructor in constructors) {
- for (var parameter in constructor.parameters) {
- if (parameter is FieldFormalParameterElementImpl) {
- parameter.field = element.getField(parameter.name);
- }
- }
- }
}
void _buildExecutableElementChildren({
diff --git a/pkg/analyzer/lib/src/summary2/element_flags.dart b/pkg/analyzer/lib/src/summary2/element_flags.dart
index e808000..529a06f 100644
--- a/pkg/analyzer/lib/src/summary2/element_flags.dart
+++ b/pkg/analyzer/lib/src/summary2/element_flags.dart
@@ -8,8 +8,8 @@
class ClassElementFlags {
static const int _isAbstract = 1 << 0;
- static const int _isMixinApplication = 1 << 1;
- static const int _isSimplyBounded = 1 << 2;
+ static const int _isMixinApplication = 1 << 2;
+ static const int _isSimplyBounded = 1 << 3;
static void read(SummaryDataReader reader, ClassElementImpl element) {
var byte = reader.readByte();
@@ -60,8 +60,8 @@
static const int _isCovariant = 1 << 5;
static const int _isExternal = 1 << 6;
static const int _isFinal = 1 << 7;
- static const int _isLate = 1 << 8;
- static const int _isStatic = 1 << 9;
+ static const int _isLate = 1 << 9;
+ static const int _isStatic = 1 << 10;
static void read(SummaryDataReader reader, FieldElementImpl element) {
var byte = reader.readUInt30();
@@ -161,8 +161,8 @@
static const int _isAbstract = 1 << 1;
static const int _isAsynchronous = 1 << 2;
static const int _isExternal = 1 << 3;
- static const int _isGenerator = 1 << 4;
- static const int _isStatic = 1 << 5;
+ static const int _isGenerator = 1 << 5;
+ static const int _isStatic = 1 << 6;
static void read(SummaryDataReader reader, MethodElementImpl element) {
var byte = reader.readByte();
@@ -217,8 +217,8 @@
static const int _isAbstract = 1 << 3;
static const int _isAsynchronous = 1 << 4;
static const int _isExternal = 1 << 5;
- static const int _isGenerator = 1 << 6;
- static const int _isStatic = 1 << 7;
+ static const int _isGenerator = 1 << 7;
+ static const int _isStatic = 1 << 8;
static void read(
SummaryDataReader reader,
diff --git a/pkg/analyzer/lib/src/summary2/function_type_builder.dart b/pkg/analyzer/lib/src/summary2/function_type_builder.dart
index f59a117..4ab0f6a 100644
--- a/pkg/analyzer/lib/src/summary2/function_type_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/function_type_builder.dart
@@ -190,7 +190,7 @@
} else if (isNNBD) {
nullabilitySuffix = NullabilitySuffix.none;
} else {
- nullabilitySuffix = NullabilitySuffix.question;
+ nullabilitySuffix = NullabilitySuffix.star;
}
return FunctionTypeBuilder(
diff --git a/pkg/analyzer/lib/src/summary2/informative_data.dart b/pkg/analyzer/lib/src/summary2/informative_data.dart
index 1dd1e5f..f14a0f2 100644
--- a/pkg/analyzer/lib/src/summary2/informative_data.dart
+++ b/pkg/analyzer/lib/src/summary2/informative_data.dart
@@ -19,6 +19,15 @@
import 'package:analyzer/src/util/comment.dart';
import 'package:collection/collection.dart';
+/// Write the informative data (mostly offsets) of the given [node].
+/// Throw [UnimplementedError] if [node] is not supported.
+Uint8List writeDeclarationInformative(AstNode node) {
+ var byteSink = ByteSink();
+ var sink = BufferedSink(byteSink);
+ _InformativeDataWriter(sink).writeDeclaration(node);
+ return sink.flushAndTake();
+}
+
Uint8List writeUnitInformative(CompilationUnit unit) {
var byteSink = ByteSink();
var sink = BufferedSink(byteSink);
@@ -55,14 +64,13 @@
class InformativeDataApplier {
final LinkedElementFactory _elementFactory;
- final Map<Uri, Uint8List> _unitsInformativeBytes2;
- InformativeDataApplier(
- this._elementFactory,
- this._unitsInformativeBytes2,
- );
+ InformativeDataApplier(this._elementFactory);
- void applyTo(LibraryElementImpl libraryElement) {
+ void applyTo(
+ Map<Uri, Uint8List> unitsInformativeBytes,
+ LibraryElementImpl libraryElement,
+ ) {
if (_elementFactory.isApplyingInformativeData) {
throw StateError('Unexpected recursion.');
}
@@ -72,7 +80,7 @@
for (var i = 0; i < unitElements.length; i++) {
var unitElement = unitElements[i] as CompilationUnitElementImpl;
var unitUri = unitElement.source.uri;
- var unitInfoBytes = _unitsInformativeBytes2[unitUri];
+ var unitInfoBytes = unitsInformativeBytes[unitUri];
if (unitInfoBytes != null) {
var unitReader = SummaryDataReader(unitInfoBytes);
var unitInfo = _InfoUnit(unitReader);
@@ -140,35 +148,49 @@
_elementFactory.isApplyingInformativeData = false;
}
+ /// Read informative data from [bytes], and apply it to [element].
+ /// The data and the [element] must correspond to each other.
+ void applyToDeclaration(Element element, Uint8List bytes) {
+ if (_elementFactory.isApplyingInformativeData) {
+ throw StateError('Unexpected recursion.');
+ }
+ _elementFactory.isApplyingInformativeData = true;
+
+ var reader = SummaryDataReader(bytes);
+
+ var kindIndex = reader.readByte();
+ var kind = _DeclarationKind.values[kindIndex];
+
+ if (kind == _DeclarationKind.constructorDeclaration &&
+ element is ConstructorElement) {
+ var info = _InfoConstructorDeclaration(reader);
+ _applyToConstructor(element, info);
+ } else if (kind == _DeclarationKind.methodDeclaration &&
+ element is MethodElement) {
+ var info = _InfoMethodDeclaration(reader);
+ _applyToMethod(element, info);
+ } else if (kind == _DeclarationKind.methodDeclaration &&
+ element is PropertyAccessorElement) {
+ var info = _InfoMethodDeclaration(reader);
+ _applyToPropertyAccessor(element, info);
+ } else {
+ throw UnimplementedError(
+ 'Unsupported kind: $kind, '
+ 'or element: ${element.runtimeType}',
+ );
+ }
+
+ _elementFactory.isApplyingInformativeData = false;
+ }
+
void _applyToAccessors(
List<PropertyAccessorElement> elementList,
List<_InfoMethodDeclaration> infoList,
) {
- forCorrespondingPairs<PropertyAccessorElement, _InfoMethodDeclaration>(
+ forCorrespondingPairs(
elementList.notSynthetic,
infoList,
- (element, info) {
- element as PropertyAccessorElementImpl;
- element.setCodeRange(info.codeOffset, info.codeLength);
- element.nameOffset = info.nameOffset;
- element.documentationComment = info.documentationComment;
- _applyToFormalParameters(
- element.parameters_unresolved,
- info.parameters,
- );
-
- var linkedData = element.linkedData;
- if (linkedData is PropertyAccessorElementLinkedData) {
- linkedData.applyConstantOffsets = ApplyConstantOffsets(
- info.constantOffsets,
- (applier) {
- applier.applyToMetadata(element);
- applier.applyToTypeParameters(element.typeParameters);
- applier.applyToFormalParameters(element.parameters);
- },
- );
- }
- },
+ _applyToPropertyAccessor,
);
}
@@ -240,6 +262,32 @@
);
}
+ void _applyToConstructor(
+ ConstructorElement element,
+ _InfoConstructorDeclaration info,
+ ) {
+ element as ConstructorElementImpl;
+ element.setCodeRange(info.codeOffset, info.codeLength);
+ element.periodOffset = info.periodOffset;
+ element.nameOffset = info.nameOffset;
+ element.nameEnd = info.nameEnd;
+ element.documentationComment = info.documentationComment;
+ _applyToFormalParameters(
+ element.parameters_unresolved,
+ info.parameters,
+ );
+
+ var linkedData = element.linkedData as ConstructorElementLinkedData;
+ linkedData.applyConstantOffsets = ApplyConstantOffsets(
+ info.constantOffsets,
+ (applier) {
+ applier.applyToMetadata(element);
+ applier.applyToFormalParameters(element.parameters);
+ applier.applyToConstructorInitializers(element);
+ },
+ );
+ }
+
void _applyToConstructors(
List<ConstructorElement> elementList,
List<_InfoConstructorDeclaration> infoList,
@@ -247,28 +295,7 @@
forCorrespondingPairs<ConstructorElement, _InfoConstructorDeclaration>(
elementList,
infoList,
- (element, info) {
- element as ConstructorElementImpl;
- element.setCodeRange(info.codeOffset, info.codeLength);
- element.periodOffset = info.periodOffset;
- element.nameOffset = info.nameOffset;
- element.nameEnd = info.nameEnd;
- element.documentationComment = info.documentationComment;
- _applyToFormalParameters(
- element.parameters_unresolved,
- info.parameters,
- );
-
- var linkedData = element.linkedData as ConstructorElementLinkedData;
- linkedData.applyConstantOffsets = ApplyConstantOffsets(
- info.constantOffsets,
- (applier) {
- applier.applyToMetadata(element);
- applier.applyToFormalParameters(element.parameters);
- applier.applyToConstructorInitializers(element);
- },
- );
- },
+ _applyToConstructor,
);
}
@@ -499,6 +526,31 @@
);
}
+ void _applyToMethod(MethodElement element, _InfoMethodDeclaration info) {
+ element as MethodElementImpl;
+ element.setCodeRange(info.codeOffset, info.codeLength);
+ element.nameOffset = info.nameOffset;
+ element.documentationComment = info.documentationComment;
+ _applyToTypeParameters(
+ element.typeParameters_unresolved,
+ info.typeParameters,
+ );
+ _applyToFormalParameters(
+ element.parameters_unresolved,
+ info.parameters,
+ );
+
+ var linkedData = element.linkedData as MethodElementLinkedData;
+ linkedData.applyConstantOffsets = ApplyConstantOffsets(
+ info.constantOffsets,
+ (applier) {
+ applier.applyToMetadata(element);
+ applier.applyToTypeParameters(element.typeParameters);
+ applier.applyToFormalParameters(element.parameters);
+ },
+ );
+ }
+
void _applyToMethods(
List<MethodElement> elementList,
List<_InfoMethodDeclaration> infoList,
@@ -506,30 +558,7 @@
forCorrespondingPairs<MethodElement, _InfoMethodDeclaration>(
elementList,
infoList,
- (element, info) {
- element as MethodElementImpl;
- element.setCodeRange(info.codeOffset, info.codeLength);
- element.nameOffset = info.nameOffset;
- element.documentationComment = info.documentationComment;
- _applyToTypeParameters(
- element.typeParameters_unresolved,
- info.typeParameters,
- );
- _applyToFormalParameters(
- element.parameters_unresolved,
- info.parameters,
- );
-
- var linkedData = element.linkedData as MethodElementLinkedData;
- linkedData.applyConstantOffsets = ApplyConstantOffsets(
- info.constantOffsets,
- (applier) {
- applier.applyToMetadata(element);
- applier.applyToTypeParameters(element.typeParameters);
- applier.applyToFormalParameters(element.parameters);
- },
- );
- },
+ _applyToMethod,
);
}
@@ -560,6 +589,32 @@
);
}
+ void _applyToPropertyAccessor(
+ PropertyAccessorElement element,
+ _InfoMethodDeclaration info,
+ ) {
+ element as PropertyAccessorElementImpl;
+ element.setCodeRange(info.codeOffset, info.codeLength);
+ element.nameOffset = info.nameOffset;
+ element.documentationComment = info.documentationComment;
+ _applyToFormalParameters(
+ element.parameters_unresolved,
+ info.parameters,
+ );
+
+ var linkedData = element.linkedData;
+ if (linkedData is PropertyAccessorElementLinkedData) {
+ linkedData.applyConstantOffsets = ApplyConstantOffsets(
+ info.constantOffsets,
+ (applier) {
+ applier.applyToMetadata(element);
+ applier.applyToTypeParameters(element.typeParameters);
+ applier.applyToFormalParameters(element.parameters);
+ },
+ );
+ }
+ }
+
void _applyToTopLevelVariable(
TopLevelVariableElement element,
_InfoTopLevelVariable info,
@@ -629,6 +684,11 @@
}
}
+enum _DeclarationKind {
+ constructorDeclaration,
+ methodDeclaration,
+}
+
class _InfoClassDeclaration {
final int codeOffset;
final int codeLength;
@@ -1289,6 +1349,18 @@
);
}
+ void writeDeclaration(AstNode node) {
+ if (node is ConstructorDeclaration) {
+ sink.addByte(_DeclarationKind.constructorDeclaration.index);
+ _writeConstructor(node);
+ } else if (node is MethodDeclaration) {
+ sink.addByte(_DeclarationKind.methodDeclaration.index);
+ _writeMethod(node);
+ } else {
+ throw UnimplementedError('(${node.runtimeType}) $node');
+ }
+ }
+
int _codeOffsetForVariable(VariableDeclaration node) {
var codeOffset = node.offset;
var variableList = node.parent as VariableDeclarationList;
@@ -1305,22 +1377,24 @@
});
}
+ void _writeConstructor(ConstructorDeclaration node) {
+ sink.writeUInt30(node.offset);
+ sink.writeUInt30(node.length);
+ sink.writeOptionalUInt30(node.period?.offset);
+ var nameNode = node.name ?? node.returnType;
+ sink.writeUInt30(nameNode.offset);
+ sink.writeUInt30(nameNode.end);
+ _writeDocumentationComment(node);
+ _writeFormalParameters(node.parameters);
+ _writeOffsets(
+ metadata: node.metadata,
+ formalParameters: node.parameters,
+ constructorInitializers: node.initializers,
+ );
+ }
+
void _writeConstructors(List<ClassMember> members) {
- sink.writeList2<ConstructorDeclaration>(members, (node) {
- sink.writeUInt30(node.offset);
- sink.writeUInt30(node.length);
- sink.writeOptionalUInt30(node.period?.offset);
- var nameNode = node.name ?? node.returnType;
- sink.writeUInt30(nameNode.offset);
- sink.writeUInt30(nameNode.end);
- _writeDocumentationComment(node);
- _writeFormalParameters(node.parameters);
- _writeOffsets(
- metadata: node.metadata,
- formalParameters: node.parameters,
- constructorInitializers: node.initializers,
- );
- });
+ sink.writeList2<ConstructorDeclaration>(members, _writeConstructor);
}
void _writeDocumentationComment(AnnotatedNode node) {
@@ -1383,19 +1457,7 @@
.whereType<MethodDeclaration>()
.where((e) => e.isGetter || e.isSetter)
.toList(),
- (node) {
- sink.writeUInt30(node.offset);
- sink.writeUInt30(node.length);
- sink.writeUInt30(node.name.offset);
- _writeDocumentationComment(node);
- _writeTypeParameters(node.typeParameters);
- _writeFormalParameters(node.parameters);
- _writeOffsets(
- metadata: node.metadata,
- typeParameters: node.typeParameters,
- formalParameters: node.parameters,
- );
- },
+ _writeMethod,
);
}
@@ -1420,25 +1482,27 @@
);
}
+ void _writeMethod(MethodDeclaration node) {
+ sink.writeUInt30(node.offset);
+ sink.writeUInt30(node.length);
+ sink.writeUInt30(node.name.offset);
+ _writeDocumentationComment(node);
+ _writeTypeParameters(node.typeParameters);
+ _writeFormalParameters(node.parameters);
+ _writeOffsets(
+ metadata: node.metadata,
+ typeParameters: node.typeParameters,
+ formalParameters: node.parameters,
+ );
+ }
+
void _writeMethods(List<ClassMember> members) {
sink.writeList<MethodDeclaration>(
members
.whereType<MethodDeclaration>()
.where((e) => !(e.isGetter || e.isSetter))
.toList(),
- (node) {
- sink.writeUInt30(node.offset);
- sink.writeUInt30(node.length);
- sink.writeUInt30(node.name.offset);
- _writeDocumentationComment(node);
- _writeTypeParameters(node.typeParameters);
- _writeFormalParameters(node.parameters);
- _writeOffsets(
- metadata: node.metadata,
- typeParameters: node.typeParameters,
- formalParameters: node.parameters,
- );
- },
+ _writeMethod,
);
}
diff --git a/pkg/analyzer/lib/src/summary2/library_builder.dart b/pkg/analyzer/lib/src/summary2/library_builder.dart
index 2c1a0b3..c1eb205 100644
--- a/pkg/analyzer/lib/src/summary2/library_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/library_builder.dart
@@ -2,13 +2,15 @@
// 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.
-import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/ast.dart' as ast;
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/dart/ast/ast.dart' as ast;
import 'package:analyzer/src/dart/ast/mixin_super_invoked_names.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/resolver/scope.dart';
+import 'package:analyzer/src/macro/builders/data_class.dart' as macro;
+import 'package:analyzer/src/macro/builders/observable.dart' as macro;
+import 'package:analyzer/src/macro/impl/macro.dart' as macro;
import 'package:analyzer/src/summary2/combinator.dart';
import 'package:analyzer/src/summary2/constructor_initializer_resolver.dart';
import 'package:analyzer/src/summary2/default_value_resolver.dart';
@@ -111,10 +113,7 @@
}
elementBuilder.buildDeclarationElements(linkingUnit.node);
}
- if ('$uri' == 'dart:core') {
- localScope.declare('dynamic', reference.getChild('dynamic'));
- localScope.declare('Never', reference.getChild('Never'));
- }
+ _declareDartCoreDynamicNever();
}
void buildEnumChildren() {
@@ -145,6 +144,38 @@
}
}
+ /// We don't create default constructors during building elements from AST,
+ /// there might be macros that will add one later. So, this method is
+ /// invoked after all macros that affect element models.
+ void processClassConstructors() {
+ // TODO(scheglov) We probably don't need constructors for mixins.
+ var classes = element.topLevelElements
+ .whereType<ClassElementImpl>()
+ .where((e) => !e.isMixinApplication)
+ .toList();
+
+ for (var element in classes) {
+ if (element.constructors.isEmpty) {
+ var containerRef = element.reference!.getChild('@constructor');
+ element.constructors = [
+ ConstructorElementImpl('', -1)
+ ..isSynthetic = true
+ ..reference = containerRef.getChild(''),
+ ];
+ }
+
+ // We have all fields and constructors.
+ // Now we can resolve field formal parameters.
+ for (var constructor in element.constructors) {
+ for (var parameter in constructor.parameters) {
+ if (parameter is FieldFormalParameterElementImpl) {
+ parameter.field = element.getField(parameter.name);
+ }
+ }
+ }
+ }
+ }
+
void resolveConstructors() {
ConstructorInitializerResolver(linker, element).resolve();
}
@@ -162,18 +193,99 @@
void resolveTypes(NodesToBuildType nodesToBuildType) {
for (var linkingUnit in units) {
- var resolver = ReferenceResolver(
- linker,
- nodesToBuildType,
- linker.elementFactory,
- element,
- linkingUnit.reference,
- linkingUnit.node.featureSet.isEnabled(Feature.non_nullable),
- );
+ var resolver = ReferenceResolver(linker, nodesToBuildType, element);
linkingUnit.node.accept(resolver);
}
}
+ /// Run built-in declaration macros.
+ void runDeclarationMacros() {
+ bool hasMacroAnnotation(ast.AnnotatedNode node, String name) {
+ for (var annotation in node.metadata) {
+ var nameNode = annotation.name;
+ if (nameNode is ast.SimpleIdentifier &&
+ annotation.arguments == null &&
+ annotation.constructorName == null &&
+ nameNode.name == name) {
+ var nameElement = element.scope.lookup(name).getter;
+ return nameElement != null &&
+ nameElement.library?.name == 'analyzer.macro.annotations';
+ }
+ }
+ return false;
+ }
+
+ /// Build types for type annotations in new [nodes].
+ void resolveTypeAnnotations(
+ List<ast.AstNode> nodes, {
+ ClassElementImpl? classElement,
+ }) {
+ var nodesToBuildType = NodesToBuildType();
+ var resolver = ReferenceResolver(linker, nodesToBuildType, element);
+ if (classElement != null) {
+ resolver.enterScopeClassElement(classElement);
+ }
+ for (var node in nodes) {
+ node.accept(resolver);
+ }
+ TypesBuilder(linker).build(nodesToBuildType);
+ }
+
+ var collector = macro.DeclarationCollector();
+ for (var linkingUnit in units) {
+ for (var declaration in linkingUnit.node.declarations) {
+ if (declaration is ast.ClassDeclarationImpl) {
+ var members = declaration.members.toList();
+ var classBuilder = macro.ClassDeclarationBuilderImpl(
+ collector,
+ declaration,
+ );
+ if (hasMacroAnnotation(declaration, 'autoConstructor')) {
+ macro.AutoConstructorMacro().visitClassDeclaration(
+ declaration,
+ classBuilder,
+ );
+ }
+ if (hasMacroAnnotation(declaration, 'hashCode')) {
+ macro.HashCodeMacro().visitClassDeclaration(
+ declaration,
+ classBuilder,
+ );
+ }
+ if (hasMacroAnnotation(declaration, 'toString')) {
+ macro.ToStringMacro().visitClassDeclaration(
+ declaration,
+ classBuilder,
+ );
+ }
+ for (var member in members) {
+ if (member is ast.FieldDeclarationImpl) {
+ if (hasMacroAnnotation(member, 'observable')) {
+ macro.ObservableMacro().visitFieldDeclaration(
+ member,
+ classBuilder,
+ );
+ }
+ }
+ }
+
+ var newMembers = declaration.members.sublist(members.length);
+ if (newMembers.isNotEmpty) {
+ var elementBuilder = ElementBuilder(
+ libraryBuilder: this,
+ unitReference: linkingUnit.reference,
+ unitElement: linkingUnit.element,
+ );
+ var classElement = declaration.declaredElement as ClassElementImpl;
+ elementBuilder.buildMacroClassMembers(classElement, newMembers);
+ resolveTypeAnnotations(newMembers, classElement: classElement);
+ }
+ }
+ }
+ }
+ collector.updateElements();
+ }
+
void storeExportScope() {
exports = exportScope.map.values.toList();
linker.elementFactory.setExportsOfLibrary('$uri', exports);
@@ -195,6 +307,19 @@
}
}
+ /// These elements are implicitly declared in `dart:core`.
+ void _declareDartCoreDynamicNever() {
+ if (reference.name == 'dart:core') {
+ var dynamicRef = reference.getChild('dynamic');
+ dynamicRef.element = DynamicElementImpl.instance;
+ localScope.declare('dynamic', dynamicRef);
+
+ var neverRef = reference.getChild('Never');
+ neverRef.element = NeverElementImpl.instance;
+ localScope.declare('Never', neverRef);
+ }
+ }
+
static void build(Linker linker, LinkInputLibrary inputLibrary) {
var elementFactory = linker.elementFactory;
diff --git a/pkg/analyzer/lib/src/summary2/link.dart b/pkg/analyzer/lib/src/summary2/link.dart
index f0b0174..7a33308 100644
--- a/pkg/analyzer/lib/src/summary2/link.dart
+++ b/pkg/analyzer/lib/src/summary2/link.dart
@@ -93,6 +93,7 @@
_createTypeSystem();
_buildEnumChildren();
_resolveTypes();
+ _runDeclarationMacros();
_performTopLevelInference();
_resolveConstructors();
_resolveConstantInitializers();
@@ -213,6 +214,13 @@
TypesBuilder(this).build(nodesToBuildType);
}
+ void _runDeclarationMacros() {
+ for (var library in builders.values) {
+ library.runDeclarationMacros();
+ library.processClassConstructors();
+ }
+ }
+
void _writeLibraries() {
var bundleWriter = BundleWriter(
elementFactory.dynamicRef,
diff --git a/pkg/analyzer/lib/src/summary2/linked_element_factory.dart b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
index a449b97..e83e492 100644
--- a/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
@@ -27,7 +27,6 @@
) {
ArgumentError.checkNotNull(analysisContext, 'analysisContext');
ArgumentError.checkNotNull(analysisSession, 'analysisSession');
- _declareDartCoreDynamicNever();
}
Reference get dynamicRef {
@@ -182,10 +181,22 @@
/// that the client can re-add the bundle, this time read from bytes.
void removeBundle(Set<String> uriStrSet) {
removeLibraries(uriStrSet);
+ }
- // This is the bundle with dart:core and dart:async, based on full ASTs.
- // To link them, the linker set the type provider. We are removing these
- // libraries, and we should also remove the type provider.
+ /// Remove libraries with the specified URIs from the reference tree, and
+ /// any session level caches.
+ void removeLibraries(Set<String> uriStrSet) {
+ for (var uriStr in uriStrSet) {
+ _exportsOfLibrary.remove(uriStr);
+ libraryReaders.remove(uriStr);
+ rootReference.removeChild(uriStr);
+ }
+
+ analysisSession.classHierarchy.removeOfLibraries(uriStrSet);
+ analysisSession.inheritanceManager.removeOfLibraries(uriStrSet);
+
+ // If we discard `dart:core` and `dart:async`, we should also discard
+ // the type provider.
if (uriStrSet.contains('dart:core')) {
if (!uriStrSet.contains('dart:async')) {
throw StateError(
@@ -200,23 +211,9 @@
);
}
analysisContext.clearTypeProvider();
- _declareDartCoreDynamicNever();
}
}
- /// Remove libraries with the specified URIs from the reference tree, and
- /// any session level caches.
- void removeLibraries(Set<String> uriStrSet) {
- for (var uriStr in uriStrSet) {
- _exportsOfLibrary.remove(uriStr);
- libraryReaders.remove(uriStr);
- rootReference.removeChild(uriStr);
- }
-
- analysisSession.classHierarchy.removeOfLibraries(uriStrSet);
- analysisSession.inheritanceManager.removeOfLibraries(uriStrSet);
- }
-
/// Set exports of the library with [uriStr], after building exports during
/// linking, or after reading a linked bundle.
void setExportsOfLibrary(String uriStr, List<Reference> exports) {
@@ -242,10 +239,4 @@
libraryElement.createLoadLibraryFunction();
}
-
- void _declareDartCoreDynamicNever() {
- var dartCoreRef = rootReference.getChild('dart:core');
- dartCoreRef.getChild('dynamic').element = DynamicElementImpl.instance;
- dartCoreRef.getChild('Never').element = NeverElementImpl.instance;
- }
}
diff --git a/pkg/analyzer/lib/src/summary2/reference.dart b/pkg/analyzer/lib/src/summary2/reference.dart
index a2cf17b..23c3836 100644
--- a/pkg/analyzer/lib/src/summary2/reference.dart
+++ b/pkg/analyzer/lib/src/summary2/reference.dart
@@ -2,7 +2,6 @@
// 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.
-import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/summary2/scope.dart';
@@ -32,14 +31,6 @@
/// The simple name of the reference in its [parent].
final String name;
- /// The node accessor, used to read nodes lazily.
- /// Or `null` if a named container.
- ReferenceNodeAccessor? nodeAccessor;
-
- /// The corresponding [AstNode], or `null` if a named container.
- /// TODO(scheglov) remove it
- AstNode? node;
-
/// The corresponding [Element], or `null` if a named container.
Element? element;
@@ -62,30 +53,14 @@
return const [];
}
- bool get isClass => parent != null && parent!.name == '@class';
-
- bool get isConstructor => parent != null && parent!.name == '@constructor';
-
- bool get isDynamic => name == 'dynamic' && parent?.name == 'dart:core';
-
- bool get isEnum => parent != null && parent!.name == '@enum';
-
- bool get isGetter => parent != null && parent!.name == '@getter';
-
bool get isLibrary => parent != null && parent!.isRoot;
- bool get isParameter => parent != null && parent!.name == '@parameter';
-
bool get isPrefix => parent != null && parent!.name == '@prefix';
bool get isRoot => parent == null;
bool get isSetter => parent != null && parent!.name == '@setter';
- bool get isTypeAlias => parent != null && parent!.name == '@typeAlias';
-
- bool get isUnit => parent != null && parent!.name == '@unit';
-
/// Return the child with the given name, or `null` if does not exist.
Reference? operator [](String name) {
return _children != null ? _children![name] : null;
@@ -97,21 +72,6 @@
return map[name] ??= Reference._(this, name);
}
- /// If the reference has element, and it is for the [node], return `true`.
- ///
- /// The element might be not `null`, but the node is different in case of
- /// duplicate declarations.
- bool hasElementFor(AstNode node) {
- if (element != null && this.node == node) {
- return true;
- } else {
- if (this.node == null) {
- this.node = node;
- }
- return false;
- }
- }
-
void removeChild(String name) {
_children!.remove(name);
}
@@ -119,13 +79,3 @@
@override
String toString() => parent == null ? 'root' : '$parent::$name';
}
-
-abstract class ReferenceNodeAccessor {
- /// Return the node that corresponds to this [Reference], read it if not yet.
- AstNode get node;
-
- /// Fill [Reference.nodeAccessor] for children.
- ///
- /// TODO(scheglov) only class reader has a meaningful implementation.
- void readIndex();
-}
diff --git a/pkg/analyzer/lib/src/summary2/reference_resolver.dart b/pkg/analyzer/lib/src/summary2/reference_resolver.dart
index ea3f216..1cba245 100644
--- a/pkg/analyzer/lib/src/summary2/reference_resolver.dart
+++ b/pkg/analyzer/lib/src/summary2/reference_resolver.dart
@@ -14,10 +14,8 @@
import 'package:analyzer/src/dart/element/type_system.dart';
import 'package:analyzer/src/summary2/function_type_builder.dart';
import 'package:analyzer/src/summary2/link.dart';
-import 'package:analyzer/src/summary2/linked_element_factory.dart';
import 'package:analyzer/src/summary2/linking_node_scope.dart';
import 'package:analyzer/src/summary2/named_type_builder.dart';
-import 'package:analyzer/src/summary2/reference.dart';
import 'package:analyzer/src/summary2/types_builder.dart';
/// Recursive visitor of [LinkedNode]s that resolves explicit type annotations
@@ -33,8 +31,6 @@
final Linker linker;
final TypeSystemImpl _typeSystem;
final NodesToBuildType nodesToBuildType;
- final LinkedElementFactory elementFactory;
- final Reference unitReference;
/// Indicates whether the library is opted into NNBD.
final bool isNNBD;
@@ -44,12 +40,14 @@
ReferenceResolver(
this.linker,
this.nodesToBuildType,
- this.elementFactory,
LibraryElementImpl libraryElement,
- this.unitReference,
- this.isNNBD,
) : _typeSystem = libraryElement.typeSystem,
- scope = libraryElement.scope;
+ scope = libraryElement.scope,
+ isNNBD = libraryElement.isNonNullableByDefault;
+
+ void enterScopeClassElement(ClassElementImpl element) {
+ scope = TypeParameterScope(scope, element.typeParameters);
+ }
@override
void visitBlockFunctionBody(BlockFunctionBody node) {}
@@ -59,9 +57,6 @@
var outerScope = scope;
var element = node.declaredElement as ClassElementImpl;
- element.accessors; // create elements
- element.constructors; // create elements
- element.methods; // create elements
scope = TypeParameterScope(scope, element.typeParameters);
@@ -108,7 +103,6 @@
var outerScope = scope;
var element = node.declaredElement as ConstructorElementImpl;
- element.parameters; // create elements
scope = TypeParameterScope(scope, element.typeParameters);
LinkingNodeContext(node, scope);
@@ -164,7 +158,6 @@
var outerScope = scope;
var element = node.declaredElement as FieldFormalParameterElementImpl;
- element.parameters; // create elements
scope = TypeParameterScope(scope, element.typeParameters);
@@ -186,7 +179,6 @@
var outerScope = scope;
var element = node.declaredElement as ExecutableElementImpl;
- element.parameters; // create elements
scope = TypeParameterScope(outerScope, element.typeParameters);
LinkingNodeContext(node, scope);
@@ -214,9 +206,6 @@
node.returnType?.accept(this);
node.typeParameters?.accept(this);
-
- var function = element.aliasedElement as GenericFunctionTypeElementImpl;
- function.parameters; // create elements
node.parameters.accept(this);
nodesToBuildType.addDeclaration(node);
@@ -229,7 +218,6 @@
var outerScope = scope;
var element = node.declaredElement as ParameterElementImpl;
- element.parameters; // create elements
scope = TypeParameterScope(scope, element.typeParameters);
@@ -293,7 +281,6 @@
var outerScope = scope;
var element = node.declaredElement as ExecutableElementImpl;
- element.parameters; // create elements
scope = TypeParameterScope(scope, element.typeParameters);
LinkingNodeContext(node, scope);
@@ -311,9 +298,6 @@
var outerScope = scope;
var element = node.declaredElement as MixinElementImpl;
- element.accessors; // create elements
- element.constructors; // create elements
- element.methods; // create elements
scope = TypeParameterScope(scope, element.typeParameters);
diff --git a/pkg/analyzer/lib/src/task/options.dart b/pkg/analyzer/lib/src/task/options.dart
index 28b4452..2efaaa1 100644
--- a/pkg/analyzer/lib/src/task/options.dart
+++ b/pkg/analyzer/lib/src/task/options.dart
@@ -151,6 +151,8 @@
/// Ways to say `include`.
static const List<String> includeSynonyms = ['include', 'true'];
+ static const String propagateLinterExceptions = 'propagate-linter-exceptions';
+
/// Ways to say `true` or `false`.
static const List<String> trueOrFalse = ['true', 'false'];
@@ -163,6 +165,7 @@
language,
optionalChecks,
plugins,
+ propagateLinterExceptions,
strong_mode,
];
@@ -805,6 +808,9 @@
if (feature == AnalyzerOptions.implicitDynamic) {
options.implicitDynamic = boolValue;
}
+ if (feature == AnalyzerOptions.propagateLinterExceptions) {
+ options.propagateLinterExceptions = boolValue;
+ }
}
}
diff --git a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
index 3aa1807..b20ece0 100644
--- a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
+++ b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
@@ -748,6 +748,12 @@
external T operator [](int index);
}
+
+class FfiNative<T> {
+ final String nativeName;
+ final bool isLeaf;
+ const FfiNative(this.nativeName, {this.isLeaf: false});
+}
''',
)
]);
diff --git a/pkg/analyzer/lib/src/workspace/simple.dart b/pkg/analyzer/lib/src/workspace/simple.dart
index 51d96d2..02413ce 100644
--- a/pkg/analyzer/lib/src/workspace/simple.dart
+++ b/pkg/analyzer/lib/src/workspace/simple.dart
@@ -3,7 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/src/context/builder.dart';
import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/source/package_map_resolver.dart';
@@ -12,9 +11,6 @@
/// An abstract class for simple workspaces which do not feature any build
/// artifacts or generated files.
-///
-/// The [packageMap] and [packageUrlResolver] are simple derivations from the
-/// [ContextBuilder] and [ResourceProvider] required for the class.
abstract class SimpleWorkspace extends Workspace {
/// The [ResourceProvider] by which paths are converted into [Resource]s.
final ResourceProvider provider;
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index d52b622..4afb0cc 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
name: analyzer
-version: 2.0.0
+version: 2.1.0-dev
description: This package provides a library that performs static analysis of Dart code.
homepage: https://github.com/dart-lang/sdk/tree/master/pkg/analyzer
diff --git a/pkg/analyzer/test/error/error_reporter_test.dart b/pkg/analyzer/test/error/error_reporter_test.dart
index dba624a..7b32e98 100644
--- a/pkg/analyzer/test/error/error_reporter_test.dart
+++ b/pkg/analyzer/test/error/error_reporter_test.dart
@@ -166,7 +166,7 @@
var fa = findNode.topLevelVariableDeclaration('fa');
var fb = findNode.topLevelVariableDeclaration('fb');
- var source = result.unit!.declaredElement!.source;
+ var source = result.unit.declaredElement!.source;
var reporter = ErrorReporter(
listener,
source,
@@ -201,7 +201,7 @@
var ba = findNode.topLevelVariableDeclaration('ba');
var bb = findNode.topLevelVariableDeclaration('bb');
- var source = result.unit!.declaredElement!.source;
+ var source = result.unit.declaredElement!.source;
var reporter = ErrorReporter(
listener,
source,
diff --git a/pkg/analyzer/test/generated/constant_test.dart b/pkg/analyzer/test/generated/constant_test.dart
index f4a4079..f97d66a 100644
--- a/pkg/analyzer/test/generated/constant_test.dart
+++ b/pkg/analyzer/test/generated/constant_test.dart
@@ -497,7 +497,7 @@
var expression = findNode.variableDeclaration('x =').initializer!;
- var file = getFile(result.path!);
+ var file = getFile(result.path);
var evaluator = ConstantEvaluator(
file.createSource(result.uri),
result.libraryElement as LibraryElementImpl,
diff --git a/pkg/analyzer/test/generated/function_reference_parser_test.dart b/pkg/analyzer/test/generated/function_reference_parser_test.dart
index 13d0d82..c7cc214 100644
--- a/pkg/analyzer/test/generated/function_reference_parser_test.dart
+++ b/pkg/analyzer/test/generated/function_reference_parser_test.dart
@@ -300,6 +300,59 @@
as MethodInvocation);
}
+ void test_functionReference_after_indexExpression() {
+ // Note: this is not legal Dart, but it's important that we do error
+ // recovery and don't crash the parser.
+ var functionReference =
+ parseExpression('x[0]<a, b>', featureSet: constructorTearoffs)
+ as FunctionReference;
+ expect(functionReference.function, TypeMatcher<IndexExpression>());
+ var typeArgs = functionReference.typeArguments!.arguments;
+ expect(typeArgs, hasLength(2));
+ expect(((typeArgs[0] as TypeName).name as SimpleIdentifier).name, 'a');
+ expect(((typeArgs[1] as TypeName).name as SimpleIdentifier).name, 'b');
+ }
+
+ void test_functionReference_after_indexExpression_bang() {
+ // Note: this is not legal Dart, but it's important that we do error
+ // recovery and don't crash the parser.
+ var functionReference =
+ parseExpression('x[0]!<a, b>', featureSet: constructorTearoffs)
+ as FunctionReference;
+ expect(functionReference.function, TypeMatcher<PostfixExpression>());
+ var typeArgs = functionReference.typeArguments!.arguments;
+ expect(typeArgs, hasLength(2));
+ expect(((typeArgs[0] as TypeName).name as SimpleIdentifier).name, 'a');
+ expect(((typeArgs[1] as TypeName).name as SimpleIdentifier).name, 'b');
+ }
+
+ void test_functionReference_after_indexExpression_functionCall() {
+ // Note: this is not legal Dart, but it's important that we do error
+ // recovery and don't crash the parser.
+ var functionReference =
+ parseExpression('x[0]()<a, b>', featureSet: constructorTearoffs)
+ as FunctionReference;
+ expect(functionReference.function,
+ TypeMatcher<FunctionExpressionInvocation>());
+ var typeArgs = functionReference.typeArguments!.arguments;
+ expect(typeArgs, hasLength(2));
+ expect(((typeArgs[0] as TypeName).name as SimpleIdentifier).name, 'a');
+ expect(((typeArgs[1] as TypeName).name as SimpleIdentifier).name, 'b');
+ }
+
+ void test_functionReference_after_indexExpression_nullAware() {
+ // Note: this is not legal Dart, but it's important that we do error
+ // recovery and don't crash the parser.
+ var functionReference =
+ parseExpression('x?[0]<a, b>', featureSet: constructorTearoffs)
+ as FunctionReference;
+ expect(functionReference.function, TypeMatcher<IndexExpression>());
+ var typeArgs = functionReference.typeArguments!.arguments;
+ expect(typeArgs, hasLength(2));
+ expect(((typeArgs[0] as TypeName).name as SimpleIdentifier).name, 'a');
+ expect(((typeArgs[1] as TypeName).name as SimpleIdentifier).name, 'b');
+ }
+
void test_methodTearoff() {
var functionReference =
parseExpression('f().m<a, b>', featureSet: constructorTearoffs)
@@ -314,6 +367,21 @@
expect(((typeArgs[1] as TypeName).name as SimpleIdentifier).name, 'b');
}
+ void test_methodTearoff_cascaded() {
+ var cascadeExpression =
+ parseExpression('f()..m<a, b>', featureSet: constructorTearoffs)
+ as CascadeExpression;
+ var functionReference =
+ cascadeExpression.cascadeSections[0] as FunctionReference;
+ var function = functionReference.function as PropertyAccess;
+ expect(function.target, isNull);
+ expect(function.propertyName.name, 'm');
+ var typeArgs = functionReference.typeArguments!.arguments;
+ expect(typeArgs, hasLength(2));
+ expect(((typeArgs[0] as TypeName).name as SimpleIdentifier).name, 'a');
+ expect(((typeArgs[1] as TypeName).name as SimpleIdentifier).name, 'b');
+ }
+
void test_prefixedIdentifier() {
var functionReference =
parseExpression('prefix.f<a, b>', featureSet: constructorTearoffs)
diff --git a/pkg/analyzer/test/generated/non_error_resolver_test.dart b/pkg/analyzer/test/generated/non_error_resolver_test.dart
index 33fc9a1..91e4e01 100644
--- a/pkg/analyzer/test/generated/non_error_resolver_test.dart
+++ b/pkg/analyzer/test/generated/non_error_resolver_test.dart
@@ -761,7 +761,7 @@
class D {}
class E {}
''');
- CompilationUnit unit = result.unit!;
+ CompilationUnit unit = result.unit;
ClassElement classC = unit.declaredElement!.getType('C')!;
expect(classC.documentationComment, isNotNull);
}
@@ -1610,7 +1610,7 @@
class C extends A<B> with M {}
''');
- CompilationUnit unit = result.unit!;
+ CompilationUnit unit = result.unit;
ClassElement classC = unit.declaredElement!.getType('C')!;
expect(classC.mixins, hasLength(1));
assertType(classC.mixins[0], 'M<B>');
@@ -1632,7 +1632,7 @@
1,
),
]);
- CompilationUnit unit = result.unit!;
+ CompilationUnit unit = result.unit;
ClassElement classC = unit.declaredElement!.getType('C')!;
expect(classC.mixins, hasLength(1));
assertType(classC.mixins[0], 'M<int, String>');
@@ -1648,7 +1648,7 @@
class C extends A<List<B>> with M {}
''');
- CompilationUnit unit = result.unit!;
+ CompilationUnit unit = result.unit;
ClassElement classC = unit.declaredElement!.getType('C')!;
expect(classC.mixins, hasLength(1));
assertType(classC.mixins[0], 'M<B>');
@@ -2095,7 +2095,7 @@
error(HintCode.UNUSED_LOCAL_VARIABLE, 93, 1),
error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 97, 1),
]);
- var z = result.unit!.declaredElement!.topLevelVariables
+ var z = result.unit.declaredElement!.topLevelVariables
.where((e) => e.name == 'z')
.single;
assertType(z.type, 'List<String>');
@@ -2275,7 +2275,7 @@
class B<T> = Object with A<T>;
class C = Object with B;
''');
- var bReference = result.unit!.declaredElement!.getType('C')!.mixins[0];
+ var bReference = result.unit.declaredElement!.getType('C')!.mixins[0];
assertTypeDynamic(bReference.typeArguments[0]);
}
@@ -2294,7 +2294,7 @@
''', [
error(CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT_OBJECT, 122, 1),
]);
- var bReference = result.unit!.declaredElement!.getType('C')!.mixins[0];
+ var bReference = result.unit.declaredElement!.getType('C')!.mixins[0];
assertType(bReference.typeArguments[0], 'int');
}
@@ -2333,7 +2333,7 @@
x;
}
''');
- var main = result.unit!.declarations.last as FunctionDeclaration;
+ var main = result.unit.declarations.last as FunctionDeclaration;
var mainBody = main.functionExpression.body as BlockFunctionBody;
var xDecl = mainBody.block.statements[0] as VariableDeclarationStatement;
var xElem = xDecl.variables.variables[0].declaredElement!;
@@ -2804,8 +2804,8 @@
@B.named8()
main() {}
''');
- expect(result.unit!.declarations, hasLength(1));
- final mainDecl = result.unit!.declarations[0];
+ expect(result.unit.declarations, hasLength(1));
+ final mainDecl = result.unit.declarations[0];
expect(mainDecl.metadata, hasLength(8));
mainDecl.metadata.forEach((metadata) {
final value = metadata.elementAnnotation!.computeConstantValue()!;
diff --git a/pkg/analyzer/test/generated/simple_resolver_test.dart b/pkg/analyzer/test/generated/simple_resolver_test.dart
index b0a30a2..254dea0 100644
--- a/pkg/analyzer/test/generated/simple_resolver_test.dart
+++ b/pkg/analyzer/test/generated/simple_resolver_test.dart
@@ -1264,7 +1264,7 @@
/// Verify that all of the identifiers in the [result] have been resolved.
void verifyTestResolved() {
var verifier = ResolutionVerifier();
- result.unit!.accept(verifier);
+ result.unit.accept(verifier);
verifier.assertResolved();
}
diff --git a/pkg/analyzer/test/generated/strong_mode_test.dart b/pkg/analyzer/test/generated/strong_mode_test.dart
index aa67fe2..e724509 100644
--- a/pkg/analyzer/test/generated/strong_mode_test.dart
+++ b/pkg/analyzer/test/generated/strong_mode_test.dart
@@ -59,7 +59,7 @@
late final AsserterBuilder<Element, DartType> _hasElement;
- CompilationUnit get unit => result.unit!;
+ CompilationUnit get unit => result.unit;
@override
Future<void> resolveTestFile() async {
@@ -2404,7 +2404,7 @@
}
''');
- var b = result.unit!.declarations[1] as ClassDeclaration;
+ var b = result.unit.declarations[1] as ClassDeclaration;
var bConstructor = b.members[0] as ConstructorDeclaration;
var redirected = bConstructor.redirectedConstructor as ConstructorName;
diff --git a/pkg/analyzer/test/generated/utilities_test.dart b/pkg/analyzer/test/generated/utilities_test.dart
index 589c79a..b6d2157 100644
--- a/pkg/analyzer/test/generated/utilities_test.dart
+++ b/pkg/analyzer/test/generated/utilities_test.dart
@@ -5,13 +5,11 @@
import 'package:analyzer/dart/analysis/utilities.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
-import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/src/dart/ast/ast_factory.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/generated/java_engine.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/testing/ast_test_factory.dart';
-import 'package:analyzer/src/generated/testing/token_factory.dart';
import 'package:analyzer/src/generated/utilities_collection.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -19,7 +17,6 @@
main() {
defineReflectiveSuite(() {
defineReflectiveTests(BooleanArrayTest);
- defineReflectiveTests(ExceptionHandlingDelegatingAstVisitorTest);
defineReflectiveTests(LineInfoTest);
defineReflectiveTests(NodeReplacerTest);
defineReflectiveTests(SourceRangeTest);
@@ -116,23 +113,6 @@
}
}
-@reflectiveTest
-class ExceptionHandlingDelegatingAstVisitorTest {
- void test_handlerIsCalled() {
- AstVisitor exceptionThrowingVisitor = _ExceptionThrowingVisitor();
- bool handlerInvoked = false;
- AstVisitor visitor = ExceptionHandlingDelegatingAstVisitor(
- [exceptionThrowingVisitor], (AstNode node, AstVisitor visitor,
- dynamic exception, StackTrace stackTrace) {
- handlerInvoked = true;
- });
- astFactory
- .nullLiteral(TokenFactory.tokenFromKeyword(Keyword.NULL))
- .accept(visitor);
- expect(handlerInvoked, isTrue);
- }
-}
-
class Getter_NodeReplacerTest_test_annotation
implements NodeReplacerTest_Getter<Annotation, ArgumentList> {
@override
@@ -2740,10 +2720,3 @@
expect(StringUtilities.substringBeforeChar("abc", 0x64), "abc");
}
}
-
-class _ExceptionThrowingVisitor extends SimpleAstVisitor {
- @override
- visitNullLiteral(NullLiteral node) {
- throw ArgumentError('');
- }
-}
diff --git a/pkg/analyzer/test/src/context/builder_test.dart b/pkg/analyzer/test/src/context/builder_test.dart
index e439283..66c9590 100644
--- a/pkg/analyzer/test/src/context/builder_test.dart
+++ b/pkg/analyzer/test/src/context/builder_test.dart
@@ -4,22 +4,6 @@
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/context/builder.dart';
-import 'package:analyzer/src/context/context_root.dart';
-import 'package:analyzer/src/context/packages.dart';
-import 'package:analyzer/src/context/source.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/sdk.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/source/package_map_resolver.dart';
-import 'package:analyzer/src/test_utilities/mock_sdk.dart';
-import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
-import 'package:analyzer/src/workspace/basic.dart';
-import 'package:analyzer/src/workspace/bazel.dart';
-import 'package:analyzer/src/workspace/gn.dart';
-import 'package:analyzer/src/workspace/package_build.dart';
-import 'package:analyzer/src/workspace/pub.dart';
-import 'package:analyzer/src/workspace/workspace.dart';
-import 'package:path/path.dart' as path;
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -27,461 +11,11 @@
main() {
defineReflectiveSuite(() {
- defineReflectiveTests(ContextBuilderTest);
defineReflectiveTests(EmbedderYamlLocatorTest);
});
}
@reflectiveTest
-class ContextBuilderTest with ResourceProviderMixin {
- /// The SDK manager used by the tests;
- late final DartSdkManager sdkManager;
-
- /// The options passed to the context builder.
- ContextBuilderOptions builderOptions = ContextBuilderOptions();
-
- /// The context builder to be used in the test.
- late ContextBuilder builder;
-
- /// The path to the default SDK, or `null` if the test has not explicitly
- /// invoked [createDefaultSdk].
- late final String defaultSdkPath;
-
- Uri convertedDirectoryUri(String directoryPath) {
- return Uri.directory(convertPath(directoryPath),
- windows: resourceProvider.pathContext.style == path.windows.style);
- }
-
- void createDefaultSdk() {
- defaultSdkPath = convertPath(sdkRoot);
- MockSdk(resourceProvider: resourceProvider);
- }
-
- void setUp() {
- MockSdk(resourceProvider: resourceProvider);
- sdkManager = DartSdkManager(convertPath('/sdk'));
- builder = ContextBuilder(
- resourceProvider,
- sdkManager,
- options: builderOptions,
- );
- }
-
- @failingTest
- void test_buildContext() {
- fail('Incomplete test');
- }
-
- @failingTest
- void test_cmdline_options_override_options_file() {
- fail('No clear choice of option to override.');
-// ArgParser argParser = new ArgParser();
-// defineAnalysisArguments(argParser);
-// ArgResults argResults = argParser.parse(['--$enableSuperMixinFlag']);
-// var builder = new ContextBuilder(resourceProvider, sdkManager, contentCache,
-// options: createContextBuilderOptions(argResults));
-//
-// AnalysisOptionsImpl expected = new AnalysisOptionsImpl();
-// expected.option = true;
-//
-// String path = resourceProvider.convertPath('/some/directory/path');
-// String filePath =
-// join(path, AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE);
-// resourceProvider.newFile(filePath, '''
-//analyzer:
-// language:
-// option: true
-//''');
-//
-// AnalysisOptions options = builder.getAnalysisOptions(path);
-// _expectEqualOptions(options, expected);
- }
-
- void test_createPackageMap_fromPackageFile_explicit() {
- // Use a package file that is outside the project directory's hierarchy.
- String rootPath = convertPath('/root');
- String projectPath = join(rootPath, 'project');
- String packageFilePath = join(rootPath, 'child', '.packages');
- newFolder(projectPath);
- newFile(packageFilePath, content: '''
-foo:${toUriStr('/pkg/foo')}
-bar:${toUriStr('/pkg/bar')}
-''');
-
- builderOptions.defaultPackageFilePath = packageFilePath;
- Packages packages = _createPackageMap(projectPath);
- _assertPackages(
- packages,
- {
- 'foo': convertPath('/pkg/foo'),
- 'bar': convertPath('/pkg/bar'),
- },
- );
- }
-
- void test_createPackageMap_fromPackageFile_inParentOfRoot() {
- // Use a package file that is inside the parent of the project directory.
- String rootPath = convertPath('/root');
- String projectPath = join(rootPath, 'project');
- String packageFilePath = join(rootPath, '.packages');
- newFolder(projectPath);
- newFile(packageFilePath, content: '''
-foo:${toUriStr('/pkg/foo')}
-bar:${toUriStr('/pkg/bar')}
-''');
-
- Packages packages = _createPackageMap(projectPath);
- _assertPackages(
- packages,
- {
- 'foo': convertPath('/pkg/foo'),
- 'bar': convertPath('/pkg/bar'),
- },
- );
- }
-
- void test_createPackageMap_fromPackageFile_inRoot() {
- // Use a package file that is inside the project directory.
- String rootPath = convertPath('/root');
- String projectPath = join(rootPath, 'project');
- String packageFilePath = join(projectPath, '.packages');
- newFolder(projectPath);
- newFile(packageFilePath, content: '''
-foo:${toUriStr('/pkg/foo')}
-bar:${toUriStr('/pkg/bar')}
-''');
-
- Packages packages = _createPackageMap(projectPath);
- _assertPackages(
- packages,
- {
- 'foo': convertPath('/pkg/foo'),
- 'bar': convertPath('/pkg/bar'),
- },
- );
- }
-
- void test_createPackageMap_none() {
- String rootPath = convertPath('/root');
- newFolder(rootPath);
- Packages packages = _createPackageMap(rootPath);
- expect(packages.packages, isEmpty);
- }
-
- void test_createPackageMap_rootDoesNotExist() {
- String rootPath = convertPath('/root');
- Packages packages = _createPackageMap(rootPath);
- expect(packages.packages, isEmpty);
- }
-
- void test_createSourceFactory_bazelWorkspace_fileProvider() {
- String projectPath = convertPath('/workspace/my/module');
- newFile('/workspace/WORKSPACE');
- newFolder('/workspace/bazel-bin');
- newFolder('/workspace/bazel-genfiles');
- newFolder(projectPath);
-
- var factory = _createSourceFactory(projectPath);
- expect(factory.resolvers,
- contains(predicate((r) => r is BazelFileUriResolver)));
- expect(factory.resolvers,
- contains(predicate((r) => r is BazelPackageUriResolver)));
- }
-
- void test_createSourceFactory_bazelWorkspace_withPackagesFile() {
- String projectPath = convertPath('/workspace/my/module');
- newFile('/workspace/WORKSPACE');
- newFolder('/workspace/bazel-bin');
- newFolder('/workspace/bazel-genfiles');
- newFolder(projectPath);
- newFile(join(projectPath, '.packages'));
-
- var factory = _createSourceFactory(projectPath);
- expect(factory.resolvers,
- contains(predicate((r) => r is ResourceUriResolver)));
- expect(factory.resolvers,
- contains(predicate((r) => r is PackageMapUriResolver)));
- }
-
- void test_createSourceFactory_noProvider_packages_embedder_noExtensions() {
- String rootPath = convertPath('/root');
- createDefaultSdk();
- String projectPath = join(rootPath, 'project');
- String packageFilePath = join(projectPath, '.packages');
-
- String skyEnginePath = join(rootPath, 'pkgs', 'sky_engine');
- String embedderPath = join(skyEnginePath, '_embedder.yaml');
- String asyncPath = join(skyEnginePath, 'sdk', 'async.dart');
- String corePath = join(skyEnginePath, 'sdk', 'core.dart');
- newFile(embedderPath, content: '''
-embedded_libs:
- "dart:async": ${_relativeUri(asyncPath, from: skyEnginePath)}
- "dart:core": ${_relativeUri(corePath, from: skyEnginePath)}
-''');
-
- String packageB = join(rootPath, 'pkgs', 'b');
- newFile(packageFilePath, content: '''
-sky_engine:${resourceProvider.pathContext.toUri(skyEnginePath)}
-b:${resourceProvider.pathContext.toUri(packageB)}
-''');
-
- SourceFactory factory = _createSourceFactory(projectPath);
-
- var dartSource = factory.forUri('dart:async')!;
- expect(dartSource, isNotNull);
- expect(dartSource.fullName, asyncPath);
-
- var packageSource = factory.forUri('package:b/b.dart')!;
- expect(packageSource, isNotNull);
- expect(packageSource.fullName, join(packageB, 'b.dart'));
- }
-
- @failingTest
- void test_createSourceFactory_noProvider_packages_noEmbedder_extensions() {
- fail('Incomplete test');
- }
-
- void test_createSourceFactory_noProvider_packages_noEmbedder_noExtensions() {
- String rootPath = convertPath('/root');
- createDefaultSdk();
- String projectPath = join(rootPath, 'project');
- String packageFilePath = join(projectPath, '.packages');
- String packageA = join(rootPath, 'pkgs', 'a');
- String packageB = join(rootPath, 'pkgs', 'b');
- newFile(packageFilePath, content: '''
-a:${resourceProvider.pathContext.toUri(packageA)}
-b:${resourceProvider.pathContext.toUri(packageB)}
-''');
-
- SourceFactory factory = _createSourceFactory(projectPath);
-
- var dartSource = factory.forUri('dart:core')!;
- expect(dartSource, isNotNull);
- expect(
- dartSource.fullName, join(defaultSdkPath, 'lib', 'core', 'core.dart'));
-
- var packageSource = factory.forUri('package:a/a.dart')!;
- expect(packageSource, isNotNull);
- expect(packageSource.fullName, join(packageA, 'a.dart'));
- }
-
- void test_createWorkspace_hasPackagesFile_hasDartToolAndPubspec() {
- newDotPackagesFile('/workspace');
- newFolder('/workspace/.dart_tool/build/generated/project/lib');
- newPubspecYamlFile('/workspace', 'name: project');
- Workspace workspace = _createWorkspace('/workspace/project/lib/lib.dart');
- expect(workspace, TypeMatcher<PackageBuildWorkspace>());
- }
-
- void test_createWorkspace_hasPackagesFile_hasPubspec() {
- newDotPackagesFile('/workspace');
- newPubspecYamlFile('/workspace', 'name: project');
- Workspace workspace = _createWorkspace('/workspace/project/lib/lib.dart');
- expect(workspace, TypeMatcher<PubWorkspace>());
- }
-
- void test_createWorkspace_hasPackagesFile_noMarkerFiles() {
- newDotPackagesFile('/workspace');
- Workspace workspace = _createWorkspace('/workspace/project/lib/lib.dart');
- expect(workspace, TypeMatcher<BasicWorkspace>());
- }
-
- void test_createWorkspace_noPackagesFile_hasBazelMarkerFiles() {
- newFile('/workspace/WORKSPACE');
- newFolder('/workspace/bazel-genfiles');
- Workspace workspace = _createWorkspace('/workspace/project/lib/lib.dart');
- expect(workspace, TypeMatcher<BazelWorkspace>());
- }
-
- void test_createWorkspace_noPackagesFile_hasDartToolAndPubspec() {
- newFolder('/workspace/.dart_tool/build/generated/project/lib');
- newPubspecYamlFile('/workspace', 'name: project');
- Workspace workspace = _createWorkspace('/workspace/project/lib/lib.dart');
- expect(workspace, TypeMatcher<PackageBuildWorkspace>());
- }
-
- void test_createWorkspace_noPackagesFile_hasGnMarkerFiles() {
- newFolder('/workspace/.jiri_root');
- newFile(
- '/workspace/out/debug-x87_128/dartlang/gen/project/lib/lib_package_config.json',
- content: '''{
- "configVersion": 2,
- "packages": []
-}''');
- Workspace workspace = _createWorkspace('/workspace/project/lib/lib.dart');
- expect(workspace, TypeMatcher<GnWorkspace>());
- }
-
- void test_createWorkspace_noPackagesFile_hasPubspec() {
- newPubspecYamlFile('/workspace', 'name: project');
- Workspace workspace = _createWorkspace('/workspace/project/lib/lib.dart');
- expect(workspace, TypeMatcher<PubWorkspace>());
- }
-
- void test_createWorkspace_noPackagesFile_noMarkerFiles() {
- Workspace workspace = _createWorkspace('/workspace/project/lib/lib.dart');
- expect(workspace, TypeMatcher<BasicWorkspace>());
- }
-
- @failingTest
- void test_findSdk_embedder_extensions() {
- // See test_createSourceFactory_noProvider_packages_embedder_extensions
- fail('Incomplete test');
- }
-
- @failingTest
- void test_findSdk_embedder_noExtensions() {
- // See test_createSourceFactory_noProvider_packages_embedder_noExtensions
- fail('Incomplete test');
- }
-
- @failingTest
- void test_findSdk_noEmbedder_extensions() {
- // See test_createSourceFactory_noProvider_packages_noEmbedder_extensions
- fail('Incomplete test');
- }
-
- @failingTest
- void test_findSdk_noEmbedder_noExtensions() {
- // See test_createSourceFactory_noProvider_packages_noEmbedder_noExtensions
- fail('Incomplete test');
- }
-
- void test_findSdk_noPackageMap() {
- DartSdk sdk = builder.findSdk(null);
- expect(sdk, isNotNull);
- }
-
- void test_findSdk_noPackageMap_html_strong() {
- DartSdk sdk = builder.findSdk(null);
- expect(sdk, isNotNull);
- Source htmlSource = sdk.mapDartUri('dart:html')!;
- expect(htmlSource.fullName,
- convertPath('/sdk/lib/html/dart2js/html_dart2js.dart'));
- expect(htmlSource.exists(), isTrue);
- }
-
- void test_getAnalysisOptions_gnWorkspace() {
- String projectPath = convertPath('/workspace/some/path');
- newFolder('/workspace/.jiri_root');
- newFile('/workspace/out/debug/gen/dart.sources/foo_pkg',
- content: convertPath('/workspace/foo_pkg/lib'));
- newFolder(projectPath);
- builder =
- ContextBuilder(resourceProvider, sdkManager, options: builderOptions);
- AnalysisOptionsImpl expected = AnalysisOptionsImpl();
- var options = _getAnalysisOptions(builder, projectPath);
- _expectEqualOptions(options, expected);
- }
-
- void test_getAnalysisOptions_invalid() {
- String path = convertPath('/some/directory/path');
- newAnalysisOptionsYamlFile(path, content: ';');
-
- AnalysisOptions options = _getAnalysisOptions(builder, path);
- expect(options, isNotNull);
- }
-
- void test_getAnalysisOptions_noDefault_noOverrides() {
- String path = convertPath('/some/directory/path');
- newAnalysisOptionsYamlFile(path, content: '''
-linter:
- rules:
- - non_existent_lint_rule
-''');
-
- var options = _getAnalysisOptions(builder, path);
- _expectEqualOptions(options, AnalysisOptionsImpl());
- }
-
- void test_getAnalysisOptions_sdkVersionConstraint() {
- var projectPath = convertPath('/test');
- newPubspecYamlFile(projectPath, '''
-environment:
- sdk: ^2.1.0
-''');
-
- var options = _getAnalysisOptions(builder, projectPath);
- expect(options.sdkVersionConstraint.toString(), '^2.1.0');
- }
-
- void test_getAnalysisOptions_sdkVersionConstraint_any_noOptionsFile() {
- var projectPath = convertPath('/test');
- var options = _getAnalysisOptions(builder, projectPath);
- expect(options.sdkVersionConstraint, isNull);
- }
-
- void _assertPackages(Packages packages, Map<String, String> nameToPath) {
- expect(packages, isNotNull);
- expect(packages.packages, hasLength(nameToPath.length));
- for (var name in nameToPath.keys) {
- var expectedPath = nameToPath[name];
- var path = packages[name]!.libFolder.path;
- expect(path, expectedPath, reason: 'package $name');
- }
- }
-
- Packages _createPackageMap(String rootPath) {
- return ContextBuilder.createPackageMap(
- resourceProvider: resourceProvider,
- options: builderOptions,
- rootPath: rootPath,
- );
- }
-
- SourceFactoryImpl _createSourceFactory(String projectPath) {
- Workspace workspace = ContextBuilder.createWorkspace(
- resourceProvider: resourceProvider,
- options: builderOptions,
- rootPath: projectPath,
- );
- return builder.createSourceFactory(projectPath, workspace)
- as SourceFactoryImpl;
- }
-
- Workspace _createWorkspace(String posixPath) {
- return ContextBuilder.createWorkspace(
- resourceProvider: resourceProvider,
- options: ContextBuilderOptions(),
- rootPath: convertPath(posixPath),
- );
- }
-
- void _expectEqualOptions(
- AnalysisOptionsImpl actual, AnalysisOptionsImpl expected) {
- // TODO(brianwilkerson) Consider moving this to AnalysisOptionsImpl.==.
- expect(actual.enableTiming, expected.enableTiming);
- expect(actual.hint, expected.hint);
- expect(actual.lint, expected.lint);
- expect(
- actual.lintRules.map((l) => l.name),
- unorderedEquals(expected.lintRules.map((l) => l.name)),
- );
- expect(actual.implicitCasts, expected.implicitCasts);
- expect(actual.implicitDynamic, expected.implicitDynamic);
- expect(actual.strictInference, expected.strictInference);
- expect(actual.strictRawTypes, expected.strictRawTypes);
- }
-
- AnalysisOptionsImpl _getAnalysisOptions(ContextBuilder builder, String path,
- {ContextRoot? contextRoot}) {
- Workspace workspace = ContextBuilder.createWorkspace(
- resourceProvider: resourceProvider,
- options: builder.builderOptions,
- rootPath: path,
- );
- return builder.getAnalysisOptions(path, workspace,
- contextRoot: contextRoot);
- }
-
- Uri _relativeUri(String path, {String? from}) {
- var pathContext = resourceProvider.pathContext;
- String relativePath = pathContext.relative(path, from: from);
- return pathContext.toUri(relativePath);
- }
-}
-
-@reflectiveTest
class EmbedderYamlLocatorTest extends EmbedderRelatedTest {
void test_empty() {
EmbedderYamlLocator locator = EmbedderYamlLocator({
diff --git a/pkg/analyzer/test/src/dart/analysis/base.dart b/pkg/analyzer/test/src/dart/analysis/base.dart
index 542e7f8..1bb79b1 100644
--- a/pkg/analyzer/test/src/dart/analysis/base.dart
+++ b/pkg/analyzer/test/src/dart/analysis/base.dart
@@ -33,7 +33,7 @@
late final AnalysisDriverScheduler scheduler;
late final AnalysisDriver driver;
final List<AnalysisStatus> allStatuses = <AnalysisStatus>[];
- final List<ResolvedUnitResult> allResults = <ResolvedUnitResult>[];
+ final List<AnalysisResultWithErrors> allResults = [];
final List<ExceptionResult> allExceptions = <ExceptionResult>[];
late final String testProject;
@@ -141,7 +141,11 @@
driver = createAnalysisDriver();
scheduler.start();
scheduler.status.listen(allStatuses.add);
- driver.results.listen(allResults.add);
+ driver.results.listen((result) {
+ if (result is AnalysisResultWithErrors) {
+ allResults.add(result);
+ }
+ });
driver.exceptions.listen(allExceptions.add);
}
diff --git a/pkg/analyzer/test/src/dart/analysis/context_builder_test.dart b/pkg/analyzer/test/src/dart/analysis/context_builder_test.dart
index af27464..44a7634 100644
--- a/pkg/analyzer/test/src/dart/analysis/context_builder_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/context_builder_test.dart
@@ -5,14 +5,25 @@
import 'package:analyzer/dart/analysis/analysis_context.dart';
import 'package:analyzer/dart/analysis/context_root.dart';
import 'package:analyzer/dart/analysis/declared_variables.dart';
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/src/context/source.dart';
import 'package:analyzer/src/dart/analysis/context_builder.dart';
+import 'package:analyzer/src/dart/analysis/context_locator.dart';
import 'package:analyzer/src/dart/analysis/context_root.dart';
+import 'package:analyzer/src/dart/analysis/driver_based_analysis_context.dart';
+import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/source/package_map_resolver.dart';
import 'package:analyzer/src/test_utilities/mock_sdk.dart';
import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
import 'package:analyzer/src/workspace/basic.dart';
+import 'package:analyzer/src/workspace/bazel.dart';
+import 'package:analyzer/src/workspace/pub.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
+import '../resolution/context_collection_resolution.dart';
+
main() {
defineReflectiveSuite(() {
defineReflectiveTests(ContextBuilderImplTest);
@@ -40,6 +51,61 @@
contextRoot = ContextRootImpl(resourceProvider, folder, workspace);
}
+ void test_analysisOptions_invalid() {
+ MockSdk(resourceProvider: resourceProvider);
+
+ var projectPath = convertPath('/home/test');
+ newAnalysisOptionsYamlFile(projectPath, content: ';');
+
+ var analysisContext = _createSingleAnalysisContext(projectPath);
+ var analysisOptions = analysisContext.analysisOptionsImpl;
+ _expectEqualOptions(analysisOptions, AnalysisOptionsImpl());
+ }
+
+ void test_analysisOptions_languageOptions() {
+ MockSdk(resourceProvider: resourceProvider);
+
+ var projectPath = convertPath('/home/test');
+ newAnalysisOptionsYamlFile(
+ projectPath,
+ content: AnalysisOptionsFileConfig(
+ strictRawTypes: true,
+ ).toContent(),
+ );
+
+ var analysisContext = _createSingleAnalysisContext(projectPath);
+ var analysisOptions = analysisContext.analysisOptionsImpl;
+ _expectEqualOptions(
+ analysisOptions,
+ AnalysisOptionsImpl()..strictRawTypes = true,
+ );
+ }
+
+ void test_analysisOptions_sdkVersionConstraint_hasPubspec_hasSdk() {
+ MockSdk(resourceProvider: resourceProvider);
+
+ var projectPath = convertPath('/home/test');
+ newPubspecYamlFile(projectPath, '''
+environment:
+ sdk: ^2.1.0
+''');
+
+ var analysisContext = _createSingleAnalysisContext(projectPath);
+ var analysisOptions = analysisContext.analysisOptionsImpl;
+ expect(analysisOptions.sdkVersionConstraint.toString(), '^2.1.0');
+ }
+
+ void test_analysisOptions_sdkVersionConstraint_noPubspec() {
+ MockSdk(resourceProvider: resourceProvider);
+
+ var projectPath = convertPath('/home/test');
+ newFile('$projectPath/lib/a.dart');
+
+ var analysisContext = _createSingleAnalysisContext(projectPath);
+ var analysisOptions = analysisContext.driver.analysisOptions;
+ expect(analysisOptions.sdkVersionConstraint, isNull);
+ }
+
test_createContext_declaredVariables() {
MockSdk(resourceProvider: resourceProvider);
DeclaredVariables declaredVariables =
@@ -101,4 +167,88 @@
expect(context.contextRoot, contextRoot);
expect(context.sdkRoot?.path, resourceProvider.convertPath(sdkRoot));
}
+
+ void test_sourceFactory_bazelWorkspace() {
+ MockSdk(resourceProvider: resourceProvider);
+
+ var projectPath = convertPath('/workspace/my/module');
+ newFile('/workspace/WORKSPACE');
+ newFolder('/workspace/bazel-bin');
+ newFolder('/workspace/bazel-genfiles');
+
+ var analysisContext = _createSingleAnalysisContext(projectPath);
+ expect(analysisContext.contextRoot.workspace, isA<BazelWorkspace>());
+
+ expect(
+ analysisContext.uriResolvers,
+ unorderedEquals([
+ isA<DartUriResolver>(),
+ isA<BazelPackageUriResolver>(),
+ isA<BazelFileUriResolver>(),
+ ]),
+ );
+ }
+
+ void test_sourceFactory_pubWorkspace() {
+ MockSdk(resourceProvider: resourceProvider);
+
+ var projectPath = convertPath('/home/my');
+ newFile('/home/my/pubspec.yaml');
+
+ var analysisContext = _createSingleAnalysisContext(projectPath);
+ expect(analysisContext.contextRoot.workspace, isA<PubWorkspace>());
+
+ expect(
+ analysisContext.uriResolvers,
+ unorderedEquals([
+ isA<DartUriResolver>(),
+ isA<PackageMapUriResolver>(),
+ isA<ResourceUriResolver>(),
+ ]),
+ );
+ }
+
+ /// Return a single expected analysis context at the [path].
+ DriverBasedAnalysisContext _createSingleAnalysisContext(String path) {
+ var roots = ContextLocatorImpl(
+ resourceProvider: resourceProvider,
+ ).locateRoots(includedPaths: [path]);
+
+ return ContextBuilderImpl(
+ resourceProvider: resourceProvider,
+ ).createContext(
+ contextRoot: roots.single,
+ sdkPath: convertPath(sdkRoot),
+ );
+ }
+
+ static void _expectEqualOptions(
+ AnalysisOptionsImpl actual,
+ AnalysisOptionsImpl expected,
+ ) {
+ // TODO(brianwilkerson) Consider moving this to AnalysisOptionsImpl.==.
+ expect(actual.enableTiming, expected.enableTiming);
+ expect(actual.hint, expected.hint);
+ expect(actual.lint, expected.lint);
+ expect(
+ actual.lintRules.map((l) => l.name),
+ unorderedEquals(expected.lintRules.map((l) => l.name)),
+ );
+ expect(actual.implicitCasts, expected.implicitCasts);
+ expect(actual.implicitDynamic, expected.implicitDynamic);
+ expect(
+ actual.propagateLinterExceptions, expected.propagateLinterExceptions);
+ expect(actual.strictInference, expected.strictInference);
+ expect(actual.strictRawTypes, expected.strictRawTypes);
+ }
+}
+
+extension on DriverBasedAnalysisContext {
+ AnalysisOptionsImpl get analysisOptionsImpl {
+ return driver.analysisOptions as AnalysisOptionsImpl;
+ }
+
+ List<UriResolver> get uriResolvers {
+ return (driver.sourceFactory as SourceFactoryImpl).resolvers;
+ }
}
diff --git a/pkg/analyzer/test/src/dart/analysis/dependency/base.dart b/pkg/analyzer/test/src/dart/analysis/dependency/base.dart
index 6570844..0c2aefa 100644
--- a/pkg/analyzer/test/src/dart/analysis/dependency/base.dart
+++ b/pkg/analyzer/test/src/dart/analysis/dependency/base.dart
@@ -138,9 +138,9 @@
Future<List<CompilationUnit>> _resolveLibrary(String libraryPath) async {
var session = contextFor(libraryPath).currentSession;
- var resolvedLibrary = await session.getResolvedLibrary2(libraryPath);
+ var resolvedLibrary = await session.getResolvedLibrary(libraryPath);
resolvedLibrary as ResolvedLibraryResult;
- return resolvedLibrary.units!.map((ru) => ru.unit!).toList();
+ return resolvedLibrary.units.map((ru) => ru.unit).toList();
}
}
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_caching_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_caching_test.dart
index 300536e..230b7cd 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_caching_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_caching_test.dart
@@ -276,7 +276,7 @@
var testFilePathConverted = convertPath(testFilePath);
var errorsResult = await contextFor(testFilePathConverted)
.currentSession
- .getErrors2(testFilePathConverted) as ErrorsResult;
+ .getErrors(testFilePathConverted) as ErrorsResult;
return errorsResult.errors;
}
}
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
index 5853f91..9fe7223 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
@@ -143,7 +143,7 @@
await resolveTestFile();
var myDeclaration =
- result.unit!.declarations[0] as TopLevelVariableDeclaration;
+ result.unit.declarations[0] as TopLevelVariableDeclaration;
var myVariable = myDeclaration.variables.variables[0];
var myElement = myVariable.declaredElement as TopLevelVariableElement;
@@ -157,7 +157,7 @@
}
{
- var classNode = result.unit!.declarations[1] as ClassDeclaration;
+ var classNode = result.unit.declarations[1] as ClassDeclaration;
assertMyAnnotation(classNode);
{
@@ -177,12 +177,12 @@
}
{
- var node = result.unit!.declarations[2] as TopLevelVariableDeclaration;
+ var node = result.unit.declarations[2] as TopLevelVariableDeclaration;
assertMyAnnotation(node);
}
{
- var node = result.unit!.declarations[3] as FunctionDeclaration;
+ var node = result.unit.declarations[3] as FunctionDeclaration;
assertMyAnnotation(node);
}
}
@@ -346,11 +346,11 @@
await resolveTestFile();
- var c = result.unit!.declarations[0] as ClassDeclaration;
+ var c = result.unit.declarations[0] as ClassDeclaration;
var constructor = c.members[1] as ConstructorDeclaration;
ConstructorElement element = constructor.declaredElement!;
- var main = result.unit!.declarations[1] as FunctionDeclaration;
+ var main = result.unit.declarations[1] as FunctionDeclaration;
var statement = (main.functionExpression.body as BlockFunctionBody)
.block
.statements[0] as VariableDeclarationStatement;
@@ -377,11 +377,11 @@
await resolveTestFile();
var myDeclaration =
- result.unit!.declarations[0] as TopLevelVariableDeclaration;
+ result.unit.declarations[0] as TopLevelVariableDeclaration;
VariableDeclaration myVariable = myDeclaration.variables.variables[0];
var myElement = myVariable.declaredElement as TopLevelVariableElement;
- var classNode = result.unit!.declarations[1] as ClassDeclaration;
+ var classNode = result.unit.declarations[1] as ClassDeclaration;
var node = classNode.members[0] as MethodDeclaration;
var statement = (node.body as BlockFunctionBody).block.statements[0]
as VariableDeclarationStatement;
@@ -406,7 +406,7 @@
main() {}
''');
await resolveTestFile();
- CompilationUnit unit = result.unit!;
+ CompilationUnit unit = result.unit;
ImportElement aImport = unit.declaredElement!.library.imports[0];
PrefixElement aPrefix = aImport.prefix!;
@@ -445,7 +445,7 @@
main() {}
''');
await resolveTestFile();
- CompilationUnit unit = result.unit!;
+ CompilationUnit unit = result.unit;
ImportElement aImport = unit.declaredElement!.library.imports[0];
PrefixElement aPrefix = aImport.prefix!;
@@ -486,7 +486,7 @@
main() {}
''');
await resolveTestFile();
- CompilationUnit unit = result.unit!;
+ CompilationUnit unit = result.unit;
ImportElement aImport = unit.declaredElement!.library.imports[0];
PrefixElement aPrefix = aImport.prefix!;
@@ -527,7 +527,7 @@
main() {}
''');
await resolveTestFile();
- CompilationUnit unit = result.unit!;
+ CompilationUnit unit = result.unit;
ImportElement aImport = unit.declaredElement!.library.imports[0];
PrefixElement aPrefix = aImport.prefix!;
@@ -560,7 +560,7 @@
}
''');
await resolveTestFile();
- CompilationUnit unit = result.unit!;
+ CompilationUnit unit = result.unit;
CompilationUnitElement unitElement = unit.declaredElement!;
ClassElement aClass = unitElement.getType('A')!;
@@ -590,7 +590,7 @@
}
''');
await resolveTestFile();
- CompilationUnit unit = result.unit!;
+ CompilationUnit unit = result.unit;
CompilationUnitElement unitElement = unit.declaredElement!;
ClassElement aClass = unitElement.getType('A')!;
@@ -620,7 +620,7 @@
}
''');
await resolveTestFile();
- CompilationUnit unit = result.unit!;
+ CompilationUnit unit = result.unit;
CompilationUnitElement unitElement = unit.declaredElement!;
ClassElement aClass = unitElement.getType('A')!;
@@ -657,11 +657,11 @@
f() {}
''');
await resolveTestFile();
- var elementC = AstFinder.getClass(result.unit!, 'C').declaredElement!;
+ var elementC = AstFinder.getClass(result.unit, 'C').declaredElement!;
var constructorC = elementC.constructors[0];
- var elementD = AstFinder.getClass(result.unit!, 'D').declaredElement!;
+ var elementD = AstFinder.getClass(result.unit, 'D').declaredElement!;
var constructorD = elementD.constructors[0];
- var atD = AstFinder.getTopLevelFunction(result.unit!, 'f').metadata[0];
+ var atD = AstFinder.getTopLevelFunction(result.unit, 'f').metadata[0];
var constC = atD.arguments!.arguments[0] as InstanceCreationExpression;
expect(atD.name.staticElement, elementD);
@@ -689,16 +689,16 @@
await resolveTestFile();
var declaration_1 =
- result.unit!.declarations[0] as TopLevelVariableDeclaration;
+ result.unit.declarations[0] as TopLevelVariableDeclaration;
VariableDeclaration variable_1 = declaration_1.variables.variables[0];
var element_1 = variable_1.declaredElement as TopLevelVariableElement;
var declaration_2 =
- result.unit!.declarations[1] as TopLevelVariableDeclaration;
+ result.unit.declarations[1] as TopLevelVariableDeclaration;
VariableDeclaration variable_2 = declaration_2.variables.variables[0];
var element_2 = variable_2.declaredElement as TopLevelVariableElement;
- var main = result.unit!.declarations[2] as FunctionDeclaration;
+ var main = result.unit.declarations[2] as FunctionDeclaration;
Annotation annotation_1 = main.metadata[0];
expect(annotation_1.element, same(element_1.getter));
@@ -959,7 +959,7 @@
''');
await resolveTestFile();
- var mainDeclaration = result.unit!.declarations[0] as FunctionDeclaration;
+ var mainDeclaration = result.unit.declarations[0] as FunctionDeclaration;
var mainElement = mainDeclaration.declaredElement as FunctionElement;
var mainBody = mainDeclaration.functionExpression.body as BlockFunctionBody;
List<Statement> mainStatements = mainBody.block.statements;
@@ -1090,7 +1090,7 @@
}
''');
await resolveTestFile();
- CompilationUnit unit = result.unit!;
+ CompilationUnit unit = result.unit;
var c = unit.declarations[0] as ClassDeclaration;
var declaration = c.members[0] as FieldDeclaration;
@@ -1107,7 +1107,7 @@
var v = (() => 42)();
''');
await resolveTestFile();
- CompilationUnit unit = result.unit!;
+ CompilationUnit unit = result.unit;
var declaration = unit.declarations[0] as TopLevelVariableDeclaration;
VariableDeclaration variable = declaration.variables.variables[0];
@@ -1164,7 +1164,7 @@
''');
await resolveTestFile();
- var cNode = result.unit!.declarations[0] as ClassDeclaration;
+ var cNode = result.unit.declarations[0] as ClassDeclaration;
var constructorNode = cNode.members[0] as ConstructorDeclaration;
ParameterElement pElement = constructorNode.declaredElement!.parameters[0];
@@ -1188,7 +1188,7 @@
''');
await resolveTestFile();
- var cNode = result.unit!.declarations[0] as ClassDeclaration;
+ var cNode = result.unit.declarations[0] as ClassDeclaration;
ClassElement cElement = cNode.declaredElement!;
FieldElement fElement = cElement.getField('f')!;
@@ -1219,10 +1219,10 @@
''');
await resolveTestFile();
- var aNode = result.unit!.declarations[0] as ClassDeclaration;
+ var aNode = result.unit.declarations[0] as ClassDeclaration;
ClassElement aElement = aNode.declaredElement!;
- var bNode = result.unit!.declarations[1] as ClassDeclaration;
+ var bNode = result.unit.declarations[1] as ClassDeclaration;
{
var constructor = bNode.members[0] as ConstructorDeclaration;
@@ -1261,7 +1261,7 @@
''');
await resolveTestFile();
- var cNode = result.unit!.declarations[0] as ClassDeclaration;
+ var cNode = result.unit.declarations[0] as ClassDeclaration;
ClassElement cElement = cNode.declaredElement!;
{
@@ -1312,10 +1312,10 @@
await resolveTestFile();
expect(result.errors, isEmpty);
- var aNode = result.unit!.declarations[0] as ClassDeclaration;
+ var aNode = result.unit.declarations[0] as ClassDeclaration;
ClassElement aElement = aNode.declaredElement!;
- var bNode = result.unit!.declarations[1] as ClassDeclaration;
+ var bNode = result.unit.declarations[1] as ClassDeclaration;
{
ConstructorElement aUnnamed = aElement.constructors[0];
@@ -1373,10 +1373,10 @@
await resolveTestFile();
expect(result.errors, isEmpty);
- var aNode = result.unit!.declarations[0] as ClassDeclaration;
+ var aNode = result.unit.declarations[0] as ClassDeclaration;
ClassElement aElement = aNode.declaredElement!;
- var bNode = result.unit!.declarations[1] as ClassDeclaration;
+ var bNode = result.unit.declarations[1] as ClassDeclaration;
TypeParameterType uType =
typeParameterTypeNone(bNode.declaredElement!.typeParameters[0]);
InterfaceType auType = aElement.instantiate(
@@ -1714,7 +1714,7 @@
''');
await resolveTestFile();
- var enumNode = result.unit!.declarations[0] as EnumDeclaration;
+ var enumNode = result.unit.declarations[0] as EnumDeclaration;
ClassElement enumElement = enumNode.declaredElement!;
List<Statement> mainStatements = _getMainStatements(result);
@@ -1758,7 +1758,7 @@
''');
await resolveTestFile();
- var cNode = result.unit!.declarations[0] as ClassDeclaration;
+ var cNode = result.unit.declarations[0] as ClassDeclaration;
var tElement = cNode.declaredElement!.typeParameters[0];
var fDeclaration = cNode.members[0] as FieldDeclaration;
@@ -1806,7 +1806,7 @@
''');
await resolveTestFile();
- var clazz = result.unit!.declarations[0] as ClassDeclaration;
+ var clazz = result.unit.declarations[0] as ClassDeclaration;
var constructor = clazz.members[0] as ConstructorDeclaration;
List<FormalParameter> parameters = constructor.parameters.parameters;
@@ -1841,7 +1841,7 @@
''');
await resolveTestFile();
- var clazz = result.unit!.declarations[0] as ClassDeclaration;
+ var clazz = result.unit.declarations[0] as ClassDeclaration;
var fDeclaration = clazz.members[0] as FieldDeclaration;
VariableDeclaration fNode = fDeclaration.fields.variables[0];
@@ -1886,7 +1886,7 @@
''');
await resolveTestFile();
- var clazz = result.unit!.declarations[0] as ClassDeclaration;
+ var clazz = result.unit.declarations[0] as ClassDeclaration;
var fDeclaration = clazz.members[0] as FieldDeclaration;
VariableDeclaration fNode = fDeclaration.fields.variables[0];
@@ -1916,7 +1916,7 @@
''');
await resolveTestFile();
- var clazz = result.unit!.declarations[0] as ClassDeclaration;
+ var clazz = result.unit.declarations[0] as ClassDeclaration;
var fDeclaration = clazz.members[0] as FieldDeclaration;
VariableDeclaration fNode = fDeclaration.fields.variables[0];
@@ -2078,7 +2078,7 @@
addTestFile(content);
await resolveTestFile();
- CompilationUnit unit = result.unit!;
+ CompilationUnit unit = result.unit;
var cNode = unit.declarations[0] as ClassDeclaration;
ClassElement cElement = cNode.declaredElement!;
@@ -2131,7 +2131,7 @@
''');
await resolveTestFile();
- CompilationUnit unit = result.unit!;
+ CompilationUnit unit = result.unit;
var xNode = unit.declarations[0] as ClassDeclaration;
ClassElement xElement = xNode.declaredElement!;
@@ -2172,7 +2172,7 @@
addTestFile(content);
await resolveTestFile();
- CompilationUnit unit = result.unit!;
+ CompilationUnit unit = result.unit;
var cNode = unit.declarations[0] as ClassDeclaration;
ClassElement cElement = cNode.declaredElement!;
@@ -2239,7 +2239,7 @@
}
''');
await resolveTestFile();
- CompilationUnit unit = result.unit!;
+ CompilationUnit unit = result.unit;
ImportElement aImport = unit.declaredElement!.library.imports[0];
LibraryElement aLibrary = aImport.importedLibrary!;
@@ -2356,7 +2356,7 @@
}
''');
await resolveTestFile();
- CompilationUnit unit = result.unit!;
+ CompilationUnit unit = result.unit;
CompilationUnitElement unitElement = unit.declaredElement!;
ClassElement cElement = unitElement.getType('C')!;
@@ -4342,7 +4342,7 @@
}
''');
- var main = result.unit!.declarations[0] as FunctionDeclaration;
+ var main = result.unit.declarations[0] as FunctionDeclaration;
List<Statement> statements = _getMainStatements(result);
// (int p)
@@ -4735,7 +4735,7 @@
InterfaceType intType = typeProvider.intType;
- var main = result.unit!.declarations[0] as FunctionDeclaration;
+ var main = result.unit.declarations[0] as FunctionDeclaration;
expect(main.declaredElement, isNotNull);
expect(main.name.staticElement, isNotNull);
expect(main.name.staticType, isNull);
@@ -4778,7 +4778,7 @@
}
''');
await resolveTestFile();
- CompilationUnit unit = result.unit!;
+ CompilationUnit unit = result.unit;
var cDeclaration = unit.declarations[0] as ClassDeclaration;
@@ -4849,7 +4849,7 @@
num v;
''');
await resolveTestFile();
- CompilationUnit unit = result.unit!;
+ CompilationUnit unit = result.unit;
List<Statement> statements = _getMainStatements(result);
@@ -5089,7 +5089,7 @@
String fTypeString = 'double Function(int, {String b, bool c})';
await resolveTestFile();
- var classDeclaration = result.unit!.declarations[0] as ClassDeclaration;
+ var classDeclaration = result.unit.declarations[0] as ClassDeclaration;
var methodDeclaration = classDeclaration.members[0] as MethodDeclaration;
var methodElement = methodDeclaration.declaredElement as MethodElement;
@@ -5134,7 +5134,7 @@
// Validate the arguments at the call site.
//
var functionDeclaration =
- result.unit!.declarations[1] as FunctionDeclaration;
+ result.unit.declarations[1] as FunctionDeclaration;
var body = functionDeclaration.functionExpression.body as BlockFunctionBody;
var statement = body.block.statements[0] as ExpressionStatement;
var invocation = statement.expression as MethodInvocation;
@@ -5157,7 +5157,7 @@
await resolveTestFile();
expect(result.errors, isEmpty);
- var cNode = result.unit!.declarations[0] as ClassDeclaration;
+ var cNode = result.unit.declarations[0] as ClassDeclaration;
ClassElement cElement = cNode.declaredElement!;
MethodElement callElement = cElement.methods[0];
@@ -5183,7 +5183,7 @@
await resolveTestFile();
expect(result.errors, isEmpty);
- var main = result.unit!.declarations[0] as FunctionDeclaration;
+ var main = result.unit.declarations[0] as FunctionDeclaration;
var mainElement = main.declaredElement as FunctionElement;
ParameterElement parameter = mainElement.parameters[0];
@@ -5220,7 +5220,7 @@
''');
await resolveTestFile();
- var aNode = result.unit!.declarations[0] as ClassDeclaration;
+ var aNode = result.unit.declarations[0] as ClassDeclaration;
var fooNode = aNode.members[0] as MethodDeclaration;
var fooElement = fooNode.declaredElement as MethodElement;
@@ -5305,7 +5305,7 @@
await resolveTestFile();
List<Statement> mainStatements = _getMainStatements(result);
- var foo = result.unit!.declarations[1] as FunctionDeclaration;
+ var foo = result.unit.declarations[1] as FunctionDeclaration;
ExecutableElement fooElement = foo.declaredElement!;
var statement = mainStatements[0] as ExpressionStatement;
@@ -5452,7 +5452,7 @@
await resolveTestFile();
List<Statement> mainStatements = _getMainStatements(result);
- var cNode = result.unit!.declarations[1] as ClassDeclaration;
+ var cNode = result.unit.declarations[1] as ClassDeclaration;
ClassElement cElement = cNode.declaredElement!;
var mNode = cNode.members[0] as MethodDeclaration;
var mElement = mNode.declaredElement as MethodElement;
@@ -5509,7 +5509,7 @@
''');
await resolveTestFile();
- var cNode = result.unit!.declarations[0] as ClassDeclaration;
+ var cNode = result.unit.declarations[0] as ClassDeclaration;
TypeParameterElement tElement = cNode.declaredElement!.typeParameters[0];
var barNode = cNode.members[1] as MethodDeclaration;
@@ -5535,7 +5535,7 @@
InterfaceType doubleType = typeProvider.doubleType;
- var fNode = result.unit!.declarations[1] as FunctionDeclaration;
+ var fNode = result.unit.declarations[1] as FunctionDeclaration;
var fElement = fNode.declaredElement as FunctionElement;
var statement = mainStatements[0] as ExpressionStatement;
@@ -5564,7 +5564,7 @@
List<Statement> mainStatements = _getMainStatements(result);
- var fNode = result.unit!.declarations[1] as FunctionDeclaration;
+ var fNode = result.unit.declarations[1] as FunctionDeclaration;
var fElement = fNode.declaredElement as FunctionElement;
// f<bool, String>(true, 'str');
@@ -6030,7 +6030,7 @@
addTestFile(content);
await resolveTestFile();
- CompilationUnit unit = result.unit!;
+ CompilationUnit unit = result.unit;
var cClassDeclaration = unit.declarations[1] as ClassDeclaration;
ClassElement cClassElement = cClassDeclaration.declaredElement!;
@@ -6129,7 +6129,7 @@
List<Statement> statements = _getMainStatements(result);
- var cDeclaration = result.unit!.declarations[1] as ClassDeclaration;
+ var cDeclaration = result.unit.declarations[1] as ClassDeclaration;
ClassElement cElement = cDeclaration.declaredElement!;
FieldElement fElement = cElement.fields[0];
@@ -6164,7 +6164,7 @@
List<Statement> statements = _getMainStatements(result);
- var cDeclaration = result.unit!.declarations[1] as ClassDeclaration;
+ var cDeclaration = result.unit.declarations[1] as ClassDeclaration;
ClassElement cElement = cDeclaration.declaredElement!;
FieldElement fElement = cElement.fields[0];
@@ -6189,7 +6189,7 @@
await resolveTestFile();
expect(result.errors, isEmpty);
- var main = result.unit!.declarations[0] as FunctionDeclaration;
+ var main = result.unit.declarations[0] as FunctionDeclaration;
var mainElement = main.declaredElement as FunctionElement;
ParameterElement parameter = mainElement.parameters[0];
@@ -6232,7 +6232,7 @@
// TODO(scheglov) Uncomment and fix "unused imports" hint.
// expect(result.errors, isEmpty);
- var unitElement = result.unit!.declaredElement!;
+ var unitElement = result.unit.declaredElement!;
ImportElement myImport = unitElement.library.imports[0];
PrefixElement myPrefix = myImport.prefix!;
@@ -6405,7 +6405,7 @@
addTestFile(content);
await resolveTestFile();
- CompilationUnit unit = result.unit!;
+ CompilationUnit unit = result.unit;
var cClassDeclaration = unit.declarations[1] as ClassDeclaration;
ClassElement cClassElement = cClassDeclaration.declaredElement!;
@@ -6467,7 +6467,7 @@
addTestFile(content);
await resolveTestFile();
- CompilationUnit unit = result.unit!;
+ CompilationUnit unit = result.unit;
var cClassDeclaration = unit.declarations[1] as ClassDeclaration;
ClassElement cClassElement = cClassDeclaration.declaredElement!;
@@ -6504,7 +6504,7 @@
addTestFile(content);
await resolveTestFile();
- CompilationUnit unit = result.unit!;
+ CompilationUnit unit = result.unit;
var cClassDeclaration = unit.declarations[1] as ClassDeclaration;
ClassElement cClassElement = cClassDeclaration.declaredElement!;
@@ -6571,7 +6571,7 @@
}
''');
- var main = result.unit!.declarations[0] as FunctionDeclaration;
+ var main = result.unit.declarations[0] as FunctionDeclaration;
expect(main.declaredElement, isNotNull);
expect(main.name.staticElement, isNotNull);
expect(main.name.staticType, isNull);
@@ -6655,8 +6655,8 @@
addTestFile(content);
await resolveTestFile();
- var aNode = result.unit!.declarations[0] as ClassDeclaration;
- var bNode = result.unit!.declarations[1] as ClassDeclaration;
+ var aNode = result.unit.declarations[0] as ClassDeclaration;
+ var bNode = result.unit.declarations[1] as ClassDeclaration;
var methodElement = aNode.members[0].declaredElement as MethodElement;
var getterElement =
@@ -6784,7 +6784,7 @@
addTestFile(content);
await resolveTestFile();
- var aNode = result.unit!.declarations[0] as ClassDeclaration;
+ var aNode = result.unit.declarations[0] as ClassDeclaration;
var methodElement = aNode.members[0].declaredElement as MethodElement;
var getterElement =
@@ -6900,7 +6900,7 @@
addTestFile(content);
await resolveTestFile();
- var cNode = result.unit!.declarations[0] as ClassDeclaration;
+ var cNode = result.unit.declarations[0] as ClassDeclaration;
ClassElement cElement = cNode.declaredElement!;
var constructorNode = cNode.members[1] as ConstructorDeclaration;
@@ -6945,16 +6945,16 @@
addTestFile(content);
await resolveTestFile();
- var aNode = result.unit!.declarations[0] as ClassDeclaration;
+ var aNode = result.unit.declarations[0] as ClassDeclaration;
ClassElement aElement = aNode.declaredElement!;
- var bNode = result.unit!.declarations[1] as ClassDeclaration;
+ var bNode = result.unit.declarations[1] as ClassDeclaration;
ClassElement bElement = bNode.declaredElement!;
- var cNode = result.unit!.declarations[2] as ClassDeclaration;
+ var cNode = result.unit.declarations[2] as ClassDeclaration;
ClassElement cElement = cNode.declaredElement!;
- var dNode = result.unit!.declarations[3] as ClassDeclaration;
+ var dNode = result.unit.declarations[3] as ClassDeclaration;
Element dElement = dNode.declaredElement!;
SimpleIdentifier dName = dNode.name;
@@ -7014,16 +7014,16 @@
addTestFile(content);
await resolveTestFile();
- var aNode = result.unit!.declarations[0] as ClassDeclaration;
+ var aNode = result.unit.declarations[0] as ClassDeclaration;
ClassElement aElement = aNode.declaredElement!;
- var bNode = result.unit!.declarations[1] as ClassDeclaration;
+ var bNode = result.unit.declarations[1] as ClassDeclaration;
ClassElement bElement = bNode.declaredElement!;
- var cNode = result.unit!.declarations[2] as ClassDeclaration;
+ var cNode = result.unit.declarations[2] as ClassDeclaration;
ClassElement cElement = cNode.declaredElement!;
- var dNode = result.unit!.declarations[3] as ClassTypeAlias;
+ var dNode = result.unit.declarations[3] as ClassTypeAlias;
Element dElement = dNode.declaredElement!;
SimpleIdentifier dName = dNode.name;
@@ -7082,7 +7082,7 @@
addTestFile(content);
await resolveTestFile();
- var enumNode = result.unit!.declarations[0] as EnumDeclaration;
+ var enumNode = result.unit.declarations[0] as EnumDeclaration;
ClassElement enumElement = enumNode.declaredElement!;
SimpleIdentifier dName = enumNode.name;
@@ -7123,7 +7123,7 @@
ClassElement doubleElement = doubleType.element;
ClassElement intElement = intType.element;
- var cNode = result.unit!.declarations[0] as ClassDeclaration;
+ var cNode = result.unit.declarations[0] as ClassDeclaration;
ClassElement cElement = cNode.declaredElement!;
// The class name identifier.
@@ -7248,7 +7248,7 @@
// topFunction()
{
- var node = result.unit!.declarations[0] as FunctionDeclaration;
+ var node = result.unit.declarations[0] as FunctionDeclaration;
expect(node.declaredElement, isNotNull);
assertType(node.declaredElement!.type, 'int Function(double)');
@@ -7281,7 +7281,7 @@
// topGetter()
{
- var node = result.unit!.declarations[1] as FunctionDeclaration;
+ var node = result.unit.declarations[1] as FunctionDeclaration;
expect(node.declaredElement, isNotNull);
assertType(node.declaredElement!.type, 'int Function()');
@@ -7299,7 +7299,7 @@
// topSetter()
{
- var node = result.unit!.declarations[2] as FunctionDeclaration;
+ var node = result.unit.declarations[2] as FunctionDeclaration;
expect(node.declaredElement, isNotNull);
assertType(node.declaredElement!.type, 'void Function(double)');
@@ -7341,7 +7341,7 @@
addTestFile(content);
await resolveTestFile();
- CompilationUnit unit = result.unit!;
+ CompilationUnit unit = result.unit;
CompilationUnitElement unitElement = unit.declaredElement!;
var cNode = unit.declarations[0] as ClassDeclaration;
@@ -7388,7 +7388,7 @@
addTestFile(content);
await resolveTestFile();
- CompilationUnit unit = result.unit!;
+ CompilationUnit unit = result.unit;
var cNode = unit.declarations[0] as ClassDeclaration;
ClassElement cElement = cNode.declaredElement!;
@@ -7432,7 +7432,7 @@
addTestFile(content);
await resolveTestFile();
- CompilationUnit unit = result.unit!;
+ CompilationUnit unit = result.unit;
CompilationUnitElement unitElement = unit.declaredElement!;
{
@@ -7474,7 +7474,7 @@
addTestFile(content);
await resolveTestFile();
- CompilationUnit unit = result.unit!;
+ CompilationUnit unit = result.unit;
CompilationUnitElement unitElement = unit.declaredElement!;
var variableDeclaration =
@@ -7518,7 +7518,7 @@
String fTypeString = 'double Function(int, {String b, bool c})';
await resolveTestFile();
- var fDeclaration = result.unit!.declarations[0] as FunctionDeclaration;
+ var fDeclaration = result.unit.declarations[0] as FunctionDeclaration;
var fElement = fDeclaration.declaredElement as FunctionElement;
InterfaceType doubleType = typeProvider.doubleType;
@@ -7571,7 +7571,7 @@
//
// Validate the arguments at the call site.
//
- var mainDeclaration = result.unit!.declarations[1] as FunctionDeclaration;
+ var mainDeclaration = result.unit.declarations[1] as FunctionDeclaration;
var body = mainDeclaration.functionExpression.body as BlockFunctionBody;
var statement = body.block.statements[0] as ExpressionStatement;
var invocation = statement.expression as MethodInvocation;
@@ -7589,7 +7589,7 @@
addTestFile(content);
await resolveTestFile();
- CompilationUnit unit = result.unit!;
+ CompilationUnit unit = result.unit;
var alias = unit.declarations[0] as FunctionTypeAlias;
TypeAliasElement aliasElement = alias.declaredElement!;
@@ -7623,7 +7623,7 @@
''';
addTestFile(content);
await resolveTestFile();
- CompilationUnit unit = result.unit!;
+ CompilationUnit unit = result.unit;
CompilationUnitElement unitElement = unit.declaredElement!;
var aNode = unit.declarations[0] as ClassDeclaration;
@@ -7870,7 +7870,7 @@
c.A a2;
''');
await resolveTestFile();
- CompilationUnit unit = result.unit!;
+ CompilationUnit unit = result.unit;
ImportElement bImport = unit.declaredElement!.library.imports[0];
ImportElement cImport = unit.declaredElement!.library.imports[1];
@@ -7915,7 +7915,7 @@
typedef void F(int p);
''');
await resolveTestFile();
- CompilationUnit unit = result.unit!;
+ CompilationUnit unit = result.unit;
var fNode = unit.declarations[1] as FunctionTypeAlias;
TypeAliasElement fElement = fNode.declaredElement!;
@@ -8033,7 +8033,7 @@
await resolveTestFile();
expect(result.errors, isNotEmpty);
- var unitElement = result.unit!.declaredElement!;
+ var unitElement = result.unit.declaredElement!;
var foo = unitElement.library.imports[0].prefix;
List<Statement> statements = _getMainStatements(result);
@@ -8117,7 +8117,7 @@
await resolveTestFile();
expect(result.errors, isNotEmpty);
- var unitElement = result.unit!.declaredElement!;
+ var unitElement = result.unit.declaredElement!;
var mathImport = unitElement.library.imports[0];
var foo = mathImport.prefix;
@@ -8163,7 +8163,7 @@
await resolveTestFile();
expect(result.errors, isNotEmpty);
- var unitElement = result.unit!.declaredElement!;
+ var unitElement = result.unit.declaredElement!;
var mathImport = unitElement.library.imports[0];
var foo = mathImport.prefix;
var randomElement = mathImport.importedLibrary!.getType('Random')!;
@@ -8716,7 +8716,7 @@
}
List<Statement> _getMainStatements(ResolvedUnitResult result) {
- for (var declaration in result.unit!.declarations) {
+ for (var declaration in result.unit.declarations) {
if (declaration is FunctionDeclaration &&
declaration.name.name == 'main') {
var body = declaration.functionExpression.body as BlockFunctionBody;
@@ -8728,7 +8728,7 @@
TopLevelVariableElement _getTopLevelVariable(
ResolvedUnitResult result, String name) {
- for (var variable in result.unit!.declaredElement!.topLevelVariables) {
+ for (var variable in result.unit.declaredElement!.topLevelVariables) {
if (variable.name == name) {
return variable;
}
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
index dee0e8e..29a974a 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
@@ -59,7 +59,7 @@
late final AnalysisDriverScheduler scheduler;
- List<ResolvedUnitResult> allResults = [];
+ final List<AnalysisResultWithErrors> allResults = [];
AnalysisDriver newDriver() {
sdk = MockSdk(resourceProvider: resourceProvider);
@@ -74,7 +74,11 @@
analysisOptions: AnalysisOptionsImpl(),
packages: Packages.empty,
);
- driver.results.forEach(allResults.add);
+ driver.results.listen((result) {
+ if (result is AnalysisResultWithErrors) {
+ allResults.add(result);
+ }
+ });
return driver;
}
@@ -444,9 +448,9 @@
ResolvedUnitResult partResult1 = await driver.getResultValid(part1);
ResolvedUnitResult partResult2 = await driver.getResultValid(part2);
- CompilationUnit libUnit = libResult.unit!;
- CompilationUnit partUnit1 = partResult1.unit!;
- CompilationUnit partUnit2 = partResult2.unit!;
+ CompilationUnit libUnit = libResult.unit;
+ CompilationUnit partUnit1 = partResult1.unit;
+ CompilationUnit partUnit2 = partResult2.unit;
CompilationUnitElement unitElement = libUnit.declaredElement!;
CompilationUnitElement partElement1 = partUnit1.declaredElement!;
@@ -669,8 +673,10 @@
await waitForIdleWithoutExceptions();
expect(allResults, hasLength(1));
{
- ResolvedUnitResult ar = allResults.firstWhere((r) => r.path == a);
- _assertTopLevelVarType(ar.unit!, 'A', 'int');
+ ResolvedUnitResult ar = allResults
+ .whereType<ResolvedUnitResult>()
+ .firstWhere((r) => r.path == a);
+ _assertTopLevelVarType(ar.unit, 'A', 'int');
}
allResults.clear();
@@ -686,8 +692,10 @@
await waitForIdleWithoutExceptions();
expect(allResults, hasLength(1));
{
- ResolvedUnitResult ar = allResults.firstWhere((r) => r.path == a);
- _assertTopLevelVarType(ar.unit!, 'A', 'double');
+ ResolvedUnitResult ar = allResults
+ .whereType<ResolvedUnitResult>()
+ .firstWhere((r) => r.path == a);
+ _assertTopLevelVarType(ar.unit, 'A', 'double');
}
}
@@ -740,13 +748,17 @@
// We have results for both "a" and "b".
expect(allResults, hasLength(2));
{
- ResolvedUnitResult ar = allResults.firstWhere((r) => r.path == a);
- _assertTopLevelVarType(ar.unit!, 'A1', 'int');
- _assertTopLevelVarType(ar.unit!, 'A2', 'int');
+ ResolvedUnitResult ar = allResults
+ .whereType<ResolvedUnitResult>()
+ .firstWhere((r) => r.path == a);
+ _assertTopLevelVarType(ar.unit, 'A1', 'int');
+ _assertTopLevelVarType(ar.unit, 'A2', 'int');
}
{
- ResolvedUnitResult br = allResults.firstWhere((r) => r.path == b);
- _assertTopLevelVarType(br.unit!, 'B1', 'int');
+ ResolvedUnitResult br = allResults
+ .whereType<ResolvedUnitResult>()
+ .firstWhere((r) => r.path == b);
+ _assertTopLevelVarType(br.unit, 'B1', 'int');
}
// Clear the results and update "a".
@@ -763,13 +775,17 @@
await waitForIdleWithoutExceptions();
expect(allResults, hasLength(2));
{
- ResolvedUnitResult ar = allResults.firstWhere((r) => r.path == a);
- _assertTopLevelVarType(ar.unit!, 'A1', 'double');
- _assertTopLevelVarType(ar.unit!, 'A2', 'double');
+ ResolvedUnitResult ar = allResults
+ .whereType<ResolvedUnitResult>()
+ .firstWhere((r) => r.path == a);
+ _assertTopLevelVarType(ar.unit, 'A1', 'double');
+ _assertTopLevelVarType(ar.unit, 'A2', 'double');
}
{
- ResolvedUnitResult br = allResults.firstWhere((r) => r.path == b);
- _assertTopLevelVarType(br.unit!, 'B1', 'double');
+ ResolvedUnitResult br = allResults
+ .whereType<ResolvedUnitResult>()
+ .firstWhere((r) => r.path == b);
+ _assertTopLevelVarType(br.unit, 'B1', 'double');
}
}
@@ -780,9 +796,9 @@
{
await waitForIdleWithoutExceptions();
expect(allResults, hasLength(1));
- ResolvedUnitResult result = allResults[0];
+ var result = allResults[0] as ResolvedUnitResult;
expect(result.path, testFile);
- _assertTopLevelVarType(result.unit!, 'V', 'int');
+ _assertTopLevelVarType(result.unit, 'V', 'int');
}
// Update the file, but don't notify the driver.
@@ -803,9 +819,9 @@
{
await waitForIdleWithoutExceptions();
expect(allResults, hasLength(1));
- ResolvedUnitResult result = allResults[0];
+ var result = allResults[0] as ResolvedUnitResult;
expect(result.path, testFile);
- _assertTopLevelVarType(result.unit!, 'V', 'double');
+ _assertTopLevelVarType(result.unit, 'V', 'double');
}
}
@@ -820,7 +836,7 @@
class C {}
''');
var result = await driver.getResultValid(testFile);
- var atD = AstFinder.getClass(result.unit!, 'C').metadata[0];
+ var atD = AstFinder.getClass(result.unit, 'C').metadata[0];
var atDI = atD.elementAnnotation as ElementAnnotationImpl;
var value = atDI.evaluationResult!.value;
// That is illegal.
@@ -837,7 +853,7 @@
}
''');
var result = await driver.getResultValid(testFile);
- var atD = AstFinder.getClass(result.unit!, 'C').metadata[0];
+ var atD = AstFinder.getClass(result.unit, 'C').metadata[0];
var atDI = atD.elementAnnotation as ElementAnnotationImpl;
var value = atDI.evaluationResult!.value!;
expect(value.type, isNotNull);
@@ -853,7 +869,7 @@
@x class C {}
''');
var result = await driver.getResultValid(testFile);
- Annotation at_x = AstFinder.getClass(result.unit!, 'C').metadata[0];
+ Annotation at_x = AstFinder.getClass(result.unit, 'C').metadata[0];
expect(at_x.elementAnnotation!.computeConstantValue()!.toIntValue(), 1);
}
@@ -863,7 +879,7 @@
const y = x + 1;
''');
var result = await driver.getResultValid(testFile);
- var x = AstFinder.getTopLevelVariableElement(result.unit!, 'x')
+ var x = AstFinder.getTopLevelVariableElement(result.unit, 'x')
as TopLevelVariableElementImpl;
_expectCircularityError(x.evaluationResult!);
}
@@ -874,8 +890,8 @@
const y = 1;
''');
var result = await driver.getResultValid(testFile);
- var x = AstFinder.getTopLevelVariableElement(result.unit!, 'x');
- var y = AstFinder.getTopLevelVariableElement(result.unit!, 'y');
+ var x = AstFinder.getTopLevelVariableElement(result.unit, 'x');
+ var y = AstFinder.getTopLevelVariableElement(result.unit, 'y');
expect(x.computeConstantValue()!.toIntValue(), 2);
expect(y.computeConstantValue()!.toIntValue(), 1);
}
@@ -891,7 +907,7 @@
class B {}
''');
var result = await driver.getResultValid(testFile);
- var x = AstFinder.getTopLevelVariableElement(result.unit!, 'x');
+ var x = AstFinder.getTopLevelVariableElement(result.unit, 'x');
expect(x.computeConstantValue(), isNotNull);
}
@@ -957,7 +973,7 @@
const x = const Derived();
''');
var result = await driver.getResultValid(testFile);
- var x = AstFinder.getTopLevelVariableElement(result.unit!, 'x');
+ var x = AstFinder.getTopLevelVariableElement(result.unit, 'x');
expect(x.computeConstantValue(), isNotNull);
}
@@ -966,7 +982,7 @@
const x = 1;
''');
var result = await driver.getResultValid(testFile);
- var x = AstFinder.getTopLevelVariableElement(result.unit!, 'x');
+ var x = AstFinder.getTopLevelVariableElement(result.unit, 'x');
expect(x.computeConstantValue()!.toIntValue(), 1);
}
@@ -1403,10 +1419,10 @@
var result = driver.getParsedLibrary2(testFile);
result as ParsedLibraryResult;
expect(result.units, hasLength(1));
- expect(result.units![0].path, testFile);
- expect(result.units![0].content, content);
- expect(result.units![0].unit, isNotNull);
- expect(result.units![0].errors, isEmpty);
+ expect(result.units[0].path, testFile);
+ expect(result.units[0].content, content);
+ expect(result.units[0].unit, isNotNull);
+ expect(result.units[0].errors, isEmpty);
}
test_getParsedLibrary2_invalidPath_notAbsolute() async {
@@ -1429,9 +1445,9 @@
result as ParsedLibraryResult;
expect(result.uri, uri);
expect(result.units, hasLength(1));
- expect(result.units![0].uri, uri);
- expect(result.units![0].path, testFile);
- expect(result.units![0].content, content);
+ expect(result.units[0].uri, uri);
+ expect(result.units[0].path, testFile);
+ expect(result.units[0].content, content);
}
test_getParsedLibraryByUri2_notLibrary() async {
@@ -1454,10 +1470,10 @@
var result = await driver.getResolvedLibrary2(testFile);
result as ResolvedLibraryResult;
expect(result.units, hasLength(1));
- expect(result.units![0].path, testFile);
- expect(result.units![0].content, content);
- expect(result.units![0].unit, isNotNull);
- expect(result.units![0].errors, isEmpty);
+ expect(result.units[0].path, testFile);
+ expect(result.units[0].content, content);
+ expect(result.units[0].unit, isNotNull);
+ expect(result.units[0].errors, isEmpty);
}
test_getResolvedLibrary2_invalidPath_notAbsolute() async {
@@ -1479,11 +1495,11 @@
var result = await driver.getResolvedLibraryByUri2(uri);
result as ResolvedLibraryResult;
expect(result.uri, uri);
- expect(result.element!.source.fullName, testFile);
+ expect(result.element.source.fullName, testFile);
expect(result.units, hasLength(1));
- expect(result.units![0].uri, uri);
- expect(result.units![0].path, testFile);
- expect(result.units![0].content, content);
+ expect(result.units[0].uri, uri);
+ expect(result.units[0].path, testFile);
+ expect(result.units[0].content, content);
}
test_getResolvedLibraryByUri2_notLibrary() async {
@@ -1512,7 +1528,7 @@
expect(result.unit, isNotNull);
expect(result.errors, hasLength(0));
- var f = result.unit!.declarations[0] as FunctionDeclaration;
+ var f = result.unit.declarations[0] as FunctionDeclaration;
assertType(f.declaredElement!.type, 'int Function()');
assertType(f.returnType!.typeOrThrow, 'int');
@@ -1657,7 +1673,7 @@
await waitForIdleWithoutExceptions();
ResolvedUnitResult result = await driver.getResultValid(testFile);
- _assertClassFieldType(result.unit!, 'C', 'f', 'int');
+ _assertClassFieldType(result.unit, 'C', 'f', 'int');
}
test_getResult_inferTypes_instanceMethod() async {
@@ -1672,8 +1688,8 @@
await waitForIdleWithoutExceptions();
ResolvedUnitResult result = await driver.getResultValid(testFile);
- _assertClassMethodReturnType(result.unit!, 'A', 'm', 'int');
- _assertClassMethodReturnType(result.unit!, 'B', 'm', 'int');
+ _assertClassMethodReturnType(result.unit, 'A', 'm', 'int');
+ _assertClassMethodReturnType(result.unit, 'B', 'm', 'int');
}
test_getResult_invalid_annotation_functionAsConstructor() async {
@@ -1685,7 +1701,7 @@
''', priority: true);
ResolvedUnitResult result = await driver.getResultValid(testFile);
- ClassDeclaration c = result.unit!.declarations[1] as ClassDeclaration;
+ ClassDeclaration c = result.unit.declarations[1] as ClassDeclaration;
Annotation a = c.metadata[0];
expect(a.name.name, 'fff');
expect(a.name.staticElement, isFunctionElement);
@@ -1772,7 +1788,7 @@
''');
var result = await driver.getResultValid(path);
- var languageVersion = result.unit!.languageVersionToken!;
+ var languageVersion = result.unit.languageVersionToken!;
expect(languageVersion.major, 2);
expect(languageVersion.minor, 7);
}
@@ -1855,7 +1871,7 @@
ResolvedUnitResult result = await driver.getResultValid(path);
expect(result, isNotNull);
- expect(result.unit!.declaredElement!.classes.map((e) => e.name), ['A']);
+ expect(result.unit.declaredElement!.classes.map((e) => e.name), ['A']);
}
test_getResult_recursiveFlatten() async {
@@ -1888,18 +1904,18 @@
{
ResolvedUnitResult result = await driver.getResultValid(b);
- expect(_getImportSource(result.unit!, 0).uri.toString(),
+ expect(_getImportSource(result.unit, 0).uri.toString(),
'package:test/a.dart');
- _assertTopLevelVarType(result.unit!, 'VB', 'A<int>');
+ _assertTopLevelVarType(result.unit, 'VB', 'A<int>');
}
{
ResolvedUnitResult result = await driver.getResultValid(c);
expect(
- _getImportSource(result.unit!, 0).uri,
+ _getImportSource(result.unit, 0).uri,
toUri('/test/lib/a.dart'),
);
- _assertTopLevelVarType(result.unit!, 'VC', 'A<double>');
+ _assertTopLevelVarType(result.unit, 'VC', 'A<double>');
}
}
@@ -1922,8 +1938,8 @@
{
ResolvedUnitResult result = await driver.getResultValid(a);
- _assertTopLevelVarType(result.unit!, 'A1', 'int');
- _assertTopLevelVarType(result.unit!, 'A2', 'int');
+ _assertTopLevelVarType(result.unit, 'A1', 'int');
+ _assertTopLevelVarType(result.unit, 'A2', 'int');
}
// Update "a" so that "A1" is now "double".
@@ -1942,8 +1958,8 @@
{
ResolvedUnitResult result = await driver.getResultValid(a);
- _assertTopLevelVarType(result.unit!, 'A1', 'double');
- _assertTopLevelVarType(result.unit!, 'A2', 'double');
+ _assertTopLevelVarType(result.unit, 'A1', 'double');
+ _assertTopLevelVarType(result.unit, 'A2', 'double');
}
}
@@ -2078,7 +2094,7 @@
''');
var result = await driver.getResultValid(b);
- var c = _getTopLevelVar(result.unit!, 'c');
+ var c = _getTopLevelVar(result.unit, 'c');
var typeC = c.declaredElement!.type as InterfaceType;
// The class C has an old field 'foo', not the new 'bar'.
expect(typeC.element.getField('foo'), isNotNull);
@@ -2517,15 +2533,15 @@
{
ResolvedUnitResult result = await driver.getResultValid(a);
expect(result.errors, isEmpty);
- _assertTopLevelVarType(result.unit!, 'c', 'C');
+ _assertTopLevelVarType(result.unit, 'c', 'C');
}
// Now c.dart can be resolved without errors in the context of a.dart
{
ResolvedUnitResult result = await driver.getResultValid(c);
expect(result.errors, isEmpty);
- _assertTopLevelVarType(result.unit!, 'a', 'A');
- _assertTopLevelVarType(result.unit!, 'b', 'B');
+ _assertTopLevelVarType(result.unit, 'a', 'A');
+ _assertTopLevelVarType(result.unit, 'b', 'B');
}
}
@@ -2556,8 +2572,8 @@
// So, A and B references are resolved.
ResolvedUnitResult result = await driver.getResultValid(c);
expect(result.errors, isEmpty);
- _assertTopLevelVarType(result.unit!, 'a', 'A');
- _assertTopLevelVarType(result.unit!, 'b', 'B');
+ _assertTopLevelVarType(result.unit, 'a', 'A');
+ _assertTopLevelVarType(result.unit, 'b', 'B');
}
test_part_getResult_changePart_invalidatesLibraryCycle() async {
@@ -2735,9 +2751,9 @@
// c.dart was added after a.dart, so it is analyzed after a.dart,
// so we know that a.dart is the library of c.dart, so no errors.
- ResolvedUnitResult result = allResults.lastWhere((r) => r.path == c);
+ var result =
+ allResults.whereType<ErrorsResult>().lastWhere((r) => r.path == c);
expect(result.errors, isEmpty);
- expect(result.unit, isNull);
}
// Update a.dart so that c.dart is not a part.
@@ -2748,9 +2764,9 @@
// Now c.dart does not have a library context, so A and B cannot be
// resolved, so there are errors.
- ResolvedUnitResult result = allResults.lastWhere((r) => r.path == c);
+ var result =
+ allResults.whereType<ErrorsResult>().lastWhere((r) => r.path == c);
expect(result.errors, isNotEmpty);
- expect(result.unit, isNull);
}
}
@@ -2784,9 +2800,9 @@
// a.dart, but we cannot find the library for it, so we delay analysis
// until all other files are analyzed, including a.dart, after which we
// analyze the delayed parts.
- ResolvedUnitResult result = allResults.lastWhere((r) => r.path == c);
+ var result =
+ allResults.whereType<ErrorsResult>().lastWhere((r) => r.path == c);
expect(result.errors, isEmpty);
- expect(result.unit, isNull);
}
test_part_results_noLibrary() async {
@@ -2804,9 +2820,9 @@
// There is no library which c.dart is a part of, so it has unresolved
// A and B references.
- ResolvedUnitResult result = allResults.lastWhere((r) => r.path == c);
+ var result =
+ allResults.whereType<ErrorsResult>().lastWhere((r) => r.path == c);
expect(result.errors, isNotEmpty);
- expect(result.unit, isNull);
}
test_part_results_priority_beforeLibrary() async {
@@ -2840,7 +2856,9 @@
// a.dart, but we cannot find the library for it, so we delay analysis
// until all other files are analyzed, including a.dart, after which we
// analyze the delayed parts.
- ResolvedUnitResult result = allResults.lastWhere((r) => r.path == c);
+ ResolvedUnitResult result = allResults
+ .whereType<ResolvedUnitResult>()
+ .lastWhere((r) => r.path == c);
expect(result.errors, isEmpty);
expect(result.unit, isNotNull);
}
@@ -2862,12 +2880,16 @@
await waitForIdleWithoutExceptions();
expect(allResults, hasLength(2));
{
- ResolvedUnitResult ar = allResults.firstWhere((r) => r.path == a);
- _assertTopLevelVarType(ar.unit!, 'A', 'int');
+ ResolvedUnitResult ar = allResults
+ .whereType<ResolvedUnitResult>()
+ .firstWhere((r) => r.path == a);
+ _assertTopLevelVarType(ar.unit, 'A', 'int');
}
{
- ResolvedUnitResult br = allResults.firstWhere((r) => r.path == b);
- _assertTopLevelVarType(br.unit!, 'B', 'int');
+ ResolvedUnitResult br = allResults
+ .whereType<ResolvedUnitResult>()
+ .firstWhere((r) => r.path == b);
+ _assertTopLevelVarType(br.unit, 'B', 'int');
}
allResults.clear();
@@ -2882,8 +2904,10 @@
await waitForIdleWithoutExceptions();
expect(allResults, hasLength(1));
{
- ResolvedUnitResult ar = allResults.firstWhere((r) => r.path == a);
- _assertTopLevelVarType(ar.unit!, 'A', 'double');
+ ResolvedUnitResult ar = allResults
+ .whereType<ResolvedUnitResult>()
+ .firstWhere((r) => r.path == a);
+ _assertTopLevelVarType(ar.unit, 'A', 'double');
}
}
@@ -3028,7 +3052,7 @@
driver.changeFile(b);
await waitForIdleWithoutExceptions();
- List<String> analyzedPaths = allResults.map((r) => r.path!).toList();
+ List<String> analyzedPaths = allResults.map((r) => r.path).toList();
// The changed file must be the first.
expect(analyzedPaths[0], b);
@@ -3070,7 +3094,7 @@
driver.changeFile(a);
await waitForIdleWithoutExceptions();
- List<String> analyzedPaths = allResults.map((r) => r.path!).toList();
+ List<String> analyzedPaths = allResults.map((r) => r.path).toList();
// The changed files must be the first.
expect(analyzedPaths[0], a);
@@ -3088,14 +3112,14 @@
await waitForIdleWithoutExceptions();
expect(allResults, hasLength(1));
- ResolvedUnitResult result = allResults.single;
+ var result = allResults.single as ResolvedUnitResult;
expect(result.path, testFile);
expect(result.uri.toString(), 'package:test/test.dart');
expect(result.content, content);
expect(result.unit, isNotNull);
expect(result.errors, hasLength(0));
- var f = result.unit!.declarations[0] as FunctionDeclaration;
+ var f = result.unit.declarations[0] as FunctionDeclaration;
assertType(f.declaredElement!.type, 'int Function()');
assertType(f.returnType!.typeOrThrow, 'int');
}
@@ -3115,7 +3139,7 @@
await waitForIdleWithoutExceptions();
expect(allResults, hasLength(3));
- ResolvedUnitResult result = allResults[0];
+ var result = allResults[0] as ResolvedUnitResult;
expect(result.path, b);
expect(result.unit, isNotNull);
expect(result.errors, hasLength(0));
@@ -3127,11 +3151,9 @@
await waitForIdleWithoutExceptions();
expect(allResults, hasLength(1));
- ResolvedUnitResult result = allResults.single;
+ var result = allResults.single as ErrorsResult;
expect(result.path, testFile);
expect(result.uri.toString(), 'package:test/test.dart');
- expect(result.content, isNull);
- expect(result.unit, isNull);
expect(result.errors, hasLength(0));
}
diff --git a/pkg/analyzer/test/src/dart/analysis/index_test.dart b/pkg/analyzer/test/src/dart/analysis/index_test.dart
index 63c5831..c61fa44 100644
--- a/pkg/analyzer/test/src/dart/analysis/index_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/index_test.dart
@@ -1734,7 +1734,7 @@
Future<void> _indexTestUnit(String code) async {
await resolveTestCode(code);
- var indexBuilder = indexUnit(result.unit!);
+ var indexBuilder = indexUnit(result.unit);
var indexBytes = indexBuilder.toBuffer();
index = AnalysisDriverUnitIndex.fromBuffer(indexBytes);
}
diff --git a/pkg/analyzer/test/src/dart/analysis/results/get_element_declaration_test.dart b/pkg/analyzer/test/src/dart/analysis/results/get_element_declaration_test.dart
index 89fdeda..983d7bb 100644
--- a/pkg/analyzer/test/src/dart/analysis/results/get_element_declaration_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/results/get_element_declaration_test.dart
@@ -42,7 +42,7 @@
expect(node.name.name, 'A');
expect(
node.name.offset,
- this.result.content!.indexOf('A {} // 1'),
+ this.result.content.indexOf('A {} // 1'),
);
}
@@ -53,7 +53,7 @@
expect(node.name.name, 'A');
expect(
node.name.offset,
- this.result.content!.indexOf('A {} // 2'),
+ this.result.content.indexOf('A {} // 2'),
);
}
}
@@ -66,7 +66,7 @@
await resolveTestCode(r'''
part 'a.dart';
''');
- var library = this.result.unit!.declaredElement!.library;
+ var library = this.result.unit.declaredElement!.library;
var element = library.getType('A')!;
var result = await getElementDeclaration(element);
var node = result!.node as ClassDeclaration;
@@ -139,7 +139,7 @@
expect(node.name!.name, 'named');
expect(
node.name!.offset,
- this.result.content!.indexOf('named(); // 1'),
+ this.result.content.indexOf('named(); // 1'),
);
}
@@ -150,7 +150,7 @@
expect(node.name!.name, 'named');
expect(
node.name!.offset,
- this.result.content!.indexOf('named(); // 2'),
+ this.result.content.indexOf('named(); // 2'),
);
}
}
@@ -169,7 +169,7 @@
expect(node.name, isNull);
expect(
node.returnType.offset,
- this.result.content!.indexOf('A(); // 1'),
+ this.result.content.indexOf('A(); // 1'),
);
}
@@ -180,7 +180,7 @@
expect(node.name, isNull);
expect(
node.returnType.offset,
- this.result.content!.indexOf('A(); // 2'),
+ this.result.content.indexOf('A(); // 2'),
);
}
}
@@ -439,7 +439,7 @@
ParsedLibraryResult _getParsedLibrary(String path) {
var session = contextFor(path).currentSession;
- return session.getParsedLibrary2(path) as ParsedLibraryResult;
+ return session.getParsedLibrary(path) as ParsedLibraryResult;
}
}
@@ -456,6 +456,6 @@
Future<ResolvedLibraryResult> _getResolvedLibrary(String path) async {
var session = contextFor(path).currentSession;
- return await session.getResolvedLibrary2(path) as ResolvedLibraryResult;
+ return await session.getResolvedLibrary(path) as ResolvedLibraryResult;
}
}
diff --git a/pkg/analyzer/test/src/dart/analysis/search_test.dart b/pkg/analyzer/test/src/dart/analysis/search_test.dart
index 5b33cdf..dab758b 100644
--- a/pkg/analyzer/test/src/dart/analysis/search_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/search_test.dart
@@ -64,7 +64,7 @@
class SearchTest extends PubPackageResolutionTest {
AnalysisDriver get driver => driverFor(testFilePath);
- CompilationUnitElement get resultUnitElement => result.unit!.declaredElement!;
+ CompilationUnitElement get resultUnitElement => result.unit.declaredElement!;
String get testUriStr => 'package:test/test.dart';
@@ -378,7 +378,7 @@
var element = findElement.unnamedConstructor('A');
var otherUnitResult = await driver.getResult2(other) as ResolvedUnitResult;
- CompilationUnit otherUnit = otherUnitResult.unit!;
+ CompilationUnit otherUnit = otherUnitResult.unit;
Element main = otherUnit.declaredElement!.functions[0];
var expected = [
ExpectedResult(main, SearchResultKind.REFERENCE,
diff --git a/pkg/analyzer/test/src/dart/analysis/session_helper_test.dart b/pkg/analyzer/test/src/dart/analysis/session_helper_test.dart
index 6e96379..6beca53 100644
--- a/pkg/analyzer/test/src/dart/analysis/session_helper_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/session_helper_test.dart
@@ -91,7 +91,7 @@
''');
var element = findNode.classDeclaration('A').declaredElement!;
var resolvedUnit = (await helper.getResolvedUnitByElement(element))!;
- expect(resolvedUnit.unit!.declarations, hasLength(2));
+ expect(resolvedUnit.unit.declarations, hasLength(2));
}
test_getTopLevelPropertyAccessor_defined_getter() async {
diff --git a/pkg/analyzer/test/src/dart/analysis/session_test.dart b/pkg/analyzer/test/src/dart/analysis/session_test.dart
index 1d2f2b0..6a9d493 100644
--- a/pkg/analyzer/test/src/dart/analysis/session_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/session_test.dart
@@ -33,7 +33,7 @@
var path = convertPath('$workspaceRootPath/$relPath');
var session = contextFor(path).currentSession;
- var result = await session.getErrors2(path);
+ var result = await session.getErrors(path);
expect(result, isA<NotPathOfUriResult>());
}
@@ -57,7 +57,7 @@
var path = convertPath('$workspaceRootPath/$relPath');
var session = contextFor(path).currentSession;
- var result = session.getParsedLibrary2(path);
+ var result = session.getParsedLibrary(path);
expect(result, isA<NotPathOfUriResult>());
}
@@ -67,7 +67,7 @@
var path = convertPath('$workspaceRootPath/$relPath');
var session = contextFor(path).currentSession;
- var result = await session.getResolvedLibrary2(path);
+ var result = await session.getResolvedLibrary(path);
expect(result, isA<NotPathOfUriResult>());
}
@@ -77,7 +77,7 @@
var path = convertPath('$workspaceRootPath/$relPath');
var session = contextFor(path).currentSession;
- var result = await session.getResolvedUnit2(path);
+ var result = await session.getResolvedUnit(path);
expect(result, isA<NotPathOfUriResult>());
}
@@ -88,8 +88,7 @@
);
var session = contextFor(file.path).currentSession;
- var result =
- await session.getResolvedUnit2(file.path) as ResolvedUnitResult;
+ var result = await session.getResolvedUnit(file.path) as ResolvedUnitResult;
expect(result.state, ResultState.VALID);
expect(result.path, file.path);
expect(result.errors, isEmpty);
@@ -103,7 +102,7 @@
);
var session = contextFor(file.path).currentSession;
- var result = await session.getUnitElement2('not_absolute.dart');
+ var result = await session.getUnitElement('not_absolute.dart');
expect(result, isA<InvalidPathResult>());
}
@@ -113,7 +112,7 @@
var path = convertPath('$workspaceRootPath/$relPath');
var session = contextFor(path).currentSession;
- var result = await session.getUnitElement2(path);
+ var result = await session.getUnitElement(path);
expect(result, isA<NotPathOfUriResult>());
}
@@ -175,12 +174,12 @@
}
test_getErrors2_invalidPath_notAbsolute() async {
- var errorsResult = await session.getErrors2('not_absolute.dart');
+ var errorsResult = await session.getErrors('not_absolute.dart');
expect(errorsResult, isA<InvalidPathResult>());
}
test_getFile2_invalidPath_notAbsolute() async {
- var errorsResult = session.getFile2('not_absolute.dart');
+ var errorsResult = session.getFile('not_absolute.dart');
expect(errorsResult, isA<InvalidPathResult>());
}
@@ -216,7 +215,7 @@
}
test_getLibraryByUri2_unresolvedUri() async {
- var result = await session.getLibraryByUri2('package:foo/foo.dart');
+ var result = await session.getLibraryByUri('package:foo/foo.dart');
expect(result, isA<CannotResolveUriResult>());
}
@@ -233,7 +232,7 @@
expect(parsedLibrary.units, hasLength(1));
{
- var parsedUnit = parsedLibrary.units![0];
+ var parsedUnit = parsedLibrary.units[0];
expect(parsedUnit.session, session);
expect(parsedUnit.path, testPath);
expect(parsedUnit.uri, Uri.parse('package:test/test.dart'));
@@ -242,13 +241,13 @@
}
test_getParsedLibrary2_invalidPath_notAbsolute() async {
- var result = session.getParsedLibrary2('not_absolute.dart');
+ var result = session.getParsedLibrary('not_absolute.dart');
expect(result, isA<InvalidPathResult>());
}
test_getParsedLibrary2_notLibrary() async {
newFile(testPath, content: 'part of "a.dart";');
- expect(session.getParsedLibrary2(testPath), isA<NotLibraryButPartResult>());
+ expect(session.getParsedLibrary(testPath), isA<NotLibraryButPartResult>());
}
test_getParsedLibrary2_parts() async {
@@ -288,21 +287,21 @@
expect(parsedLibrary.units, hasLength(3));
{
- var aUnit = parsedLibrary.units![0];
+ var aUnit = parsedLibrary.units[0];
expect(aUnit.path, a);
expect(aUnit.uri, Uri.parse('package:test/a.dart'));
expect(aUnit.unit.declarations, hasLength(1));
}
{
- var bUnit = parsedLibrary.units![1];
+ var bUnit = parsedLibrary.units[1];
expect(bUnit.path, b);
expect(bUnit.uri, Uri.parse('package:test/b.dart'));
expect(bUnit.unit.declarations, hasLength(2));
}
{
- var cUnit = parsedLibrary.units![2];
+ var cUnit = parsedLibrary.units[2];
expect(cUnit.path, c);
expect(cUnit.uri, Uri.parse('package:test/c.dart'));
expect(cUnit.unit.declarations, hasLength(3));
@@ -332,7 +331,7 @@
newFile(testPath, content: '');
var resolvedUnit =
- await session.getResolvedUnit2(testPath) as ResolvedUnitResult;
+ await session.getResolvedUnit(testPath) as ResolvedUnitResult;
var typeProvider = resolvedUnit.typeProvider;
var intClass = typeProvider.intType.element;
@@ -378,15 +377,15 @@
expect(parsedLibrary.units, hasLength(3));
expect(
- parsedLibrary.units![0].path,
+ parsedLibrary.units[0].path,
convertPath('/home/test/lib/test.dart'),
);
expect(
- parsedLibrary.units![1].path,
+ parsedLibrary.units[1].path,
convertPath('/home/test/lib/a.dart'),
);
expect(
- parsedLibrary.units![2].path,
+ parsedLibrary.units[2].path,
convertPath('/home/test/lib/c.dart'),
);
}
@@ -417,7 +416,7 @@
var aaaSession =
contextCollection.contextFor(aaaContextPath).currentSession;
- var result = aaaSession.getParsedLibraryByElement2(element);
+ var result = aaaSession.getParsedLibraryByElement(element);
expect(result, isA<NotElementOfThisSessionResult>());
}
@@ -435,7 +434,7 @@
}
test_getParsedUnit2_invalidPath_notAbsolute() async {
- var result = session.getParsedUnit2('not_absolute.dart');
+ var result = session.getParsedUnit('not_absolute.dart');
expect(result, isA<InvalidPathResult>());
}
@@ -466,28 +465,28 @@
var typeProvider = resolvedLibrary.typeProvider;
expect(typeProvider.intType.element.name, 'int');
- var libraryElement = resolvedLibrary.element!;
+ var libraryElement = resolvedLibrary.element;
var aClass = libraryElement.getType('A')!;
var bClass = libraryElement.getType('B')!;
- var aUnitResult = resolvedLibrary.units![0];
+ var aUnitResult = resolvedLibrary.units[0];
expect(aUnitResult.path, a);
expect(aUnitResult.uri, Uri.parse('package:test/a.dart'));
expect(aUnitResult.content, aContent);
expect(aUnitResult.unit, isNotNull);
- expect(aUnitResult.unit!.directives, hasLength(1));
- expect(aUnitResult.unit!.declarations, hasLength(1));
+ expect(aUnitResult.unit.directives, hasLength(1));
+ expect(aUnitResult.unit.declarations, hasLength(1));
expect(aUnitResult.errors, isEmpty);
- var bUnitResult = resolvedLibrary.units![1];
+ var bUnitResult = resolvedLibrary.units[1];
expect(bUnitResult.path, b);
expect(bUnitResult.uri, Uri.parse('package:test/b.dart'));
expect(bUnitResult.content, bContent);
expect(bUnitResult.unit, isNotNull);
- expect(bUnitResult.unit!.directives, hasLength(1));
- expect(bUnitResult.unit!.declarations, hasLength(2));
+ expect(bUnitResult.unit.directives, hasLength(1));
+ expect(bUnitResult.unit.declarations, hasLength(2));
expect(bUnitResult.errors, isNotEmpty);
var aDeclaration = resolvedLibrary.getElementDeclaration(aClass)!;
@@ -506,14 +505,14 @@
}
test_getResolvedLibrary2_invalidPath_notAbsolute() async {
- var result = await session.getResolvedLibrary2('not_absolute.dart');
+ var result = await session.getResolvedLibrary('not_absolute.dart');
expect(result, isA<InvalidPathResult>());
}
test_getResolvedLibrary2_notLibrary() async {
newFile(testPath, content: 'part of "a.dart";');
- var result = await session.getResolvedLibrary2(testPath);
+ var result = await session.getResolvedLibrary(testPath);
expect(result, isA<NotLibraryButPartResult>());
}
@@ -534,7 +533,7 @@
''');
var resolvedLibrary = await session.getResolvedLibraryValid(testPath);
- var unitElement = resolvedLibrary.element!.definingCompilationUnit;
+ var unitElement = resolvedLibrary.element.definingCompilationUnit;
var fooElement = unitElement.topLevelVariables[0];
expect(fooElement.name, 'foo');
@@ -563,15 +562,15 @@
expect(resolvedLibrary.units, hasLength(3));
expect(
- resolvedLibrary.units![0].path,
+ resolvedLibrary.units[0].path,
convertPath('/home/test/lib/test.dart'),
);
expect(
- resolvedLibrary.units![1].path,
+ resolvedLibrary.units[1].path,
convertPath('/home/test/lib/a.dart'),
);
expect(
- resolvedLibrary.units![2].path,
+ resolvedLibrary.units[2].path,
convertPath('/home/test/lib/c.dart'),
);
}
@@ -589,7 +588,7 @@
expect(result.path, testPath);
expect(result.uri, Uri.parse('package:test/test.dart'));
expect(result.units, hasLength(1));
- expect(result.units![0].unit!.declaredElement, isNotNull);
+ expect(result.units[0].unit.declaredElement, isNotNull);
}
test_getResolvedLibraryByElement2_differentSession() async {
@@ -603,7 +602,7 @@
var aaaSession =
contextCollection.contextFor(aaaContextPath).currentSession;
- var result = await aaaSession.getResolvedLibraryByElement2(element);
+ var result = await aaaSession.getResolvedLibraryByElement(element);
expect(result, isA<NotElementOfThisSessionResult>());
}
@@ -614,11 +613,11 @@
''');
var unitResult =
- await session.getResolvedUnit2(testPath) as ResolvedUnitResult;
+ await session.getResolvedUnit(testPath) as ResolvedUnitResult;
expect(unitResult.session, session);
expect(unitResult.path, testPath);
expect(unitResult.uri, Uri.parse('package:test/test.dart'));
- expect(unitResult.unit!.declarations, hasLength(2));
+ expect(unitResult.unit.declarations, hasLength(2));
expect(unitResult.typeProvider, isNotNull);
expect(unitResult.libraryElement, isNotNull);
}
@@ -643,39 +642,39 @@
extension on AnalysisSession {
Future<UnitElementResult> getUnitElementValid(String path) async {
- return await getUnitElement2(path) as UnitElementResult;
+ return await getUnitElement(path) as UnitElementResult;
}
ParsedLibraryResult getParsedLibraryValid(String path) {
- return getParsedLibrary2(path) as ParsedLibraryResult;
+ return getParsedLibrary(path) as ParsedLibraryResult;
}
FileResult getFileValid(String path) {
- return getFile2(path) as FileResult;
+ return getFile(path) as FileResult;
}
ParsedUnitResult getParsedUnitValid(String path) {
- return getParsedUnit2(path) as ParsedUnitResult;
+ return getParsedUnit(path) as ParsedUnitResult;
}
Future<ResolvedLibraryResult> getResolvedLibraryValid(String path) async {
- return await getResolvedLibrary2(path) as ResolvedLibraryResult;
+ return await getResolvedLibrary(path) as ResolvedLibraryResult;
}
Future<LibraryElementResult> getLibraryByUriValid(String path) async {
- return await getLibraryByUri2(path) as LibraryElementResult;
+ return await getLibraryByUri(path) as LibraryElementResult;
}
Future<ResolvedLibraryResult> getResolvedLibraryByElementValid(
LibraryElement element) async {
- return await getResolvedLibraryByElement2(element) as ResolvedLibraryResult;
+ return await getResolvedLibraryByElement(element) as ResolvedLibraryResult;
}
ParsedLibraryResult getParsedLibraryByElementValid(LibraryElement element) {
- return getParsedLibraryByElement2(element) as ParsedLibraryResult;
+ return getParsedLibraryByElement(element) as ParsedLibraryResult;
}
Future<ErrorsResult> getErrorsValid(String path) async {
- return await getErrors2(path) as ErrorsResult;
+ return await getErrors(path) as ErrorsResult;
}
}
diff --git a/pkg/analyzer/test/src/dart/ast/element_locator_test.dart b/pkg/analyzer/test/src/dart/ast/element_locator_test.dart
index b6f51e2..c594940 100644
--- a/pkg/analyzer/test/src/dart/ast/element_locator_test.dart
+++ b/pkg/analyzer/test/src/dart/ast/element_locator_test.dart
@@ -46,7 +46,7 @@
test_locate_CompilationUnit() async {
await resolveTestCode('// only comment');
- var unitElement = result.unit!.declaredElement!;
+ var unitElement = result.unit.declaredElement!;
var element = ElementLocator.locate(result.unit);
expect(element, same(unitElement));
diff --git a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
index 40ba0f8..1db519f 100644
--- a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
+++ b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
@@ -1218,9 +1218,6 @@
var expression = findNode.topVariableDeclarationByName(name).initializer!;
var unit = this.result.unit;
- if (unit == null) {
- throw StateError('analysis result unit is null');
- }
var source = unit.declaredElement!.source;
var errorListener = GatheringErrorListener();
var errorReporter = ErrorReporter(
diff --git a/pkg/analyzer/test/src/dart/element/class_element_test.dart b/pkg/analyzer/test/src/dart/element/class_element_test.dart
index dbe96a2..c6ed690 100644
--- a/pkg/analyzer/test/src/dart/element/class_element_test.dart
+++ b/pkg/analyzer/test/src/dart/element/class_element_test.dart
@@ -3,7 +3,9 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/error/codes.dart';
+import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../resolution/context_collection_resolution.dart';
@@ -16,6 +18,132 @@
@reflectiveTest
class ClassElementTest extends PubPackageResolutionTest {
+ test_isEnumLike_false_constructors_hasFactory() async {
+ await assertNoErrorsInCode('''
+class A {
+ factory A._foo() => A._bar();
+ A._bar();
+}
+
+void f() {
+ A._foo();
+}
+''');
+ _assertIsEnumLike(findElement.class_('A'), false);
+ }
+
+ test_isEnumLike_false_constructors_hasPublic() async {
+ await assertNoErrorsInCode('''
+class A {}
+''');
+ _assertIsEnumLike(findElement.class_('A'), false);
+ }
+
+ test_isEnumLike_false_fields_empty() async {
+ await assertNoErrorsInCode('''
+class A {
+ const A._();
+}
+
+void f() {
+ A._();
+}
+''');
+ _assertIsEnumLike(findElement.class_('A'), false);
+ }
+
+ test_isEnumLike_false_isAbstract() async {
+ await assertNoErrorsInCode('''
+abstract class A {}
+''');
+ _assertIsEnumLike(findElement.class_('A'), false);
+ }
+
+ test_isEnumLike_false_isExtended() async {
+ await assertNoErrorsInCode('''
+class A {
+ static const one = A._();
+ static const two = A._();
+ const A._();
+}
+
+class B extends A {
+ B() : super._();
+}
+''');
+ _assertIsEnumLike(findElement.class_('A'), false);
+ }
+
+ test_isEnumLike_false_isMixin() async {
+ await assertNoErrorsInCode('''
+mixin M {}
+''');
+ _assertIsEnumLike(findElement.mixin('M'), false);
+ }
+
+ test_isEnumLike_true() async {
+ await assertNoErrorsInCode('''
+class A {
+ static const one = A._();
+ static const two = A._();
+ const A._();
+}
+''');
+ _assertIsEnumLike(findElement.class_('A'), true);
+ }
+
+ test_isEnumLike_true_hasInstanceField() async {
+ await assertNoErrorsInCode('''
+class A {
+ static const one = A._(1);
+ static const two = A._(2);
+ final int f;
+ const A._(this.f);
+}
+''');
+ _assertIsEnumLike(findElement.class_('A'), true);
+ }
+
+ test_isEnumLike_true_hasSuperclass() async {
+ await assertNoErrorsInCode('''
+class A {
+ const A();
+}
+
+class B extends A {
+ static const one = B._();
+ static const two = B._();
+ const B._();
+}
+''');
+ _assertIsEnumLike(findElement.class_('B'), true);
+ }
+
+ test_isEnumLike_true_hasSyntheticField() async {
+ await assertNoErrorsInCode('''
+class A {
+ static const one = A._();
+ static const two = A._();
+ const A._();
+ int get foo => 0;
+}
+''');
+ _assertIsEnumLike(findElement.class_('A'), true);
+ }
+
+ test_isEnumLike_true_isImplemented() async {
+ await assertNoErrorsInCode('''
+class A {
+ static const one = A._();
+ static const two = A._();
+ const A._();
+}
+
+class B implements A {}
+''');
+ _assertIsEnumLike(findElement.class_('A'), true);
+ }
+
test_lookUpInheritedConcreteGetter_declared() async {
await assertNoErrorsInCode('''
class A {
@@ -1196,6 +1324,10 @@
A._lookUpInheritedMethod('foo'),
);
}
+
+ static void _assertIsEnumLike(ClassElement element, bool expected) {
+ expect((element as ClassElementImpl).isEnumLike, expected);
+ }
}
extension on ClassElement {
diff --git a/pkg/analyzer/test/src/dart/element/nullability_eliminator_test.dart b/pkg/analyzer/test/src/dart/element/nullability_eliminator_test.dart
index 632677a..ff5c8f9 100644
--- a/pkg/analyzer/test/src/dart/element/nullability_eliminator_test.dart
+++ b/pkg/analyzer/test/src/dart/element/nullability_eliminator_test.dart
@@ -2,6 +2,7 @@
// 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.
+import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/element/nullability_eliminator.dart';
@@ -155,13 +156,11 @@
nullabilitySuffix: NullabilitySuffix.none,
);
expect(_typeToString(input), 'int Function()');
- expect(input.aliasElement, same(A));
- expect(input.aliasArguments!.map(_typeToString).join(', '), 'int');
+ _assertInstantiatedAlias(input, A, 'int');
var result = NullabilityEliminator.perform(typeProvider, input);
expect(_typeToString(result), 'int* Function()*');
- expect(result.aliasElement, same(A));
- expect(result.aliasArguments!.map(_typeToString).join(', '), 'int*');
+ _assertInstantiatedAlias(result, A, 'int*');
}
test_functionType_typeParameters() {
@@ -278,8 +277,7 @@
var result = NullabilityEliminator.perform(typeProvider, input);
expect(_typeToString(result), 'List<int*>*');
- expect(result.aliasElement, same(A));
- expect(result.aliasArguments!.map(_typeToString).join(', '), 'int*');
+ _assertInstantiatedAlias(result, A, 'int*');
}
test_interfaceType_int() {
@@ -333,6 +331,13 @@
_verifySame(typeProvider.voidType);
}
+ void _assertInstantiatedAlias(
+ DartType type, Element aliasElement, String aliasArguments) {
+ var alias = type.alias!;
+ expect(alias.element, same(aliasElement));
+ expect(alias.typeArguments.map(_typeToString).join(', '), aliasArguments);
+ }
+
String _typeToString(DartType type) {
return type.getDisplayString(withNullability: true);
}
diff --git a/pkg/analyzer/test/src/dart/micro/file_resolution.dart b/pkg/analyzer/test/src/dart/micro/file_resolution.dart
index ca6326b..3c85527 100644
--- a/pkg/analyzer/test/src/dart/micro/file_resolution.dart
+++ b/pkg/analyzer/test/src/dart/micro/file_resolution.dart
@@ -74,8 +74,8 @@
Future<void> resolveTestFile() async {
var path = convertPath(_testFile);
result = await resolveFile(path);
- findNode = FindNode(result.content!, result.unit!);
- findElement = FindElement(result.unit!);
+ findNode = FindNode(result.content, result.unit);
+ findElement = FindElement(result.unit);
}
void setUp() {
diff --git a/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart b/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart
index 03dd0ff..6e07a14 100644
--- a/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart
+++ b/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart
@@ -346,6 +346,29 @@
(fileResolver.byteStore as CiderCachedByteStore).testView!.length);
}
+ test_elements_export_dartCoreDynamic() async {
+ var a_path = convertPath('/workspace/dart/test/lib/a.dart');
+ newFile(a_path, content: r'''
+export 'dart:core' show dynamic;
+''');
+
+ // Analyze so that `dart:core` is linked.
+ var a_result = await resolveFile(a_path);
+
+ // Touch `dart:core` so that its element model is discarded.
+ var dartCorePath = a_result.session.uriConverter.uriToPath(
+ Uri.parse('dart:core'),
+ )!;
+ fileResolver.changeFile(dartCorePath);
+
+ // Analyze, this will read the element model for `dart:core`.
+ // There was a bug that `root::dart:core::dynamic` had no element set.
+ await assertNoErrorsInCode(r'''
+import 'a.dart' as p;
+p.dynamic f() {}
+''');
+ }
+
test_findReferences_class() async {
var aPath = convertPath('/workspace/dart/test/lib/a.dart');
newFile(aPath, content: r'''
@@ -650,34 +673,34 @@
var path = convertPath('/workspace/dart/test/lib/test.dart');
// No resolved files yet.
- expect(fileResolver.testView!.resolvedFiles, isEmpty);
+ expect(fileResolver.testView!.resolvedLibraries, isEmpty);
// No cached, will resolve once.
expect(getTestErrors().errors, hasLength(1));
- expect(fileResolver.testView!.resolvedFiles, [path]);
+ expect(fileResolver.testView!.resolvedLibraries, [path]);
// Has cached, will be not resolved again.
expect(getTestErrors().errors, hasLength(1));
- expect(fileResolver.testView!.resolvedFiles, [path]);
+ expect(fileResolver.testView!.resolvedLibraries, [path]);
// New resolver.
// Still has cached, will be not resolved.
createFileResolver();
expect(getTestErrors().errors, hasLength(1));
- expect(fileResolver.testView!.resolvedFiles, <Object>[]);
+ expect(fileResolver.testView!.resolvedLibraries, <Object>[]);
// Change the file, new resolver.
// With changed file the previously cached result cannot be used.
addTestFile('var a = c;');
createFileResolver();
expect(getTestErrors().errors, hasLength(1));
- expect(fileResolver.testView!.resolvedFiles, [path]);
+ expect(fileResolver.testView!.resolvedLibraries, [path]);
// New resolver.
// Still has cached, will be not resolved.
createFileResolver();
expect(getTestErrors().errors, hasLength(1));
- expect(fileResolver.testView!.resolvedFiles, <Object>[]);
+ expect(fileResolver.testView!.resolvedLibraries, <Object>[]);
}
test_getErrors_reuse_changeDependency() {
@@ -693,15 +716,15 @@
var path = convertPath('/workspace/dart/test/lib/test.dart');
// No resolved files yet.
- expect(fileResolver.testView!.resolvedFiles, isEmpty);
+ expect(fileResolver.testView!.resolvedLibraries, isEmpty);
// No cached, will resolve once.
expect(getTestErrors().errors, hasLength(1));
- expect(fileResolver.testView!.resolvedFiles, [path]);
+ expect(fileResolver.testView!.resolvedLibraries, [path]);
// Has cached, will be not resolved again.
expect(getTestErrors().errors, hasLength(1));
- expect(fileResolver.testView!.resolvedFiles, [path]);
+ expect(fileResolver.testView!.resolvedLibraries, [path]);
// Change the dependency, new resolver.
// The signature of the result is different.
@@ -711,13 +734,13 @@
''');
createFileResolver();
expect(getTestErrors().errors, hasLength(1));
- expect(fileResolver.testView!.resolvedFiles, [path]);
+ expect(fileResolver.testView!.resolvedLibraries, [path]);
// New resolver.
// Still has cached, will be not resolved.
createFileResolver();
expect(getTestErrors().errors, hasLength(1));
- expect(fileResolver.testView!.resolvedFiles, <Object>[]);
+ expect(fileResolver.testView!.resolvedLibraries, <Object>[]);
}
test_getLibraryByUri() {
@@ -1007,7 +1030,7 @@
}
''');
- _assertDiscoveredLibraryForParts([result.path!]);
+ _assertDiscoveredLibraryForParts([result.path]);
}
test_resolve_part_of_uri() async {
@@ -1028,7 +1051,7 @@
}
''');
- _assertDiscoveredLibraryForParts([result.path!]);
+ _assertDiscoveredLibraryForParts([result.path]);
}
test_resolveFile_cache() async {
@@ -1036,17 +1059,21 @@
newFile(path, content: 'var a = 0;');
// No resolved files yet.
- expect(fileResolver.testView!.resolvedFiles, isEmpty);
+ var testView = fileResolver.testView!;
+ expect(testView.resolvedLibraries, isEmpty);
await resolveFile2(path);
var result1 = result;
// The file was resolved.
- expect(fileResolver.testView!.resolvedFiles, [path]);
+ expect(testView.resolvedLibraries, [path]);
+
+ // The result is cached.
+ expect(fileResolver.cachedResults, contains(path));
// Ask again, no changes, not resolved.
await resolveFile2(path);
- expect(fileResolver.testView!.resolvedFiles, [path]);
+ expect(testView.resolvedLibraries, [path]);
// The same result was returned.
expect(result, same(result1));
@@ -1057,12 +1084,41 @@
// The was a change to a file, no matter which, resolve again.
await resolveFile2(path);
- expect(fileResolver.testView!.resolvedFiles, [path, path]);
+ expect(testView.resolvedLibraries, [path, path]);
// Get should get a new result.
expect(result, isNot(same(result1)));
}
+ test_resolveFile_dontCache_whenForCompletion() async {
+ var a_path = convertPath('/workspace/dart/test/lib/a.dart');
+ newFile(a_path, content: r'''
+part 'b.dart';
+''');
+
+ var b_path = convertPath('/workspace/dart/test/lib/b.dart');
+ newFile(b_path, content: r'''
+part of 'a.dart';
+''');
+
+ // No resolved files yet.
+ var testView = fileResolver.testView!;
+ expect(testView.resolvedLibraries, isEmpty);
+
+ fileResolver.resolve(
+ path: b_path,
+ completionLine: 0,
+ completionColumn: 0,
+ );
+
+ // The file was resolved.
+ expect(testView.resolvedLibraries, [a_path]);
+
+ // The completion location was set, so not units are resolved.
+ // So, the result should not be cached.
+ expect(fileResolver.cachedResults, isEmpty);
+ }
+
test_resolveLibrary() async {
var aPath = convertPath('/workspace/dart/test/lib/a.dart');
newFile(aPath, content: r'''
@@ -1084,7 +1140,7 @@
var result = fileResolver.resolveLibrary(path: aPath);
expect(result.path, aPath);
- expect(result.units?.length, 2);
+ expect(result.units.length, 2);
}
test_reuse_compatibleOptions() async {
diff --git a/pkg/analyzer/test/src/dart/resolution/ast_rewrite_test.dart b/pkg/analyzer/test/src/dart/resolution/ast_rewrite_test.dart
index 2fb3462..b2bceea 100644
--- a/pkg/analyzer/test/src/dart/resolution/ast_rewrite_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/ast_rewrite_test.dart
@@ -351,7 +351,7 @@
List<String> expectedArguments,
) {
var argumentStrings = argumentList.arguments
- .map((e) => result.content!.substring(e.offset, e.end))
+ .map((e) => result.content.substring(e.offset, e.end))
.toList();
expect(argumentStrings, expectedArguments);
}
@@ -383,7 +383,7 @@
}
var argumentStrings = argumentList.arguments
- .map((e) => result.content!.substring(e.offset, e.end))
+ .map((e) => result.content.substring(e.offset, e.end))
.toList();
expect(argumentStrings, expectedArguments);
}
diff --git a/pkg/analyzer/test/src/dart/resolution/constant_test.dart b/pkg/analyzer/test/src/dart/resolution/constant_test.dart
index 7d71d57..2e49834 100644
--- a/pkg/analyzer/test/src/dart/resolution/constant_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/constant_test.dart
@@ -214,7 +214,7 @@
result = await resolveFile(convertPath('$testPackageLibPath/a.dart'));
assertErrorsInResolvedUnit(result, []);
- var bElement = FindElement(result.unit!).field('b') as ConstVariableElement;
+ var bElement = FindElement(result.unit).field('b') as ConstVariableElement;
var bValue = bElement.evaluationResult!.value!;
var superFields = bValue.getField(GenericState.SUPERCLASS_FIELD);
expect(superFields!.getField('f1')!.toBoolValue(), false);
diff --git a/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart b/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart
index 27ec665..afc3556 100644
--- a/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart
+++ b/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart
@@ -190,7 +190,7 @@
Future<ResolvedUnitResult> resolveFile(String path) async {
var analysisContext = contextFor(pathForContextSelection ?? path);
var session = analysisContext.currentSession;
- return await session.getResolvedUnit2(path) as ResolvedUnitResult;
+ return await session.getResolvedUnit(path) as ResolvedUnitResult;
}
@mustCallSuper
diff --git a/pkg/analyzer/test/src/dart/resolution/function_reference_test.dart b/pkg/analyzer/test/src/dart/resolution/function_reference_test.dart
index 9922d73..3675f92 100644
--- a/pkg/analyzer/test/src/dart/resolution/function_reference_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/function_reference_test.dart
@@ -28,23 +28,210 @@
assertType(reference, 'dynamic');
}
- test_instanceGetter_explicitReceiver() async {
- // This test is here to assert that the resolver does not throw, but in the
- // future, an error should be reported here as well.
+ test_explicitReceiver_unknown_multipleProperties() async {
+ await assertErrorsInCode('''
+bar() {
+ a.b.foo<int>;
+}
+''', [
+ error(CompileTimeErrorCode.UNDEFINED_IDENTIFIER, 10, 1),
+ ]);
+
+ var reference = findNode.functionReference('foo<int>;');
+ assertType(reference, 'dynamic');
+ }
+
+ test_extensionGetter_extensionOverride() async {
+ await assertErrorsInCode('''
+class A {}
+
+extension E on A {
+ int get foo => 0;
+}
+
+bar(A a) {
+ E(a).foo<int>;
+}
+''', [
+ error(
+ CompileTimeErrorCode.DISALLOWED_TYPE_INSTANTIATION_EXPRESSION, 67, 8),
+ ]);
+
+ var reference = findNode.functionReference('foo<int>;');
+ assertType(reference, 'dynamic');
+ }
+
+ test_extensionMethod() async {
+ await assertNoErrorsInCode('''
+class A {}
+
+extension E on A {
+ void foo<T>(T a) {}
+
+ bar() {
+ foo<int>;
+ }
+}
+''');
+
+ var reference = findNode.functionReference('foo<int>;');
+ assertFunctionReference(
+ reference, findElement.method('foo'), 'void Function(int)');
+ }
+
+ test_extensionMethod_explicitReceiver_this() async {
+ await assertNoErrorsInCode('''
+class A {}
+
+extension E on A {
+ void foo<T>(T a) {}
+
+ bar() {
+ this.foo<int>;
+ }
+}
+''');
+
+ var reference = findNode.functionReference('foo<int>;');
+ assertFunctionReference(
+ reference, findElement.method('foo'), 'void Function(int)');
+ }
+
+ test_extensionMethod_extensionOverride() async {
await assertNoErrorsInCode('''
class A {
int foo = 0;
}
+extension E on A {
+ void foo<T>(T a) {}
+}
+
bar(A a) {
- a.foo<int>;
+ E(a).foo<int>;
}
''');
var reference = findNode.functionReference('foo<int>;');
+ assertFunctionReference(
+ reference, findElement.method('foo'), 'void Function(int)');
+ }
+
+ test_extensionMethod_extensionOverride_cascade() async {
+ await assertErrorsInCode('''
+class A {
+ int foo = 0;
+}
+
+extension E on A {
+ void foo<T>(T a) {}
+}
+
+bar(A a) {
+ E(a)..foo<int>;
+}
+''', [
+ error(CompileTimeErrorCode.EXTENSION_OVERRIDE_WITH_CASCADE, 85, 1),
+ ]);
+
+ var reference = findNode.functionReference('foo<int>;');
+ assertFunctionReference(
+ reference, findElement.method('foo'), 'void Function(int)');
+ }
+
+ test_extensionMethod_extensionOverride_static() async {
+ await assertErrorsInCode('''
+class A {}
+
+extension E on A {
+ static void foo<T>(T a) {}
+}
+
+bar(A a) {
+ E(a).foo<int>;
+}
+''', [
+ error(CompileTimeErrorCode.EXTENSION_OVERRIDE_ACCESS_TO_STATIC_MEMBER, 81,
+ 3),
+ ]);
+
+ var reference = findNode.functionReference('foo<int>;');
+ assertFunctionReference(
+ reference, findElement.method('foo'), 'void Function(int)');
+ }
+
+ test_extensionMethod_extensionOverride_unknown() async {
+ await assertErrorsInCode('''
+class A {}
+
+extension E on A {}
+
+bar(A a) {
+ E(a).foo<int>;
+}
+''', [
+ error(CompileTimeErrorCode.UNDEFINED_EXTENSION_GETTER, 51, 3),
+ ]);
+
+ var reference = findNode.functionReference('foo<int>;');
assertType(reference, 'dynamic');
}
+ test_extensionMethod_fromClassDeclaration() async {
+ await assertNoErrorsInCode('''
+class A {
+ bar() {
+ foo<int>;
+ }
+}
+
+extension E on A {
+ void foo<T>(T a) {}
+}
+''');
+
+ var reference = findNode.functionReference('foo<int>;');
+ assertFunctionReference(
+ reference, findElement.method('foo'), 'void Function(int)');
+ }
+
+ test_instanceGetter() async {
+ await assertErrorsInCode('''
+abstract class A {
+ late void Function<T>(T) foo;
+
+ bar() {
+ foo<int>;
+ }
+}
+
+''', [
+ error(
+ CompileTimeErrorCode.DISALLOWED_TYPE_INSTANTIATION_EXPRESSION, 66, 3),
+ ]);
+
+ var reference = findNode.functionReference('foo<int>;');
+ assertType(reference, 'void Function(int)');
+ }
+
+ test_instanceGetter_explicitReceiver() async {
+ await assertErrorsInCode('''
+class A {
+ late void Function<T>(T) foo;
+}
+
+bar(A a) {
+ a.foo<int>;
+}
+''', [
+ error(
+ CompileTimeErrorCode.DISALLOWED_TYPE_INSTANTIATION_EXPRESSION, 58, 5),
+ ]);
+
+ var reference = findNode.functionReference('foo<int>;');
+ assertType(reference, 'void Function(int)');
+ }
+
test_instanceMethod() async {
await assertNoErrorsInCode('''
class A {
@@ -81,6 +268,21 @@
reference, findElement.method('foo'), 'void Function(int)');
}
+ test_instanceMethod_explicitReceiver_otherExpression() async {
+ await assertNoErrorsInCode('''
+class A {
+ void foo<T>(T a) {}
+}
+
+void f(A? a, A b) {
+ (a ?? b).foo<int>;
+}
+''');
+
+ var reference = findNode.functionReference('(a ?? b).foo<int>;');
+ assertType(reference, 'void Function(int)');
+ }
+
test_instanceMethod_explicitReceiver_super() async {
await assertNoErrorsInCode('''
class A {
@@ -184,6 +386,27 @@
'void Function(int)');
}
+ test_instanceMethod_explicitReceiver_topLevelVariable_prefix_unknown() async {
+ newFile('$testPackageLibPath/a.dart', content: '''
+class A {}
+var a = A();
+''');
+ await assertErrorsInCode('''
+import 'a.dart' as prefix;
+
+bar() {
+ prefix.a.foo<int>;
+}
+''', [
+ error(CompileTimeErrorCode.UNDEFINED_GETTER, 47, 3),
+ ]);
+
+ assertImportPrefix(
+ findNode.simple('prefix.'), findElement.prefix('prefix'));
+ var reference = findNode.functionReference('foo<int>;');
+ assertType(reference, 'dynamic');
+ }
+
test_instanceMethod_explicitReceiver_typeParameter() async {
await assertErrorsInCode('''
bar<T>() {
@@ -213,6 +436,55 @@
reference, findElement.method('foo'), 'void Function(int)');
}
+ test_instanceMethod_explicitReceiver_variable_cascade() async {
+ await assertNoErrorsInCode('''
+class A {
+ void foo<T>(T a) {}
+}
+
+bar(A a) {
+ a..foo<int>;
+}
+''');
+
+ var reference = findNode.functionReference('foo<int>;');
+ assertFunctionReference(
+ reference, findElement.method('foo'), 'void Function(int)');
+ }
+
+ test_instanceMethod_inherited() async {
+ await assertNoErrorsInCode('''
+class A {
+ void foo<T>(T a) {}
+}
+
+class B extends A {
+ bar() {
+ foo<int>;
+ }
+}
+''');
+
+ var reference = findNode.functionReference('foo<int>;');
+ assertFunctionReference(
+ reference, findElement.method('foo'), 'void Function(int)');
+ }
+
+ test_instanceMethod_unknown() async {
+ await assertErrorsInCode('''
+class A {
+ bar() {
+ foo<int>;
+ }
+}
+''', [
+ error(CompileTimeErrorCode.UNDEFINED_METHOD, 24, 3),
+ ]);
+
+ var reference = findNode.functionReference('foo<int>;');
+ assertType(reference, 'dynamic');
+ }
+
test_localFunction() async {
await assertNoErrorsInCode('''
void bar() {
@@ -228,11 +500,29 @@
}
test_localVariable() async {
- await assertNoErrorsInCode('''
+ await assertErrorsInCode('''
void bar(void Function<T>(T a) foo) {
foo<int>;
}
-''');
+''', [
+ error(
+ CompileTimeErrorCode.DISALLOWED_TYPE_INSTANTIATION_EXPRESSION, 40, 3),
+ ]);
+
+ var reference = findNode.functionReference('foo<int>;');
+ assertFunctionReference(
+ reference, findElement.parameter('foo'), 'void Function(int)');
+ }
+
+ test_localVariable_typeVariable() async {
+ await assertErrorsInCode('''
+void bar<T extends void Function<U>(U)>(T foo) {
+ foo<int>;
+}
+''', [
+ error(
+ CompileTimeErrorCode.DISALLOWED_TYPE_INSTANTIATION_EXPRESSION, 51, 3),
+ ]);
var reference = findNode.functionReference('foo<int>;');
assertFunctionReference(
@@ -258,6 +548,40 @@
reference, findElement.method('foo'), 'void Function()');
}
+ test_otherExpression() async {
+ await assertErrorsInCode('''
+void f(void Function<T>(T a) foo, void Function<T>(T a) bar) {
+ (1 == 2 ? foo : bar)<int>;
+}
+''', [
+ error(CompileTimeErrorCode.DISALLOWED_TYPE_INSTANTIATION_EXPRESSION, 65,
+ 20),
+ ]);
+
+ var reference = findNode.functionReference('(1 == 2 ? foo : bar)<int>;');
+ assertType(reference, 'void Function(int)');
+ }
+
+ test_otherExpression_wrongNumberOfTypeArguments() async {
+ await assertErrorsInCode('''
+void f(void Function<T>(T a) foo, void Function<T>(T a) bar) {
+ (1 == 2 ? foo : bar)<int, String>;
+}
+''', [
+ error(CompileTimeErrorCode.DISALLOWED_TYPE_INSTANTIATION_EXPRESSION, 65,
+ 20),
+ error(
+ CompileTimeErrorCode
+ .WRONG_NUMBER_OF_TYPE_ARGUMENTS_ANONYMOUS_FUNCTION,
+ 85,
+ 13),
+ ]);
+
+ var reference =
+ findNode.functionReference('(1 == 2 ? foo : bar)<int, String>;');
+ assertType(reference, 'void Function(dynamic)');
+ }
+
test_staticMethod() async {
await assertNoErrorsInCode('''
class A {
@@ -453,6 +777,37 @@
);
}
+ test_topLevelFunction_prefix_unknownPrefix() async {
+ await assertErrorsInCode('''
+bar() {
+ prefix.foo<int>;
+}
+''', [
+ error(CompileTimeErrorCode.UNDEFINED_IDENTIFIER, 10, 6),
+ ]);
+
+ var reference = findNode.functionReference('foo<int>;');
+ assertType(reference, 'dynamic');
+ }
+
+ test_topLevelVariable_prefix_unknownIdentifier() async {
+ newFile('$testPackageLibPath/a.dart', content: '');
+ await assertErrorsInCode('''
+import 'a.dart' as prefix;
+
+bar() {
+ prefix.a.foo<int>;
+}
+''', [
+ error(CompileTimeErrorCode.UNDEFINED_PREFIXED_NAME, 45, 1),
+ ]);
+
+ assertImportPrefix(
+ findNode.simple('prefix.'), findElement.prefix('prefix'));
+ var reference = findNode.functionReference('foo<int>;');
+ assertType(reference, 'dynamic');
+ }
+
test_typeAlias_function_unknownProperty() async {
await assertErrorsInCode('''
typedef Cb = void Function();
diff --git a/pkg/analyzer/test/src/dart/resolution/instance_creation_test.dart b/pkg/analyzer/test/src/dart/resolution/instance_creation_test.dart
index 206f003..4d27277 100644
--- a/pkg/analyzer/test/src/dart/resolution/instance_creation_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/instance_creation_test.dart
@@ -2,6 +2,7 @@
// 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.
+import 'package:analyzer/src/dart/error/syntactic_errors.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -10,6 +11,7 @@
main() {
defineReflectiveSuite(() {
defineReflectiveTests(InstanceCreationTest);
+ defineReflectiveTests(InstanceCreationWithoutConstructorTearoffsTest);
});
}
@@ -426,4 +428,75 @@
expectedSubstitution: {'T': 'String'},
);
}
+
+ test_unnamed_declaredNew() async {
+ await assertNoErrorsInCode('''
+class A {
+ A.new(int a);
+}
+
+void f() {
+ A(0);
+}
+
+''');
+
+ var creation = findNode.instanceCreation('A(0)');
+ assertInstanceCreation(creation, findElement.class_('A'), 'A');
+ }
+
+ test_unnamedViaNew_declaredNew() async {
+ await assertNoErrorsInCode('''
+class A {
+ A.new(int a);
+}
+
+void f() {
+ A.new(0);
+}
+
+''');
+
+ var creation = findNode.instanceCreation('A.new(0)');
+ assertInstanceCreation(creation, findElement.class_('A'), 'A');
+ }
+
+ test_unnamedViaNew_declaredUnnamed() async {
+ await assertNoErrorsInCode('''
+class A {
+ A(int a);
+}
+
+void f() {
+ A.new(0);
+}
+
+''');
+
+ var creation = findNode.instanceCreation('A.new(0)');
+ assertInstanceCreation(creation, findElement.class_('A'), 'A');
+ }
+}
+
+@reflectiveTest
+class InstanceCreationWithoutConstructorTearoffsTest
+ extends PubPackageResolutionTest with WithoutConstructorTearoffsMixin {
+ test_unnamedViaNew() async {
+ await assertErrorsInCode('''
+class A {
+ A(int a);
+}
+
+void f() {
+ A.new(0);
+}
+
+''', [
+ error(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 40, 3),
+ ]);
+
+ // Resolution should continue even though the experiment is not enabled.
+ var creation = findNode.instanceCreation('A.new(0)');
+ assertInstanceCreation(creation, findElement.class_('A'), 'A');
+ }
}
diff --git a/pkg/analyzer/test/src/dart/resolution/local_variable_test.dart b/pkg/analyzer/test/src/dart/resolution/local_variable_test.dart
index 213fbbb..ddad876 100644
--- a/pkg/analyzer/test/src/dart/resolution/local_variable_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/local_variable_test.dart
@@ -11,7 +11,6 @@
main() {
defineReflectiveSuite(() {
defineReflectiveTests(LocalVariableResolutionTest);
- defineReflectiveTests(LocalVariableResolutionWithNullSafetyTest);
});
}
@@ -95,11 +94,7 @@
expect(x.isLate, isFalse);
expect(x.isStatic, isFalse);
}
-}
-@reflectiveTest
-class LocalVariableResolutionWithNullSafetyTest
- extends LocalVariableResolutionTest with WithNullSafetyMixin {
test_element_late() async {
await assertErrorsInCode(r'''
void f() {
diff --git a/pkg/analyzer/test/src/dart/resolution/macro_test.dart b/pkg/analyzer/test/src/dart/resolution/macro_test.dart
new file mode 100644
index 0000000..4dd8ebc
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/resolution/macro_test.dart
@@ -0,0 +1,47 @@
+// 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.
+
+import 'package:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../../generated/elements_types_mixin.dart';
+import 'context_collection_resolution.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(MacroResolutionTest);
+ });
+}
+
+@reflectiveTest
+class MacroResolutionTest extends PubPackageResolutionTest
+ with ElementsTypesMixin {
+ @override
+ void setUp() {
+ super.setUp();
+
+ newFile('$testPackageLibPath/macro_annotations.dart', content: r'''
+library analyzer.macro.annotations;
+const observable = 0;
+''');
+ }
+
+ test_observable() async {
+ await assertErrorsInCode(r'''
+import 'macro_annotations.dart';
+
+class A {
+ @observable
+ int _foo = 0;
+}
+
+void f(A a) {
+ a.foo;
+ a.foo = 2;
+}
+''', [
+ error(HintCode.UNUSED_FIELD, 64, 4),
+ ]);
+ }
+}
diff --git a/pkg/analyzer/test/src/dart/resolution/optional_const_test.dart b/pkg/analyzer/test/src/dart/resolution/optional_const_test.dart
index e32e7e8..daa949c 100644
--- a/pkg/analyzer/test/src/dart/resolution/optional_const_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/optional_const_test.dart
@@ -152,7 +152,7 @@
}
void _fillLibraries([LibraryElement? library]) {
- library ??= result.unit!.declaredElement!.library;
+ library ??= result.unit.declaredElement!.library;
var uriStr = library.source.uri.toString();
if (!libraries.containsKey(uriStr)) {
libraries[uriStr] = library;
diff --git a/pkg/analyzer/test/src/dart/resolution/postfix_expression_test.dart b/pkg/analyzer/test/src/dart/resolution/postfix_expression_test.dart
index 094323e..2c5f443 100644
--- a/pkg/analyzer/test/src/dart/resolution/postfix_expression_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/postfix_expression_test.dart
@@ -12,13 +12,298 @@
main() {
defineReflectiveSuite(() {
defineReflectiveTests(PostfixExpressionResolutionTest);
- defineReflectiveTests(PostfixExpressionResolutionWithNullSafetyTest);
+ defineReflectiveTests(PostfixExpressionResolutionWithoutNullSafetyTest);
});
}
@reflectiveTest
class PostfixExpressionResolutionTest extends PubPackageResolutionTest
- with WithoutNullSafetyMixin {
+ with PostfixExpressionResolutionTestCases {
+ test_inc_propertyAccess_nullShorting() async {
+ await assertNoErrorsInCode(r'''
+class A {
+ int foo = 0;
+}
+
+void f(A? a) {
+ a?.foo++;
+}
+''');
+
+ assertPostfixExpression(
+ findNode.postfix('foo++'),
+ readElement: findElement.getter('foo'),
+ readType: 'int',
+ writeElement: findElement.setter('foo'),
+ writeType: 'int',
+ element: numElement.getMethod('+'),
+ type: 'int?',
+ );
+ }
+
+ test_inc_simpleIdentifier_parameter_depromote() async {
+ await assertNoErrorsInCode(r'''
+class A {
+ Object operator +(int _) => this;
+}
+
+void f(Object x) {
+ if (x is A) {
+ x++;
+ x; // ref
+ }
+}
+''');
+
+ if (hasAssignmentLeftResolution) {
+ assertType(findNode.simple('x++;'), 'A');
+ }
+
+ assertPostfixExpression(
+ findNode.postfix('x++'),
+ readElement: findElement.parameter('x'),
+ readType: 'A',
+ writeElement: findElement.parameter('x'),
+ writeType: 'Object',
+ element: findElement.method('+'),
+ type: 'A',
+ );
+
+ assertType(findNode.simple('x; // ref'), 'Object');
+ }
+
+ test_nullCheck() async {
+ await assertNoErrorsInCode(r'''
+void f(int? x) {
+ x!;
+}
+''');
+
+ assertPostfixExpression(
+ findNode.postfix('x!'),
+ readElement: null,
+ readType: null,
+ writeElement: null,
+ writeType: null,
+ element: null,
+ type: 'int',
+ );
+ }
+
+ test_nullCheck_functionExpressionInvocation_rewrite() async {
+ await assertNoErrorsInCode(r'''
+void f(Function f2) {
+ f2(42)!;
+}
+''');
+ }
+
+ test_nullCheck_indexExpression() async {
+ await assertNoErrorsInCode(r'''
+void f(Map<String, int> a) {
+ int v = a['foo']!;
+ v;
+}
+''');
+
+ assertIndexExpression(
+ findNode.index('a['),
+ readElement: elementMatcher(
+ mapElement.getMethod('[]'),
+ substitution: {'K': 'String', 'V': 'int'},
+ ),
+ writeElement: null,
+ type: 'int?',
+ );
+
+ assertPostfixExpression(
+ findNode.postfix(']!'),
+ readElement: null,
+ readType: null,
+ writeElement: null,
+ writeType: null,
+ element: null,
+ type: 'int',
+ );
+ }
+
+ test_nullCheck_null() async {
+ await assertErrorsInCode('''
+void f(Null x) {
+ x!;
+}
+''', [
+ error(HintCode.NULL_CHECK_ALWAYS_FAILS, 19, 2),
+ ]);
+
+ assertType(findNode.postfix('x!'), 'Never');
+ }
+
+ test_nullCheck_nullableContext() async {
+ await assertNoErrorsInCode(r'''
+T f<T>(T t) => t;
+
+int g() => f(null)!;
+''');
+
+ assertMethodInvocation2(
+ findNode.methodInvocation('f(null)'),
+ element: findElement.topFunction('f'),
+ typeArgumentTypes: ['int?'],
+ invokeType: 'int? Function(int?)',
+ type: 'int?',
+ );
+
+ assertPostfixExpression(
+ findNode.postfix('f(null)!'),
+ readElement: null,
+ readType: null,
+ writeElement: null,
+ writeType: null,
+ element: null,
+ type: 'int',
+ );
+ }
+
+ /// See https://github.com/dart-lang/language/issues/1163
+ test_nullCheck_participatesNullShorting() async {
+ await assertErrorsInCode('''
+class A {
+ int zero;
+ int? zeroOrNull;
+
+ A(this.zero, [this.zeroOrNull]);
+}
+
+void test1(A? a) => a?.zero!;
+void test2(A? a) => a?.zeroOrNull!;
+void test3(A? a) => a?.zero!.isEven;
+void test4(A? a) => a?.zeroOrNull!.isEven;
+
+class Foo {
+ Bar? bar;
+
+ Foo(this.bar);
+
+ Bar? operator [](int? index) => null;
+}
+
+class Bar {
+ int baz;
+
+ Bar(this.baz);
+
+ int operator [](int index) => index;
+}
+
+void test5(Foo? foo) => foo?.bar!;
+void test6(Foo? foo) => foo?.bar!.baz;
+void test7(Foo? foo, int a) => foo?.bar![a];
+void test8(Foo? foo, int? a) => foo?[a]!;
+void test9(Foo? foo, int? a) => foo?[a]!.baz;
+void test10(Foo? foo, int? a, int b) => foo?[a]![b];
+''', [
+ error(StaticWarningCode.UNNECESSARY_NON_NULL_ASSERTION, 107, 1),
+ error(StaticWarningCode.UNNECESSARY_NON_NULL_ASSERTION, 173, 1),
+ ]);
+
+ void assertTestType(int index, String expected) {
+ var function = findNode.functionDeclaration('test$index(');
+ var body = function.functionExpression.body as ExpressionFunctionBody;
+ assertType(body.expression, expected);
+ }
+
+ assertTestType(1, 'int?');
+ assertTestType(2, 'int?');
+ assertTestType(3, 'bool?');
+ assertTestType(4, 'bool?');
+
+ assertTestType(5, 'Bar?');
+ assertTestType(6, 'int?');
+ assertTestType(7, 'int?');
+ assertTestType(8, 'Bar?');
+ assertTestType(9, 'int?');
+ assertTestType(10, 'int?');
+ }
+
+ test_nullCheck_superExpression() async {
+ await assertErrorsInCode(r'''
+class A {
+ int foo() => 0;
+}
+
+class B extends A {
+ void bar() {
+ super!.foo();
+ }
+}
+''', [
+ error(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 70, 6),
+ ]);
+
+ assertTypeDynamic(findNode.super_('super!'));
+
+ assertPostfixExpression(
+ findNode.postfix('super!'),
+ readElement: null,
+ readType: null,
+ writeElement: null,
+ writeType: null,
+ element: null,
+ type: 'dynamic',
+ );
+
+ assertMethodInvocation2(
+ findNode.methodInvocation('foo();'),
+ element: null,
+ typeArgumentTypes: [],
+ invokeType: 'dynamic',
+ type: 'dynamic',
+ );
+ }
+
+ test_nullCheck_typeParameter() async {
+ await assertNoErrorsInCode(r'''
+void f<T>(T? x) {
+ x!;
+}
+''');
+
+ var postfixExpression = findNode.postfix('x!');
+ assertPostfixExpression(
+ postfixExpression,
+ readElement: null,
+ readType: null,
+ writeElement: null,
+ writeType: null,
+ element: null,
+ type: 'T & Object',
+ );
+ }
+
+ test_nullCheck_typeParameter_already_promoted() async {
+ await assertNoErrorsInCode('''
+void f<T>(T? x) {
+ if (x is num?) {
+ x!;
+ }
+}
+''');
+
+ var postfixExpression = findNode.postfix('x!');
+ assertPostfixExpression(
+ postfixExpression,
+ readElement: null,
+ readType: null,
+ writeElement: null,
+ writeType: null,
+ element: null,
+ type: 'T & num',
+ );
+ }
+}
+
+mixin PostfixExpressionResolutionTestCases on PubPackageResolutionTest {
test_dec_simpleIdentifier_parameter_int() async {
await assertNoErrorsInCode(r'''
void f(int x) {
@@ -484,288 +769,6 @@
}
@reflectiveTest
-class PostfixExpressionResolutionWithNullSafetyTest
- extends PostfixExpressionResolutionTest with WithNullSafetyMixin {
- test_inc_propertyAccess_nullShorting() async {
- await assertNoErrorsInCode(r'''
-class A {
- int foo = 0;
-}
-
-void f(A? a) {
- a?.foo++;
-}
-''');
-
- assertPostfixExpression(
- findNode.postfix('foo++'),
- readElement: findElement.getter('foo'),
- readType: 'int',
- writeElement: findElement.setter('foo'),
- writeType: 'int',
- element: numElement.getMethod('+'),
- type: 'int?',
- );
- }
-
- test_inc_simpleIdentifier_parameter_depromote() async {
- await assertNoErrorsInCode(r'''
-class A {
- Object operator +(int _) => this;
-}
-
-void f(Object x) {
- if (x is A) {
- x++;
- x; // ref
- }
-}
-''');
-
- if (hasAssignmentLeftResolution) {
- assertType(findNode.simple('x++;'), 'A');
- }
-
- assertPostfixExpression(
- findNode.postfix('x++'),
- readElement: findElement.parameter('x'),
- readType: 'A',
- writeElement: findElement.parameter('x'),
- writeType: 'Object',
- element: findElement.method('+'),
- type: 'A',
- );
-
- assertType(findNode.simple('x; // ref'), 'Object');
- }
-
- test_nullCheck() async {
- await assertNoErrorsInCode(r'''
-void f(int? x) {
- x!;
-}
-''');
-
- assertPostfixExpression(
- findNode.postfix('x!'),
- readElement: null,
- readType: null,
- writeElement: null,
- writeType: null,
- element: null,
- type: 'int',
- );
- }
-
- test_nullCheck_functionExpressionInvocation_rewrite() async {
- await assertNoErrorsInCode(r'''
-void f(Function f2) {
- f2(42)!;
-}
-''');
- }
-
- test_nullCheck_indexExpression() async {
- await assertNoErrorsInCode(r'''
-void f(Map<String, int> a) {
- int v = a['foo']!;
- v;
-}
-''');
-
- assertIndexExpression(
- findNode.index('a['),
- readElement: elementMatcher(
- mapElement.getMethod('[]'),
- substitution: {'K': 'String', 'V': 'int'},
- ),
- writeElement: null,
- type: 'int?',
- );
-
- assertPostfixExpression(
- findNode.postfix(']!'),
- readElement: null,
- readType: null,
- writeElement: null,
- writeType: null,
- element: null,
- type: 'int',
- );
- }
-
- test_nullCheck_null() async {
- await assertErrorsInCode('''
-void f(Null x) {
- x!;
-}
-''', [
- error(HintCode.NULL_CHECK_ALWAYS_FAILS, 19, 2),
- ]);
-
- assertType(findNode.postfix('x!'), 'Never');
- }
-
- test_nullCheck_nullableContext() async {
- await assertNoErrorsInCode(r'''
-T f<T>(T t) => t;
-
-int g() => f(null)!;
-''');
-
- assertMethodInvocation2(
- findNode.methodInvocation('f(null)'),
- element: findElement.topFunction('f'),
- typeArgumentTypes: ['int?'],
- invokeType: 'int? Function(int?)',
- type: 'int?',
- );
-
- assertPostfixExpression(
- findNode.postfix('f(null)!'),
- readElement: null,
- readType: null,
- writeElement: null,
- writeType: null,
- element: null,
- type: 'int',
- );
- }
-
- /// See https://github.com/dart-lang/language/issues/1163
- test_nullCheck_participatesNullShorting() async {
- await assertErrorsInCode('''
-class A {
- int zero;
- int? zeroOrNull;
-
- A(this.zero, [this.zeroOrNull]);
-}
-
-void test1(A? a) => a?.zero!;
-void test2(A? a) => a?.zeroOrNull!;
-void test3(A? a) => a?.zero!.isEven;
-void test4(A? a) => a?.zeroOrNull!.isEven;
-
-class Foo {
- Bar? bar;
-
- Foo(this.bar);
-
- Bar? operator [](int? index) => null;
-}
-
-class Bar {
- int baz;
-
- Bar(this.baz);
-
- int operator [](int index) => index;
-}
-
-void test5(Foo? foo) => foo?.bar!;
-void test6(Foo? foo) => foo?.bar!.baz;
-void test7(Foo? foo, int a) => foo?.bar![a];
-void test8(Foo? foo, int? a) => foo?[a]!;
-void test9(Foo? foo, int? a) => foo?[a]!.baz;
-void test10(Foo? foo, int? a, int b) => foo?[a]![b];
-''', [
- error(StaticWarningCode.UNNECESSARY_NON_NULL_ASSERTION, 107, 1),
- error(StaticWarningCode.UNNECESSARY_NON_NULL_ASSERTION, 173, 1),
- ]);
-
- void assertTestType(int index, String expected) {
- var function = findNode.functionDeclaration('test$index(');
- var body = function.functionExpression.body as ExpressionFunctionBody;
- assertType(body.expression, expected);
- }
-
- assertTestType(1, 'int?');
- assertTestType(2, 'int?');
- assertTestType(3, 'bool?');
- assertTestType(4, 'bool?');
-
- assertTestType(5, 'Bar?');
- assertTestType(6, 'int?');
- assertTestType(7, 'int?');
- assertTestType(8, 'Bar?');
- assertTestType(9, 'int?');
- assertTestType(10, 'int?');
- }
-
- test_nullCheck_superExpression() async {
- await assertErrorsInCode(r'''
-class A {
- int foo() => 0;
-}
-
-class B extends A {
- void bar() {
- super!.foo();
- }
-}
-''', [
- error(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 70, 6),
- ]);
-
- assertTypeDynamic(findNode.super_('super!'));
-
- assertPostfixExpression(
- findNode.postfix('super!'),
- readElement: null,
- readType: null,
- writeElement: null,
- writeType: null,
- element: null,
- type: 'dynamic',
- );
-
- assertMethodInvocation2(
- findNode.methodInvocation('foo();'),
- element: null,
- typeArgumentTypes: [],
- invokeType: 'dynamic',
- type: 'dynamic',
- );
- }
-
- test_nullCheck_typeParameter() async {
- await assertNoErrorsInCode(r'''
-void f<T>(T? x) {
- x!;
-}
-''');
-
- var postfixExpression = findNode.postfix('x!');
- assertPostfixExpression(
- postfixExpression,
- readElement: null,
- readType: null,
- writeElement: null,
- writeType: null,
- element: null,
- type: 'T & Object',
- );
- }
-
- test_nullCheck_typeParameter_already_promoted() async {
- await assertNoErrorsInCode('''
-void f<T>(T? x) {
- if (x is num?) {
- x!;
- }
-}
-''');
-
- var postfixExpression = findNode.postfix('x!');
- assertPostfixExpression(
- postfixExpression,
- readElement: null,
- readType: null,
- writeElement: null,
- writeType: null,
- element: null,
- type: 'T & num',
- );
- }
-}
+class PostfixExpressionResolutionWithoutNullSafetyTest
+ extends PubPackageResolutionTest
+ with PostfixExpressionResolutionTestCases, WithoutNullSafetyMixin {}
diff --git a/pkg/analyzer/test/src/dart/resolution/prefix_expression_test.dart b/pkg/analyzer/test/src/dart/resolution/prefix_expression_test.dart
index 06fd33d..1fa6d56 100644
--- a/pkg/analyzer/test/src/dart/resolution/prefix_expression_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/prefix_expression_test.dart
@@ -12,13 +12,140 @@
main() {
defineReflectiveSuite(() {
defineReflectiveTests(PrefixExpressionResolutionTest);
- defineReflectiveTests(PrefixExpressionResolutionWithNullSafetyTest);
+ defineReflectiveTests(PrefixExpressionResolutionWithoutNullSafetyTest);
});
}
@reflectiveTest
class PrefixExpressionResolutionTest extends PubPackageResolutionTest
- with WithoutNullSafetyMixin {
+ with PrefixExpressionResolutionTestCases {
+ test_bang_no_nullShorting() async {
+ await assertErrorsInCode(r'''
+class A {
+ bool get foo => true;
+}
+
+void f(A? a) {
+ !a?.foo;
+}
+''', [
+ error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE_AS_CONDITION,
+ 55, 6),
+ ]);
+
+ assertPrefixExpression(
+ findNode.prefix('!a'),
+ readElement: null,
+ readType: null,
+ writeElement: null,
+ writeType: null,
+ element: boolElement.getMethod('!'),
+ type: 'bool',
+ );
+ }
+
+ test_minus_no_nullShorting() async {
+ await assertErrorsInCode(r'''
+class A {
+ int get foo => 0;
+}
+
+void f(A? a) {
+ -a?.foo;
+}
+''', [
+ error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
+ 50, 1),
+ ]);
+
+ assertPrefixExpression(
+ findNode.prefix('-a'),
+ readElement: null,
+ readType: null,
+ writeElement: null,
+ writeType: null,
+ element: intElement.getMethod('unary-'),
+ type: 'int',
+ );
+ }
+
+ test_plusPlus_depromote() async {
+ await assertNoErrorsInCode(r'''
+class A {
+ Object operator +(int _) => this;
+}
+
+void f(Object x) {
+ if (x is A) {
+ ++x;
+ }
+}
+''');
+
+ assertPrefixExpression(
+ findNode.prefix('++x'),
+ readElement: findElement.parameter('x'),
+ readType: 'A',
+ writeElement: findElement.parameter('x'),
+ writeType: 'Object',
+ element: findElement.method('+'),
+ type: 'Object',
+ );
+
+ if (hasAssignmentLeftResolution) {
+ assertType(findNode.simple('x;'), 'A');
+ }
+ }
+
+ test_plusPlus_nullShorting() async {
+ await assertNoErrorsInCode(r'''
+class A {
+ int foo = 0;
+}
+
+void f(A? a) {
+ ++a?.foo;
+}
+''');
+
+ assertPrefixExpression(
+ findNode.prefix('++a'),
+ readElement: findElement.getter('foo'),
+ readType: 'int',
+ writeElement: findElement.setter('foo'),
+ writeType: 'int',
+ element: numElement.getMethod('+'),
+ type: 'int?',
+ );
+ }
+
+ test_tilde_no_nullShorting() async {
+ await assertErrorsInCode(r'''
+class A {
+ int get foo => 0;
+}
+
+void f(A? a) {
+ ~a?.foo;
+}
+''', [
+ error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
+ 50, 1),
+ ]);
+
+ assertPrefixExpression(
+ findNode.prefix('~a'),
+ readElement: null,
+ readType: null,
+ writeElement: null,
+ writeType: null,
+ element: intElement.getMethod('~'),
+ type: 'int',
+ );
+ }
+}
+
+mixin PrefixExpressionResolutionTestCases on PubPackageResolutionTest {
test_bang_bool_context() async {
await assertNoErrorsInCode(r'''
T f<T>() {
@@ -637,130 +764,6 @@
}
@reflectiveTest
-class PrefixExpressionResolutionWithNullSafetyTest
- extends PrefixExpressionResolutionTest with WithNullSafetyMixin {
- test_bang_no_nullShorting() async {
- await assertErrorsInCode(r'''
-class A {
- bool get foo => true;
-}
-
-void f(A? a) {
- !a?.foo;
-}
-''', [
- error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE_AS_CONDITION,
- 55, 6),
- ]);
-
- assertPrefixExpression(
- findNode.prefix('!a'),
- readElement: null,
- readType: null,
- writeElement: null,
- writeType: null,
- element: boolElement.getMethod('!'),
- type: 'bool',
- );
- }
-
- test_minus_no_nullShorting() async {
- await assertErrorsInCode(r'''
-class A {
- int get foo => 0;
-}
-
-void f(A? a) {
- -a?.foo;
-}
-''', [
- error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
- 50, 1),
- ]);
-
- assertPrefixExpression(
- findNode.prefix('-a'),
- readElement: null,
- readType: null,
- writeElement: null,
- writeType: null,
- element: intElement.getMethod('unary-'),
- type: 'int',
- );
- }
-
- test_plusPlus_depromote() async {
- await assertNoErrorsInCode(r'''
-class A {
- Object operator +(int _) => this;
-}
-
-void f(Object x) {
- if (x is A) {
- ++x;
- }
-}
-''');
-
- assertPrefixExpression(
- findNode.prefix('++x'),
- readElement: findElement.parameter('x'),
- readType: 'A',
- writeElement: findElement.parameter('x'),
- writeType: 'Object',
- element: findElement.method('+'),
- type: 'Object',
- );
-
- if (hasAssignmentLeftResolution) {
- assertType(findNode.simple('x;'), 'A');
- }
- }
-
- test_plusPlus_nullShorting() async {
- await assertNoErrorsInCode(r'''
-class A {
- int foo = 0;
-}
-
-void f(A? a) {
- ++a?.foo;
-}
-''');
-
- assertPrefixExpression(
- findNode.prefix('++a'),
- readElement: findElement.getter('foo'),
- readType: 'int',
- writeElement: findElement.setter('foo'),
- writeType: 'int',
- element: numElement.getMethod('+'),
- type: 'int?',
- );
- }
-
- test_tilde_no_nullShorting() async {
- await assertErrorsInCode(r'''
-class A {
- int get foo => 0;
-}
-
-void f(A? a) {
- ~a?.foo;
-}
-''', [
- error(CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE,
- 50, 1),
- ]);
-
- assertPrefixExpression(
- findNode.prefix('~a'),
- readElement: null,
- readType: null,
- writeElement: null,
- writeType: null,
- element: intElement.getMethod('~'),
- type: 'int',
- );
- }
-}
+class PrefixExpressionResolutionWithoutNullSafetyTest
+ extends PubPackageResolutionTest
+ with PrefixExpressionResolutionTestCases, WithoutNullSafetyMixin {}
diff --git a/pkg/analyzer/test/src/dart/resolution/property_access_test.dart b/pkg/analyzer/test/src/dart/resolution/property_access_test.dart
index b95d627..e3ef89b 100644
--- a/pkg/analyzer/test/src/dart/resolution/property_access_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/property_access_test.dart
@@ -11,13 +11,168 @@
main() {
defineReflectiveSuite(() {
defineReflectiveTests(PropertyAccessResolutionTest);
- defineReflectiveTests(PropertyAccessResolutionWithNullSafetyTest);
+ defineReflectiveTests(PropertyAccessResolutionWithoutNullSafetyTest);
});
}
@reflectiveTest
class PropertyAccessResolutionTest extends PubPackageResolutionTest
- with WithoutNullSafetyMixin {
+ with PropertyAccessResolutionTestCases {
+ test_implicitCall_tearOff_nullable() async {
+ await assertErrorsInCode('''
+class A {
+ int call() => 0;
+}
+
+class B {
+ A? a;
+}
+
+int Function() foo() {
+ return B().a; // ref
+}
+''', [
+ error(CompileTimeErrorCode.RETURN_OF_INVALID_TYPE_FROM_FUNCTION, 85, 5),
+ ]);
+
+ var identifier = findNode.simple('a; // ref');
+ assertElement(identifier, findElement.getter('a'));
+ assertType(identifier, 'A?');
+ }
+
+ test_nullShorting_cascade() async {
+ await assertNoErrorsInCode(r'''
+class A {
+ int get foo => 0;
+ int get bar => 0;
+}
+
+void f(A? a) {
+ a?..foo..bar;
+}
+''');
+
+ assertPropertyAccess2(
+ findNode.propertyAccess('..foo'),
+ element: findElement.getter('foo'),
+ type: 'int',
+ );
+
+ assertPropertyAccess2(
+ findNode.propertyAccess('..bar'),
+ element: findElement.getter('bar'),
+ type: 'int',
+ );
+
+ assertType(findNode.cascade('a?'), 'A?');
+ }
+
+ test_nullShorting_cascade2() async {
+ await assertNoErrorsInCode(r'''
+class A {
+ int? get foo => 0;
+}
+
+main() {
+ A a = A()..foo?.isEven;
+ a;
+}
+''');
+
+ assertPropertyAccess2(
+ findNode.propertyAccess('..foo?'),
+ element: findElement.getter('foo'),
+ type: 'int?',
+ );
+
+ assertPropertyAccess2(
+ findNode.propertyAccess('.isEven'),
+ element: intElement.getGetter('isEven'),
+ type: 'bool',
+ );
+
+ assertType(findNode.cascade('A()'), 'A');
+ }
+
+ test_nullShorting_cascade3() async {
+ await assertNoErrorsInCode(r'''
+class A {
+ A? get foo => this;
+ A? get bar => this;
+ A? get baz => this;
+}
+
+main() {
+ A a = A()..foo?.bar?.baz;
+ a;
+}
+''');
+
+ assertPropertyAccess2(
+ findNode.propertyAccess('.foo'),
+ element: findElement.getter('foo'),
+ type: 'A?',
+ );
+
+ assertPropertyAccess2(
+ findNode.propertyAccess('.bar'),
+ element: findElement.getter('bar'),
+ type: 'A?',
+ );
+
+ assertPropertyAccess2(
+ findNode.propertyAccess('.baz'),
+ element: findElement.getter('baz'),
+ type: 'A?',
+ );
+
+ assertType(findNode.cascade('A()'), 'A');
+ }
+
+ test_nullShorting_cascade4() async {
+ await assertNoErrorsInCode(r'''
+A? get foo => A();
+
+class A {
+ A get bar => this;
+ A? get baz => this;
+ A get baq => this;
+}
+
+main() {
+ foo?.bar?..baz?.baq;
+}
+''');
+
+ assertSimpleIdentifier(
+ findNode.simple('foo?'),
+ element: findElement.topGet('foo'),
+ type: 'A?',
+ );
+
+ assertPropertyAccess2(
+ findNode.propertyAccess('.bar'),
+ element: findElement.getter('bar'),
+ type: 'A?',
+ );
+
+ assertPropertyAccess2(
+ findNode.propertyAccess('.baz'),
+ element: findElement.getter('baz'),
+ type: 'A?',
+ );
+
+ assertPropertyAccess2(
+ findNode.propertyAccess('.baq'),
+ element: findElement.getter('baq'),
+ type: 'A',
+ );
+
+ assertType(findNode.cascade('foo?'), 'A?');
+ }
+}
+
+mixin PropertyAccessResolutionTestCases on PubPackageResolutionTest {
test_extensionOverride_read() async {
await assertNoErrorsInCode('''
class A {}
@@ -561,158 +716,6 @@
}
@reflectiveTest
-class PropertyAccessResolutionWithNullSafetyTest
- extends PropertyAccessResolutionTest with WithNullSafetyMixin {
- test_implicitCall_tearOff_nullable() async {
- await assertErrorsInCode('''
-class A {
- int call() => 0;
-}
-
-class B {
- A? a;
-}
-
-int Function() foo() {
- return B().a; // ref
-}
-''', [
- error(CompileTimeErrorCode.RETURN_OF_INVALID_TYPE_FROM_FUNCTION, 85, 5),
- ]);
-
- var identifier = findNode.simple('a; // ref');
- assertElement(identifier, findElement.getter('a'));
- assertType(identifier, 'A?');
- }
-
- test_nullShorting_cascade() async {
- await assertNoErrorsInCode(r'''
-class A {
- int get foo => 0;
- int get bar => 0;
-}
-
-void f(A? a) {
- a?..foo..bar;
-}
-''');
-
- assertPropertyAccess2(
- findNode.propertyAccess('..foo'),
- element: findElement.getter('foo'),
- type: 'int',
- );
-
- assertPropertyAccess2(
- findNode.propertyAccess('..bar'),
- element: findElement.getter('bar'),
- type: 'int',
- );
-
- assertType(findNode.cascade('a?'), 'A?');
- }
-
- test_nullShorting_cascade2() async {
- await assertNoErrorsInCode(r'''
-class A {
- int? get foo => 0;
-}
-
-main() {
- A a = A()..foo?.isEven;
- a;
-}
-''');
-
- assertPropertyAccess2(
- findNode.propertyAccess('..foo?'),
- element: findElement.getter('foo'),
- type: 'int?',
- );
-
- assertPropertyAccess2(
- findNode.propertyAccess('.isEven'),
- element: intElement.getGetter('isEven'),
- type: 'bool',
- );
-
- assertType(findNode.cascade('A()'), 'A');
- }
-
- test_nullShorting_cascade3() async {
- await assertNoErrorsInCode(r'''
-class A {
- A? get foo => this;
- A? get bar => this;
- A? get baz => this;
-}
-
-main() {
- A a = A()..foo?.bar?.baz;
- a;
-}
-''');
-
- assertPropertyAccess2(
- findNode.propertyAccess('.foo'),
- element: findElement.getter('foo'),
- type: 'A?',
- );
-
- assertPropertyAccess2(
- findNode.propertyAccess('.bar'),
- element: findElement.getter('bar'),
- type: 'A?',
- );
-
- assertPropertyAccess2(
- findNode.propertyAccess('.baz'),
- element: findElement.getter('baz'),
- type: 'A?',
- );
-
- assertType(findNode.cascade('A()'), 'A');
- }
-
- test_nullShorting_cascade4() async {
- await assertNoErrorsInCode(r'''
-A? get foo => A();
-
-class A {
- A get bar => this;
- A? get baz => this;
- A get baq => this;
-}
-
-main() {
- foo?.bar?..baz?.baq;
-}
-''');
-
- assertSimpleIdentifier(
- findNode.simple('foo?'),
- element: findElement.topGet('foo'),
- type: 'A?',
- );
-
- assertPropertyAccess2(
- findNode.propertyAccess('.bar'),
- element: findElement.getter('bar'),
- type: 'A?',
- );
-
- assertPropertyAccess2(
- findNode.propertyAccess('.baz'),
- element: findElement.getter('baz'),
- type: 'A?',
- );
-
- assertPropertyAccess2(
- findNode.propertyAccess('.baq'),
- element: findElement.getter('baq'),
- type: 'A',
- );
-
- assertType(findNode.cascade('foo?'), 'A?');
- }
-}
+class PropertyAccessResolutionWithoutNullSafetyTest
+ extends PubPackageResolutionTest
+ with PropertyAccessResolutionTestCases, WithoutNullSafetyMixin {}
diff --git a/pkg/analyzer/test/src/dart/resolution/resolution.dart b/pkg/analyzer/test/src/dart/resolution/resolution.dart
index 2080ec9..63a93db 100644
--- a/pkg/analyzer/test/src/dart/resolution/resolution.dart
+++ b/pkg/analyzer/test/src/dart/resolution/resolution.dart
@@ -754,8 +754,8 @@
required TypeAliasElement element,
required List<String> typeArguments,
}) {
- assertElement2(type.aliasElement, declaration: element);
- assertElementTypeStrings(type.aliasArguments, typeArguments);
+ assertElement2(type.alias?.element, declaration: element);
+ assertElementTypeStrings(type.alias?.typeArguments, typeArguments);
}
/// Assert that the given [identifier] is a reference to a type alias, in the
@@ -924,8 +924,8 @@
result = await resolveFile(path);
expect(result.state, ResultState.VALID);
- findNode = FindNode(result.content!, result.unit!);
- findElement = FindElement(result.unit!);
+ findNode = FindNode(result.content, result.unit);
+ findElement = FindElement(result.unit);
}
/// Create a new file with the [path] and [content], resolve it into [result].
diff --git a/pkg/analyzer/test/src/dart/resolution/test_all.dart b/pkg/analyzer/test/src/dart/resolution/test_all.dart
index 5f1c71d..08c23ad 100644
--- a/pkg/analyzer/test/src/dart/resolution/test_all.dart
+++ b/pkg/analyzer/test/src/dart/resolution/test_all.dart
@@ -42,6 +42,7 @@
import 'library_element_test.dart' as library_element;
import 'local_function_test.dart' as local_function;
import 'local_variable_test.dart' as local_variable;
+import 'macro_test.dart' as macro;
import 'metadata_test.dart' as metadata;
import 'method_declaration_test.dart' as method_declaration;
import 'method_invocation_test.dart' as method_invocation;
@@ -101,6 +102,7 @@
library_element.main();
local_function.main();
local_variable.main();
+ macro.main();
metadata.main();
method_declaration.main();
method_invocation.main();
diff --git a/pkg/analyzer/test/src/dart/resolution/top_level_variable_test.dart b/pkg/analyzer/test/src/dart/resolution/top_level_variable_test.dart
index 1349f39..444c894 100644
--- a/pkg/analyzer/test/src/dart/resolution/top_level_variable_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/top_level_variable_test.dart
@@ -11,13 +11,32 @@
main() {
defineReflectiveSuite(() {
defineReflectiveTests(TopLevelVariableTest);
- defineReflectiveTests(TopLevelVariableWithNullSafetyTest);
+ defineReflectiveTests(TopLevelVariableWithoutNullSafetyTest);
});
}
@reflectiveTest
class TopLevelVariableTest extends PubPackageResolutionTest
- with WithoutNullSafetyMixin {
+ with TopLevelVariableTestCases {
+ test_type_inferred_nonNullify() async {
+ newFile('$testPackageLibPath/a.dart', content: r'''
+// @dart = 2.7
+var a = 0;
+''');
+
+ await assertErrorsInCode('''
+import 'a.dart';
+
+var v = a;
+''', [
+ error(HintCode.IMPORT_OF_LEGACY_LIBRARY_INTO_NULL_SAFE, 7, 8),
+ ]);
+
+ assertType(findElement.topVar('v').type, 'int');
+ }
+}
+
+mixin TopLevelVariableTestCases on PubPackageResolutionTest {
test_session_getterSetter() async {
await resolveTestCode('''
var v = 0;
@@ -65,22 +84,5 @@
}
@reflectiveTest
-class TopLevelVariableWithNullSafetyTest extends TopLevelVariableTest
- with WithNullSafetyMixin {
- test_type_inferred_nonNullify() async {
- newFile('$testPackageLibPath/a.dart', content: r'''
-// @dart = 2.7
-var a = 0;
-''');
-
- await assertErrorsInCode('''
-import 'a.dart';
-
-var v = a;
-''', [
- error(HintCode.IMPORT_OF_LEGACY_LIBRARY_INTO_NULL_SAFE, 7, 8),
- ]);
-
- assertType(findElement.topVar('v').type, 'int');
- }
-}
+class TopLevelVariableWithoutNullSafetyTest extends PubPackageResolutionTest
+ with TopLevelVariableTestCases, WithoutNullSafetyMixin {}
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/conditional_expression_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/conditional_expression_test.dart
index 71d74e19..a1531fb 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/conditional_expression_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/conditional_expression_test.dart
@@ -9,27 +9,13 @@
main() {
defineReflectiveSuite(() {
defineReflectiveTests(ConditionalExpressionTest);
- defineReflectiveTests(ConditionalExpressionWithNullSafetyTest);
+ defineReflectiveTests(ConditionalExpressionWithoutNullSafetyTest);
});
}
@reflectiveTest
class ConditionalExpressionTest extends PubPackageResolutionTest
- with WithoutNullSafetyMixin {
- test_upward() async {
- await resolveTestCode('''
-void f(bool a, int b, int c) {
- var d = a ? b : c;
- print(d);
-}
-''');
- assertType(findNode.simple('d)'), 'int');
- }
-}
-
-@reflectiveTest
-class ConditionalExpressionWithNullSafetyTest extends ConditionalExpressionTest
- with WithNullSafetyMixin {
+ with ConditionalExpressionTestCases {
@failingTest
test_downward() async {
await resolveTestCode('''
@@ -51,3 +37,20 @@
assertType(findNode.conditionalExpression('b ?'), 'int?');
}
}
+
+mixin ConditionalExpressionTestCases on PubPackageResolutionTest {
+ test_upward() async {
+ await resolveTestCode('''
+void f(bool a, int b, int c) {
+ var d = a ? b : c;
+ print(d);
+}
+''');
+ assertType(findNode.simple('d)'), 'int');
+ }
+}
+
+@reflectiveTest
+class ConditionalExpressionWithoutNullSafetyTest
+ extends PubPackageResolutionTest
+ with ConditionalExpressionTestCases, WithoutNullSafetyMixin {}
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/function_expression_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/function_expression_test.dart
index bcde92b..11676d2 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/function_expression_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/function_expression_test.dart
@@ -10,13 +10,129 @@
main() {
defineReflectiveSuite(() {
defineReflectiveTests(FunctionExpressionTest);
- defineReflectiveTests(FunctionExpressionWithNullSafetyTest);
+ defineReflectiveTests(FunctionExpressionWithoutNullSafetyTest);
});
}
@reflectiveTest
class FunctionExpressionTest extends PubPackageResolutionTest
- with WithoutNullSafetyMixin {
+ with FunctionExpressionTestCases {
+ test_contextFunctionType_nonNullify() async {
+ newFile('$testPackageLibPath/a.dart', content: r'''
+// @dart = 2.7
+
+int Function(int a) v;
+''');
+
+ await assertErrorsInCode('''
+import 'a.dart';
+
+T foo<T>() => throw 0;
+
+void f() {
+ v = (a) {
+ return foo();
+ };
+}
+''', [
+ error(HintCode.IMPORT_OF_LEGACY_LIBRARY_INTO_NULL_SAFE, 7, 8),
+ ]);
+ assertType(findElement.parameter('a').type, 'int');
+ _assertReturnType('(a) {', 'int');
+ }
+
+ test_contextFunctionType_nonNullify_returnType_takeActual() async {
+ newFile('$testPackageLibPath/a.dart', content: r'''
+// @dart = 2.7
+
+void foo(int Function() x) {}
+''');
+ await assertErrorsInCode('''
+import 'a.dart';
+
+void test(int? a) {
+ foo(() => a);
+}
+''', [
+ error(HintCode.IMPORT_OF_LEGACY_LIBRARY_INTO_NULL_SAFE, 7, 8),
+ ]);
+ _assertReturnType('() => a', 'int?');
+ }
+
+ test_contextFunctionType_nonNullify_returnType_takeContext() async {
+ newFile('$testPackageLibPath/a.dart', content: r'''
+// @dart = 2.7
+
+void foo(int Function() x) {}
+''');
+ await assertErrorsInCode('''
+import 'a.dart';
+
+void test(dynamic a) {
+ foo(() => a);
+}
+''', [
+ error(HintCode.IMPORT_OF_LEGACY_LIBRARY_INTO_NULL_SAFE, 7, 8),
+ ]);
+ _assertReturnType('() => a', 'int');
+ }
+
+ test_contextFunctionType_returnType_async_blockBody_objectQ() async {
+ await assertNoErrorsInCode('''
+T foo<T>() => throw 0;
+
+Object? Function() v = () async {
+ return foo();
+};
+''');
+ assertTypeArgumentTypes(
+ findNode.methodInvocation('foo();'),
+ ['FutureOr<Object?>'],
+ );
+ _assertReturnType('() async', 'Future<Object?>');
+ }
+
+ test_contextFunctionType_returnType_async_blockBody_objectQ2() async {
+ await assertNoErrorsInCode('''
+T foo<T>() => throw 0;
+
+Object? Function() v = () async {
+ return;
+};
+''');
+ _assertReturnType('() async', 'Future<Null>');
+ }
+
+ test_contextFunctionType_returnType_async_expressionBody_objectQ() async {
+ await assertNoErrorsInCode('''
+T foo<T>() => throw 0;
+
+Object? Function() v = () async => foo();
+''');
+ assertTypeArgumentTypes(
+ findNode.methodInvocation('foo();'),
+ ['FutureOr<Object?>'],
+ );
+ _assertReturnType('() async => foo', 'Future<Object?>');
+ }
+
+ test_optOut_downward_returnType_expressionBody_Null() async {
+ newFile('$testPackageLibPath/a.dart', content: r'''
+void foo(Map<String, String> Function() f) {}
+''');
+ await resolveTestCode('''
+// @dart = 2.5
+import 'a.dart';
+
+void main() {
+ foo(() => null);
+}
+''');
+ _assertReturnType('() =>', 'Null*');
+ }
+}
+
+mixin FunctionExpressionTestCases on PubPackageResolutionTest {
test_contextFunctionType_returnType_async_blockBody_futureOrVoid() async {
var expectedErrors = expectedErrorsByNullability(
nullable: [
@@ -460,119 +576,5 @@
}
@reflectiveTest
-class FunctionExpressionWithNullSafetyTest extends FunctionExpressionTest
- with WithNullSafetyMixin {
- test_contextFunctionType_nonNullify() async {
- newFile('$testPackageLibPath/a.dart', content: r'''
-// @dart = 2.7
-
-int Function(int a) v;
-''');
-
- await assertErrorsInCode('''
-import 'a.dart';
-
-T foo<T>() => throw 0;
-
-void f() {
- v = (a) {
- return foo();
- };
-}
-''', [
- error(HintCode.IMPORT_OF_LEGACY_LIBRARY_INTO_NULL_SAFE, 7, 8),
- ]);
- assertType(findElement.parameter('a').type, 'int');
- _assertReturnType('(a) {', 'int');
- }
-
- test_contextFunctionType_nonNullify_returnType_takeActual() async {
- newFile('$testPackageLibPath/a.dart', content: r'''
-// @dart = 2.7
-
-void foo(int Function() x) {}
-''');
- await assertErrorsInCode('''
-import 'a.dart';
-
-void test(int? a) {
- foo(() => a);
-}
-''', [
- error(HintCode.IMPORT_OF_LEGACY_LIBRARY_INTO_NULL_SAFE, 7, 8),
- ]);
- _assertReturnType('() => a', 'int?');
- }
-
- test_contextFunctionType_nonNullify_returnType_takeContext() async {
- newFile('$testPackageLibPath/a.dart', content: r'''
-// @dart = 2.7
-
-void foo(int Function() x) {}
-''');
- await assertErrorsInCode('''
-import 'a.dart';
-
-void test(dynamic a) {
- foo(() => a);
-}
-''', [
- error(HintCode.IMPORT_OF_LEGACY_LIBRARY_INTO_NULL_SAFE, 7, 8),
- ]);
- _assertReturnType('() => a', 'int');
- }
-
- test_contextFunctionType_returnType_async_blockBody_objectQ() async {
- await assertNoErrorsInCode('''
-T foo<T>() => throw 0;
-
-Object? Function() v = () async {
- return foo();
-};
-''');
- assertTypeArgumentTypes(
- findNode.methodInvocation('foo();'),
- ['FutureOr<Object?>'],
- );
- _assertReturnType('() async', 'Future<Object?>');
- }
-
- test_contextFunctionType_returnType_async_blockBody_objectQ2() async {
- await assertNoErrorsInCode('''
-T foo<T>() => throw 0;
-
-Object? Function() v = () async {
- return;
-};
-''');
- _assertReturnType('() async', 'Future<Null>');
- }
-
- test_contextFunctionType_returnType_async_expressionBody_objectQ() async {
- await assertNoErrorsInCode('''
-T foo<T>() => throw 0;
-
-Object? Function() v = () async => foo();
-''');
- assertTypeArgumentTypes(
- findNode.methodInvocation('foo();'),
- ['FutureOr<Object?>'],
- );
- _assertReturnType('() async => foo', 'Future<Object?>');
- }
-
- test_optOut_downward_returnType_expressionBody_Null() async {
- newFile('$testPackageLibPath/a.dart', content: r'''
-void foo(Map<String, String> Function() f) {}
-''');
- await resolveTestCode('''
-// @dart = 2.5
-import 'a.dart';
-
-void main() {
- foo(() => null);
-}
-''');
- _assertReturnType('() =>', 'Null*');
- }
-}
+class FunctionExpressionWithoutNullSafetyTest extends PubPackageResolutionTest
+ with FunctionExpressionTestCases, WithoutNullSafetyMixin {}
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/list_literal_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/list_literal_test.dart
index 80aeb15..39f7df5 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/list_literal_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/list_literal_test.dart
@@ -10,13 +10,98 @@
main() {
defineReflectiveSuite(() {
defineReflectiveTests(ListLiteralTest);
- defineReflectiveTests(ListLiteralWithNullSafetyTest);
+ defineReflectiveTests(ListLiteralWithoutNullSafetyTest);
});
}
@reflectiveTest
class ListLiteralTest extends PubPackageResolutionTest
- with WithoutNullSafetyMixin {
+ with ListLiteralTestCases {
+ test_context_spread_nullAware() async {
+ await assertNoErrorsInCode('''
+T f<T>(T t) => t;
+
+main() {
+ <int>[...?f(null)];
+}
+''');
+
+ assertMethodInvocation2(
+ findNode.methodInvocation('f(null)'),
+ element: findElement.topFunction('f'),
+ typeArgumentTypes: ['Iterable<int>?'],
+ invokeType: 'Iterable<int>? Function(Iterable<int>?)',
+ type: 'Iterable<int>?',
+ );
+ }
+
+ test_nested_hasNull_1() async {
+ await assertNoErrorsInCode('''
+main() {
+ [[0], null];
+}
+''');
+ assertType(findNode.listLiteral('[0'), 'List<int>');
+ assertType(findNode.listLiteral('[[0'), 'List<List<int>?>');
+ }
+
+ test_nested_hasNull_2() async {
+ await assertNoErrorsInCode('''
+main() {
+ [[0], [1, null]];
+}
+''');
+ assertType(findNode.listLiteral('[0'), 'List<int>');
+ assertType(findNode.listLiteral('[1,'), 'List<int?>');
+ assertType(findNode.listLiteral('[[0'), 'List<List<int?>>');
+ }
+
+ test_noContext_noTypeArgs_spread_never() async {
+ await assertNoErrorsInCode('''
+void f(Never a) async {
+ // ignore:unused_local_variable
+ var v = [...a];
+}
+''');
+ assertType(findNode.listLiteral('['), 'List<Never>');
+ }
+
+ test_noContext_noTypeArgs_spread_nullAware_never() async {
+ await assertErrorsInCode('''
+void f(Never a) async {
+ // ignore:unused_local_variable
+ var v = [...?a];
+}
+''', [
+ error(StaticWarningCode.INVALID_NULL_AWARE_OPERATOR, 69, 4),
+ ]);
+ assertType(findNode.listLiteral('['), 'List<Never>');
+ }
+
+ test_noContext_noTypeArgs_spread_nullAware_typeParameter_implementsNever() async {
+ await assertErrorsInCode('''
+void f<T extends Never>(T a) async {
+ // ignore:unused_local_variable
+ var v = [...?a];
+}
+''', [
+ error(StaticWarningCode.INVALID_NULL_AWARE_OPERATOR, 82, 4),
+ ]);
+ assertType(findNode.listLiteral('['), 'List<Never>');
+ }
+
+ test_noContext_noTypeArgs_spread_typeParameter_implementsNever() async {
+ await assertNoErrorsInCode('''
+void f<T extends Never>(T a) async {
+ // ignore:unused_local_variable
+ var v = [...a];
+}
+''');
+ assertType(findNode.listLiteral('['), 'List<Never>');
+ }
+}
+
+mixin ListLiteralTestCases on PubPackageResolutionTest {
test_context_noTypeArgs_expression_conflict() async {
await assertErrorsInCode('''
List<int> a = ['a'];
@@ -415,88 +500,5 @@
}
@reflectiveTest
-class ListLiteralWithNullSafetyTest extends ListLiteralTest
- with WithNullSafetyMixin {
- test_context_spread_nullAware() async {
- await assertNoErrorsInCode('''
-T f<T>(T t) => t;
-
-main() {
- <int>[...?f(null)];
-}
-''');
-
- assertMethodInvocation2(
- findNode.methodInvocation('f(null)'),
- element: findElement.topFunction('f'),
- typeArgumentTypes: ['Iterable<int>?'],
- invokeType: 'Iterable<int>? Function(Iterable<int>?)',
- type: 'Iterable<int>?',
- );
- }
-
- test_nested_hasNull_1() async {
- await assertNoErrorsInCode('''
-main() {
- [[0], null];
-}
-''');
- assertType(findNode.listLiteral('[0'), 'List<int>');
- assertType(findNode.listLiteral('[[0'), 'List<List<int>?>');
- }
-
- test_nested_hasNull_2() async {
- await assertNoErrorsInCode('''
-main() {
- [[0], [1, null]];
-}
-''');
- assertType(findNode.listLiteral('[0'), 'List<int>');
- assertType(findNode.listLiteral('[1,'), 'List<int?>');
- assertType(findNode.listLiteral('[[0'), 'List<List<int?>>');
- }
-
- test_noContext_noTypeArgs_spread_never() async {
- await assertNoErrorsInCode('''
-void f(Never a) async {
- // ignore:unused_local_variable
- var v = [...a];
-}
-''');
- assertType(findNode.listLiteral('['), 'List<Never>');
- }
-
- test_noContext_noTypeArgs_spread_nullAware_never() async {
- await assertErrorsInCode('''
-void f(Never a) async {
- // ignore:unused_local_variable
- var v = [...?a];
-}
-''', [
- error(StaticWarningCode.INVALID_NULL_AWARE_OPERATOR, 69, 4),
- ]);
- assertType(findNode.listLiteral('['), 'List<Never>');
- }
-
- test_noContext_noTypeArgs_spread_nullAware_typeParameter_implementsNever() async {
- await assertErrorsInCode('''
-void f<T extends Never>(T a) async {
- // ignore:unused_local_variable
- var v = [...?a];
-}
-''', [
- error(StaticWarningCode.INVALID_NULL_AWARE_OPERATOR, 82, 4),
- ]);
- assertType(findNode.listLiteral('['), 'List<Never>');
- }
-
- test_noContext_noTypeArgs_spread_typeParameter_implementsNever() async {
- await assertNoErrorsInCode('''
-void f<T extends Never>(T a) async {
- // ignore:unused_local_variable
- var v = [...a];
-}
-''');
- assertType(findNode.listLiteral('['), 'List<Never>');
- }
-}
+class ListLiteralWithoutNullSafetyTest extends PubPackageResolutionTest
+ with ListLiteralTestCases, WithoutNullSafetyMixin {}
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/map_literal_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/map_literal_test.dart
index e4af4f6..894f8a9 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/map_literal_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/map_literal_test.dart
@@ -11,13 +11,121 @@
main() {
defineReflectiveSuite(() {
defineReflectiveTests(MapLiteralTest);
- defineReflectiveTests(MapLiteralWithNullSafetyTest);
+ defineReflectiveTests(MapLiteralWithoutNullSafetyTest);
});
}
@reflectiveTest
-class MapLiteralTest extends PubPackageResolutionTest
- with WithoutNullSafetyMixin {
+class MapLiteralTest extends PubPackageResolutionTest with MapLiteralTestCases {
+ test_context_noTypeArgs_noEntries_typeParameterNullable() async {
+ await assertNoErrorsInCode('''
+class C<T extends Object?> {
+ Map<String, T> a = {}; // 1
+ Map<String, T>? b = {}; // 2
+ Map<String, T?> c = {}; // 3
+ Map<String, T?>? d = {}; // 4
+}
+''');
+ assertType(setOrMapLiteral('{}; // 1'), 'Map<String, T>');
+ assertType(setOrMapLiteral('{}; // 2'), 'Map<String, T>');
+ assertType(setOrMapLiteral('{}; // 3'), 'Map<String, T?>');
+ assertType(setOrMapLiteral('{}; // 4'), 'Map<String, T?>');
+ }
+
+ test_context_spread_nullAware() async {
+ await assertNoErrorsInCode('''
+T f<T>(T t) => t;
+
+main() {
+ <int, double>{...?f(null)};
+}
+''');
+
+ assertMethodInvocation2(
+ findNode.methodInvocation('f(null)'),
+ element: findElement.topFunction('f'),
+ typeArgumentTypes: ['Map<int, double>?'],
+ invokeType: 'Map<int, double>? Function(Map<int, double>?)',
+ type: 'Map<int, double>?',
+ );
+ }
+
+ test_noContext_noTypeArgs_spread_never() async {
+ await assertErrorsInCode('''
+void f(Never a, bool b) async {
+ // ignore:unused_local_variable
+ var v = {...a, if (b) throw 0: throw 0};
+}
+''', [
+ error(HintCode.DEAD_CODE, 87, 21),
+ ]);
+ assertType(setOrMapLiteral('{...'), 'Map<Never, Never>');
+ }
+
+ test_noContext_noTypeArgs_spread_nullAware_never() async {
+ await assertErrorsInCode('''
+void f(Never a, bool b) async {
+ // ignore:unused_local_variable
+ var v = {...?a, if (b) throw 0: throw 0};
+}
+''', [
+ error(StaticWarningCode.INVALID_NULL_AWARE_OPERATOR, 77, 4),
+ error(HintCode.DEAD_CODE, 88, 21),
+ ]);
+ assertType(setOrMapLiteral('{...'), 'Map<Never, Never>');
+ }
+
+ test_noContext_noTypeArgs_spread_nullAware_null() async {
+ await assertErrorsInCode('''
+void f(Null a, bool b) async {
+ // ignore:unused_local_variable
+ var v = {...?a, if (b) throw 0: throw 0};
+}
+''', [
+ error(HintCode.DEAD_CODE, 99, 9),
+ ]);
+ assertType(setOrMapLiteral('{...'), 'Map<Never, Never>');
+ }
+
+ test_noContext_noTypeArgs_spread_nullAware_typeParameter_never() async {
+ await assertErrorsInCode('''
+void f<T extends Never>(T a, bool b) async {
+ // ignore:unused_local_variable
+ var v = {...?a, if (b) throw 0: throw 0};
+}
+''', [
+ error(StaticWarningCode.INVALID_NULL_AWARE_OPERATOR, 90, 4),
+ error(HintCode.DEAD_CODE, 101, 21),
+ ]);
+ assertType(setOrMapLiteral('{...'), 'Map<Never, Never>');
+ }
+
+ test_noContext_noTypeArgs_spread_nullAware_typeParameter_null() async {
+ await assertErrorsInCode('''
+void f<T extends Null>(T a, bool b) async {
+ // ignore:unused_local_variable
+ var v = {...?a, if (b) throw 0: throw 0};
+}
+''', [
+ error(HintCode.DEAD_CODE, 112, 9),
+ ]);
+ assertType(setOrMapLiteral('{...'), 'Map<Never, Never>');
+ }
+
+ test_noContext_noTypeArgs_spread_typeParameter_never() async {
+ await assertErrorsInCode('''
+void f<T extends Never>(T a, bool b) async {
+ // ignore:unused_local_variable
+ var v = {...a, if (b) throw 0: throw 0};
+}
+''', [
+ error(HintCode.DEAD_CODE, 100, 21),
+ ]);
+ assertType(setOrMapLiteral('{...'), 'Map<Never, Never>');
+ }
+}
+
+mixin MapLiteralTestCases on PubPackageResolutionTest {
AstNode setOrMapLiteral(String search) => findNode.setOrMapLiteral(search);
test_context_noTypeArgs_entry_conflictingKey() async {
@@ -439,112 +547,5 @@
}
@reflectiveTest
-class MapLiteralWithNullSafetyTest extends MapLiteralTest
- with WithNullSafetyMixin {
- test_context_noTypeArgs_noEntries_typeParameterNullable() async {
- await assertNoErrorsInCode('''
-class C<T extends Object?> {
- Map<String, T> a = {}; // 1
- Map<String, T>? b = {}; // 2
- Map<String, T?> c = {}; // 3
- Map<String, T?>? d = {}; // 4
-}
-''');
- assertType(setOrMapLiteral('{}; // 1'), 'Map<String, T>');
- assertType(setOrMapLiteral('{}; // 2'), 'Map<String, T>');
- assertType(setOrMapLiteral('{}; // 3'), 'Map<String, T?>');
- assertType(setOrMapLiteral('{}; // 4'), 'Map<String, T?>');
- }
-
- test_context_spread_nullAware() async {
- await assertNoErrorsInCode('''
-T f<T>(T t) => t;
-
-main() {
- <int, double>{...?f(null)};
-}
-''');
-
- assertMethodInvocation2(
- findNode.methodInvocation('f(null)'),
- element: findElement.topFunction('f'),
- typeArgumentTypes: ['Map<int, double>?'],
- invokeType: 'Map<int, double>? Function(Map<int, double>?)',
- type: 'Map<int, double>?',
- );
- }
-
- test_noContext_noTypeArgs_spread_never() async {
- await assertErrorsInCode('''
-void f(Never a, bool b) async {
- // ignore:unused_local_variable
- var v = {...a, if (b) throw 0: throw 0};
-}
-''', [
- error(HintCode.DEAD_CODE, 87, 21),
- ]);
- assertType(setOrMapLiteral('{...'), 'Map<Never, Never>');
- }
-
- test_noContext_noTypeArgs_spread_nullAware_never() async {
- await assertErrorsInCode('''
-void f(Never a, bool b) async {
- // ignore:unused_local_variable
- var v = {...?a, if (b) throw 0: throw 0};
-}
-''', [
- error(StaticWarningCode.INVALID_NULL_AWARE_OPERATOR, 77, 4),
- error(HintCode.DEAD_CODE, 88, 21),
- ]);
- assertType(setOrMapLiteral('{...'), 'Map<Never, Never>');
- }
-
- test_noContext_noTypeArgs_spread_nullAware_null() async {
- await assertErrorsInCode('''
-void f(Null a, bool b) async {
- // ignore:unused_local_variable
- var v = {...?a, if (b) throw 0: throw 0};
-}
-''', [
- error(HintCode.DEAD_CODE, 99, 9),
- ]);
- assertType(setOrMapLiteral('{...'), 'Map<Never, Never>');
- }
-
- test_noContext_noTypeArgs_spread_nullAware_typeParameter_never() async {
- await assertErrorsInCode('''
-void f<T extends Never>(T a, bool b) async {
- // ignore:unused_local_variable
- var v = {...?a, if (b) throw 0: throw 0};
-}
-''', [
- error(StaticWarningCode.INVALID_NULL_AWARE_OPERATOR, 90, 4),
- error(HintCode.DEAD_CODE, 101, 21),
- ]);
- assertType(setOrMapLiteral('{...'), 'Map<Never, Never>');
- }
-
- test_noContext_noTypeArgs_spread_nullAware_typeParameter_null() async {
- await assertErrorsInCode('''
-void f<T extends Null>(T a, bool b) async {
- // ignore:unused_local_variable
- var v = {...?a, if (b) throw 0: throw 0};
-}
-''', [
- error(HintCode.DEAD_CODE, 112, 9),
- ]);
- assertType(setOrMapLiteral('{...'), 'Map<Never, Never>');
- }
-
- test_noContext_noTypeArgs_spread_typeParameter_never() async {
- await assertErrorsInCode('''
-void f<T extends Never>(T a, bool b) async {
- // ignore:unused_local_variable
- var v = {...a, if (b) throw 0: throw 0};
-}
-''', [
- error(HintCode.DEAD_CODE, 100, 21),
- ]);
- assertType(setOrMapLiteral('{...'), 'Map<Never, Never>');
- }
-}
+class MapLiteralWithoutNullSafetyTest extends PubPackageResolutionTest
+ with MapLiteralTestCases, WithoutNullSafetyMixin {}
diff --git a/pkg/analyzer/test/src/dart/resolver/exit_detector_test.dart b/pkg/analyzer/test/src/dart/resolver/exit_detector_test.dart
index a24235f..690050e 100644
--- a/pkg/analyzer/test/src/dart/resolver/exit_detector_test.dart
+++ b/pkg/analyzer/test/src/dart/resolver/exit_detector_test.dart
@@ -1102,7 +1102,7 @@
Future<void> _assertHasReturn(String code, int n, bool expected) async {
await resolveTestCode(code);
- var function = result.unit!.declarations.last as FunctionDeclaration;
+ var function = result.unit.declarations.last as FunctionDeclaration;
var body = function.functionExpression.body as BlockFunctionBody;
Statement statement = body.block.statements[n];
expect(ExitDetector.exits(statement), expected);
diff --git a/pkg/analyzer/test/src/diagnostics/abstract_class_member_test.dart b/pkg/analyzer/test/src/diagnostics/abstract_class_member_test.dart
index cba3c60..7879c8c 100644
--- a/pkg/analyzer/test/src/diagnostics/abstract_class_member_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/abstract_class_member_test.dart
@@ -10,13 +10,15 @@
main() {
defineReflectiveSuite(() {
defineReflectiveTests(AbstractClassMemberTest);
- defineReflectiveTests(AbstractClassMemberWithNullSafetyTest);
+ defineReflectiveTests(AbstractClassMemberWithoutNullSafetyTest);
});
}
@reflectiveTest
class AbstractClassMemberTest extends PubPackageResolutionTest
- with WithoutNullSafetyMixin {
+ with AbstractClassMemberTestCases {}
+
+mixin AbstractClassMemberTestCases on PubPackageResolutionTest {
test_abstract_field_dynamic() async {
await assertErrorsInCode(
'''
@@ -55,5 +57,5 @@
}
@reflectiveTest
-class AbstractClassMemberWithNullSafetyTest extends AbstractClassMemberTest
- with WithNullSafetyMixin {}
+class AbstractClassMemberWithoutNullSafetyTest extends PubPackageResolutionTest
+ with AbstractClassMemberTestCases, WithoutNullSafetyMixin {}
diff --git a/pkg/analyzer/test/src/diagnostics/assignment_to_final_test.dart b/pkg/analyzer/test/src/diagnostics/assignment_to_final_test.dart
index d45f72d..1ef0c33 100644
--- a/pkg/analyzer/test/src/diagnostics/assignment_to_final_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/assignment_to_final_test.dart
@@ -10,119 +10,13 @@
main() {
defineReflectiveSuite(() {
defineReflectiveTests(AssignmentToFinalTest);
- defineReflectiveTests(AssignmentToFinalWithNullSafetyTest);
+ defineReflectiveTests(AssignmentToFinalWithoutNullSafetyTest);
});
}
@reflectiveTest
class AssignmentToFinalTest extends PubPackageResolutionTest
- with WithoutNullSafetyMixin {
- test_prefixedIdentifier_instanceField() async {
- await assertNoErrorsInCode('''
-class A {
- var x = 0;
-}
-
-void f(A a) {
- a.x = 0;
- a.x += 0;
- ++a.x;
- a.x++;
-}
-''');
- }
-
- test_prefixedIdentifier_instanceField_final() async {
- await assertErrorsInCode('''
-class A {
- final x = 0;
-}
-
-void f(A a) {
- a.x = 0;
- a.x += 0;
- ++a.x;
- a.x++;
-}
-''', [
- error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 46, 1),
- error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 57, 1),
- error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 71, 1),
- error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 78, 1),
- ]);
- }
-
- test_simpleIdentifier_inheritedSetter_shadowedBy_topLevelGetter() async {
- await assertErrorsInCode('''
-class A {
- void set foo(int _) {}
-}
-
-int get foo => 0;
-
-class B extends A {
- void bar() {
- foo = 0;
- }
-}
-''', [
- error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 96, 3),
- ]);
- }
-
- test_simpleIdentifier_topLevelGetter() async {
- await assertErrorsInCode('''
-int get x => 0;
-
-void f() {
- x = 0;
- x += 0;
- ++x;
- x++;
-}
-''', [
- error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 30, 1),
- error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 39, 1),
- error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 51, 1),
- error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 56, 1),
- ]);
- }
-
- test_simpleIdentifier_topLevelVariable() async {
- await assertNoErrorsInCode('''
-var x = 0;
-
-void f() {
- x = 0;
- x += 0;
- ++x;
- x++;
-}
-''');
- }
-
- test_simpleIdentifier_topLevelVariable_final() async {
- await assertErrorsInCode('''
-final x = 0;
-
-void f() {
- x = 0;
- x += 0;
- ++x;
- x++;
-}
-''', [
- error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 27, 1),
- error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 36, 1),
- error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 48, 1),
- error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 53, 1),
- ]);
- }
-}
-
-@reflectiveTest
-class AssignmentToFinalWithNullSafetyTest extends AssignmentToFinalTest
- with WithNullSafetyMixin {
+ with AssignmentToFinalTestCases {
test_prefixedIdentifier_instanceField_abstract() async {
await assertNoErrorsInCode('''
abstract class A {
@@ -450,3 +344,111 @@
]);
}
}
+
+mixin AssignmentToFinalTestCases on PubPackageResolutionTest {
+ test_prefixedIdentifier_instanceField() async {
+ await assertNoErrorsInCode('''
+class A {
+ var x = 0;
+}
+
+void f(A a) {
+ a.x = 0;
+ a.x += 0;
+ ++a.x;
+ a.x++;
+}
+''');
+ }
+
+ test_prefixedIdentifier_instanceField_final() async {
+ await assertErrorsInCode('''
+class A {
+ final x = 0;
+}
+
+void f(A a) {
+ a.x = 0;
+ a.x += 0;
+ ++a.x;
+ a.x++;
+}
+''', [
+ error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 46, 1),
+ error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 57, 1),
+ error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 71, 1),
+ error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 78, 1),
+ ]);
+ }
+
+ test_simpleIdentifier_inheritedSetter_shadowedBy_topLevelGetter() async {
+ await assertErrorsInCode('''
+class A {
+ void set foo(int _) {}
+}
+
+int get foo => 0;
+
+class B extends A {
+ void bar() {
+ foo = 0;
+ }
+}
+''', [
+ error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 96, 3),
+ ]);
+ }
+
+ test_simpleIdentifier_topLevelGetter() async {
+ await assertErrorsInCode('''
+int get x => 0;
+
+void f() {
+ x = 0;
+ x += 0;
+ ++x;
+ x++;
+}
+''', [
+ error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 30, 1),
+ error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 39, 1),
+ error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 51, 1),
+ error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 56, 1),
+ ]);
+ }
+
+ test_simpleIdentifier_topLevelVariable() async {
+ await assertNoErrorsInCode('''
+var x = 0;
+
+void f() {
+ x = 0;
+ x += 0;
+ ++x;
+ x++;
+}
+''');
+ }
+
+ test_simpleIdentifier_topLevelVariable_final() async {
+ await assertErrorsInCode('''
+final x = 0;
+
+void f() {
+ x = 0;
+ x += 0;
+ ++x;
+ x++;
+}
+''', [
+ error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 27, 1),
+ error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 36, 1),
+ error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 48, 1),
+ error(CompileTimeErrorCode.ASSIGNMENT_TO_FINAL, 53, 1),
+ ]);
+ }
+}
+
+@reflectiveTest
+class AssignmentToFinalWithoutNullSafetyTest extends PubPackageResolutionTest
+ with AssignmentToFinalTestCases, WithoutNullSafetyMixin {}
diff --git a/pkg/analyzer/test/src/diagnostics/const_constructor_with_mixin_with_field_test.dart b/pkg/analyzer/test/src/diagnostics/const_constructor_with_mixin_with_field_test.dart
index 73e81a8..08b1904 100644
--- a/pkg/analyzer/test/src/diagnostics/const_constructor_with_mixin_with_field_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/const_constructor_with_mixin_with_field_test.dart
@@ -15,6 +15,37 @@
@reflectiveTest
class ConstConstructorWithMixinWithFieldTest extends PubPackageResolutionTest {
+ test_class_instance_abstract() async {
+ await assertErrorsInCode('''
+mixin A {
+ abstract int a;
+}
+
+class B with A {
+ @override
+ int a;
+ const B(this.a);
+}
+''', [
+ error(
+ CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD, 77, 1),
+ ]);
+ }
+
+ test_class_instance_abstract_final() async {
+ await assertNoErrorsInCode('''
+mixin A {
+ abstract final int a;
+}
+
+class B with A {
+ @override
+ final int a;
+ const B(this.a);
+}
+''');
+ }
+
test_class_instance_final() async {
await assertErrorsInCode('''
class A {
@@ -64,7 +95,6 @@
const B();
}
''', [
- error(CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD, 62, 1),
error(
CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD, 62, 1),
]);
@@ -81,7 +111,6 @@
const B();
}
''', [
- error(CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD, 71, 1),
error(
CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELDS, 71, 1),
]);
@@ -119,7 +148,6 @@
const X();
}
''', [
- error(CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD, 62, 1),
error(
CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD, 62, 1),
]);
diff --git a/pkg/analyzer/test/src/diagnostics/const_constructor_with_non_final_field_test.dart b/pkg/analyzer/test/src/diagnostics/const_constructor_with_non_final_field_test.dart
index 4d4f331..0b5cf6e 100644
--- a/pkg/analyzer/test/src/diagnostics/const_constructor_with_non_final_field_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/const_constructor_with_non_final_field_test.dart
@@ -15,35 +15,6 @@
@reflectiveTest
class ConstConstructorWithNonFinalFieldTest extends PubPackageResolutionTest {
- test_mixin() async {
- await assertErrorsInCode(r'''
-class A {
- var a;
-}
-class B extends Object with A {
- const B();
-}
-''', [
- error(CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD, 61, 1),
- error(
- CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD, 61, 1),
- ]);
- }
-
- test_super() async {
- await assertErrorsInCode(r'''
-class A {
- var a;
-}
-class B extends A {
- const B();
-}
-''', [
- error(CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD, 49, 1),
- error(CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER, 49, 1),
- ]);
- }
-
test_this_named() async {
await assertErrorsInCode(r'''
class A {
diff --git a/pkg/analyzer/test/src/diagnostics/dead_code_test.dart b/pkg/analyzer/test/src/diagnostics/dead_code_test.dart
index 1fc2927..92f1995 100644
--- a/pkg/analyzer/test/src/diagnostics/dead_code_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/dead_code_test.dart
@@ -10,13 +10,139 @@
main() {
defineReflectiveSuite(() {
defineReflectiveTests(DeadCodeTest);
- defineReflectiveTests(DeadCodeWithNullSafetyTest);
+ defineReflectiveTests(DeadCodeWithoutNullSafetyTest);
});
}
@reflectiveTest
-class DeadCodeTest extends PubPackageResolutionTest
- with WithoutNullSafetyMixin {
+class DeadCodeTest extends PubPackageResolutionTest with DeadCodeTestCases {
+ test_assert_dead_message() async {
+ // We don't warn if an assert statement is live but its message is dead,
+ // because this results in nuisance warnings for desirable assertions (e.g.
+ // a `!= null` assertion that is redundant with strong checking but still
+ // useful with weak checking).
+ await assertErrorsInCode('''
+void f(Object waldo) {
+ assert(waldo != null, "Where's Waldo?");
+}
+''', [
+ error(HintCode.UNNECESSARY_NULL_COMPARISON_TRUE, 38, 7),
+ ]);
+ }
+
+ test_flowEnd_tryStatement_body() async {
+ await assertErrorsInCode(r'''
+Never foo() => throw 0;
+
+main() {
+ try {
+ foo();
+ 1;
+ } catch (_) {
+ 2;
+ }
+ 3;
+}
+''', [
+ error(HintCode.DEAD_CODE, 57, 2),
+ ]);
+ }
+
+ test_invokeNever_functionExpressionInvocation_getter_propertyAccess() async {
+ await assertErrorsInCode(r'''
+class A {
+ Never get f => throw 0;
+}
+void g(A a) {
+ a.f(0);
+ print(1);
+}
+''', [
+ error(HintCode.RECEIVER_OF_TYPE_NEVER, 54, 3),
+ error(HintCode.DEAD_CODE, 57, 16),
+ ]);
+ }
+
+ test_invokeNever_functionExpressionInvocation_parenthesizedExpression() async {
+ await assertErrorsInCode(r'''
+void g(Never f) {
+ (f)(0);
+ print(1);
+}
+''', [
+ error(HintCode.RECEIVER_OF_TYPE_NEVER, 20, 3),
+ error(HintCode.DEAD_CODE, 23, 16),
+ ]);
+ }
+
+ test_invokeNever_functionExpressionInvocation_simpleIdentifier() async {
+ await assertErrorsInCode(r'''
+void g(Never f) {
+ f(0);
+ print(1);
+}
+''', [
+ error(HintCode.RECEIVER_OF_TYPE_NEVER, 20, 1),
+ error(HintCode.DEAD_CODE, 21, 16),
+ ]);
+ }
+
+ test_returnTypeNever_function() async {
+ await assertErrorsInCode(r'''
+Never foo() => throw 0;
+
+main() {
+ foo();
+ 1;
+}
+''', [
+ error(HintCode.DEAD_CODE, 45, 2),
+ ]);
+ }
+
+ test_returnTypeNever_getter() async {
+ await assertErrorsInCode(r'''
+Never get foo => throw 0;
+
+main() {
+ foo;
+ 2;
+}
+''', [
+ error(HintCode.DEAD_CODE, 45, 2),
+ ]);
+ }
+
+ @FailingTest(reason: '@alwaysThrows is not supported in flow analysis')
+ @override
+ test_statementAfterAlwaysThrowsFunction() async {
+ return super.test_statementAfterAlwaysThrowsFunction();
+ }
+
+ @FailingTest(reason: '@alwaysThrows is not supported in flow analysis')
+ @override
+ test_statementAfterAlwaysThrowsMethod() async {
+ return super.test_statementAfterAlwaysThrowsMethod();
+ }
+
+ test_switchStatement_exhaustive() async {
+ await assertErrorsInCode(r'''
+enum Foo { a, b }
+
+int f(Foo foo) {
+ switch (foo) {
+ case Foo.a: return 0;
+ case Foo.b: return 1;
+ }
+ return -1;
+}
+''', [
+ error(HintCode.DEAD_CODE, 111, 10),
+ ]);
+ }
+}
+
+mixin DeadCodeTestCases on PubPackageResolutionTest {
@override
void setUp() {
super.setUp();
@@ -846,129 +972,5 @@
}
@reflectiveTest
-class DeadCodeWithNullSafetyTest extends DeadCodeTest with WithNullSafetyMixin {
- test_assert_dead_message() async {
- // We don't warn if an assert statement is live but its message is dead,
- // because this results in nuisance warnings for desirable assertions (e.g.
- // a `!= null` assertion that is redundant with strong checking but still
- // useful with weak checking).
- await assertErrorsInCode('''
-void f(Object waldo) {
- assert(waldo != null, "Where's Waldo?");
-}
-''', [
- error(HintCode.UNNECESSARY_NULL_COMPARISON_TRUE, 38, 7),
- ]);
- }
-
- test_flowEnd_tryStatement_body() async {
- await assertErrorsInCode(r'''
-Never foo() => throw 0;
-
-main() {
- try {
- foo();
- 1;
- } catch (_) {
- 2;
- }
- 3;
-}
-''', [
- error(HintCode.DEAD_CODE, 57, 2),
- ]);
- }
-
- test_invokeNever_functionExpressionInvocation_getter_propertyAccess() async {
- await assertErrorsInCode(r'''
-class A {
- Never get f => throw 0;
-}
-void g(A a) {
- a.f(0);
- print(1);
-}
-''', [
- error(HintCode.RECEIVER_OF_TYPE_NEVER, 54, 3),
- error(HintCode.DEAD_CODE, 57, 16),
- ]);
- }
-
- test_invokeNever_functionExpressionInvocation_parenthesizedExpression() async {
- await assertErrorsInCode(r'''
-void g(Never f) {
- (f)(0);
- print(1);
-}
-''', [
- error(HintCode.RECEIVER_OF_TYPE_NEVER, 20, 3),
- error(HintCode.DEAD_CODE, 23, 16),
- ]);
- }
-
- test_invokeNever_functionExpressionInvocation_simpleIdentifier() async {
- await assertErrorsInCode(r'''
-void g(Never f) {
- f(0);
- print(1);
-}
-''', [
- error(HintCode.RECEIVER_OF_TYPE_NEVER, 20, 1),
- error(HintCode.DEAD_CODE, 21, 16),
- ]);
- }
-
- test_returnTypeNever_function() async {
- await assertErrorsInCode(r'''
-Never foo() => throw 0;
-
-main() {
- foo();
- 1;
-}
-''', [
- error(HintCode.DEAD_CODE, 45, 2),
- ]);
- }
-
- test_returnTypeNever_getter() async {
- await assertErrorsInCode(r'''
-Never get foo => throw 0;
-
-main() {
- foo;
- 2;
-}
-''', [
- error(HintCode.DEAD_CODE, 45, 2),
- ]);
- }
-
- @FailingTest(reason: '@alwaysThrows is not supported in flow analysis')
- @override
- test_statementAfterAlwaysThrowsFunction() async {
- return super.test_statementAfterAlwaysThrowsFunction();
- }
-
- @FailingTest(reason: '@alwaysThrows is not supported in flow analysis')
- @override
- test_statementAfterAlwaysThrowsMethod() async {
- return super.test_statementAfterAlwaysThrowsMethod();
- }
-
- test_switchStatement_exhaustive() async {
- await assertErrorsInCode(r'''
-enum Foo { a, b }
-
-int f(Foo foo) {
- switch (foo) {
- case Foo.a: return 0;
- case Foo.b: return 1;
- }
- return -1;
-}
-''', [
- error(HintCode.DEAD_CODE, 111, 10),
- ]);
- }
-}
+class DeadCodeWithoutNullSafetyTest extends PubPackageResolutionTest
+ with DeadCodeTestCases, WithoutNullSafetyMixin {}
diff --git a/pkg/analyzer/test/src/diagnostics/ffi_native_test.dart b/pkg/analyzer/test/src/diagnostics/ffi_native_test.dart
new file mode 100644
index 0000000..a11172c
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/ffi_native_test.dart
@@ -0,0 +1,57 @@
+// 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.
+
+import 'package:analyzer/src/dart/error/ffi_code.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/context_collection_resolution.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(FfiNativeTest);
+ });
+}
+
+@reflectiveTest
+class FfiNativeTest extends PubPackageResolutionTest {
+ test_FfiNativeAnnotationOnInstanceMethod() async {
+ await assertErrorsInCode(r'''
+import 'dart:ffi';
+class K {
+ @FfiNative<Void Function()>('DoesntMatter')
+ external void doesntMatter();
+}
+''', [
+ error(FfiCode.FFI_NATIVE_ONLY_STATIC, 31, 75),
+ ]);
+ }
+
+ test_FfiNativeCanUseHandles() async {
+ await assertErrorsInCode(r'''
+import 'dart:ffi';
+@FfiNative<Handle Function(Handle)>('DoesntMatter')
+external Object doesntMatter(Object);
+''', []);
+ }
+
+ test_FfiNativeLeafMustNotReturnHandle() async {
+ await assertErrorsInCode(r'''
+import 'dart:ffi';
+@FfiNative<Handle Function()>('DoesntMatter', isLeaf:true)
+external Object doesntMatter();
+''', [
+ error(FfiCode.LEAF_CALL_MUST_NOT_RETURN_HANDLE, 19, 90),
+ ]);
+ }
+
+ test_FfiNativeLeafMustNotTakeHandles() async {
+ await assertErrorsInCode(r'''
+import 'dart:ffi';
+@FfiNative<Void Function(Handle)>('DoesntMatter', isLeaf:true)
+external void doesntMatter(Object o);
+''', [
+ error(FfiCode.LEAF_CALL_MUST_NOT_TAKE_HANDLE, 19, 100),
+ ]);
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/instance_access_to_static_member_test.dart b/pkg/analyzer/test/src/diagnostics/instance_access_to_static_member_test.dart
index aeaec55..ee423c8 100644
--- a/pkg/analyzer/test/src/diagnostics/instance_access_to_static_member_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/instance_access_to_static_member_test.dart
@@ -102,6 +102,19 @@
]);
}
+ test_method_reference_typeInstantiation() async {
+ await assertErrorsInCode(r'''
+class A {
+ static m<T>() {}
+}
+f(A a) {
+ a.m<int>;
+}
+''', [
+ error(CompileTimeErrorCode.INSTANCE_ACCESS_TO_STATIC_MEMBER, 44, 1),
+ ]);
+ }
+
test_propertyAccess_field() async {
await assertErrorsInCode(r'''
class A {
diff --git a/pkg/analyzer/test/src/diagnostics/mixin_application_not_implemented_interface_test.dart b/pkg/analyzer/test/src/diagnostics/mixin_application_not_implemented_interface_test.dart
index 31546d9..0266782 100644
--- a/pkg/analyzer/test/src/diagnostics/mixin_application_not_implemented_interface_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/mixin_application_not_implemented_interface_test.dart
@@ -111,7 +111,7 @@
error(HintCode.UNUSED_ELEMENT, 96, 15),
]);
var mixins =
- result.unit!.declaredElement!.getType('_LocalDirectory')!.mixins;
+ result.unit.declaredElement!.getType('_LocalDirectory')!.mixins;
assertType(mixins[0], 'ForwardingDirectory<_LocalDirectory>');
}
}
diff --git a/pkg/analyzer/test/src/diagnostics/must_be_a_native_function_type_test.dart b/pkg/analyzer/test/src/diagnostics/must_be_a_native_function_type_test.dart
index c46e611..ced28b0 100644
--- a/pkg/analyzer/test/src/diagnostics/must_be_a_native_function_type_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/must_be_a_native_function_type_test.dart
@@ -25,7 +25,7 @@
}
}
''', [
- error(FfiCode.MUST_BE_A_NATIVE_FUNCTION_TYPE, 89, 26),
+ error(FfiCode.MUST_BE_A_NATIVE_FUNCTION_TYPE, 110, 1),
]);
}
diff --git a/pkg/analyzer/test/src/diagnostics/new_with_undefined_constructor_test.dart b/pkg/analyzer/test/src/diagnostics/new_with_undefined_constructor_test.dart
index 602e5ff..4ebf06c 100644
--- a/pkg/analyzer/test/src/diagnostics/new_with_undefined_constructor_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/new_with_undefined_constructor_test.dart
@@ -2,6 +2,7 @@
// 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.
+import 'package:analyzer/src/dart/error/syntactic_errors.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -10,11 +11,16 @@
main() {
defineReflectiveSuite(() {
defineReflectiveTests(NewWithUndefinedConstructorTest);
+ defineReflectiveTests(
+ NewWithUndefinedConstructorWithoutConstructorTearoffsTest);
});
}
@reflectiveTest
-class NewWithUndefinedConstructorTest extends PubPackageResolutionTest {
+class NewWithUndefinedConstructorTest extends PubPackageResolutionTest
+ with NewWithUndefinedConstructorTestCases {}
+
+mixin NewWithUndefinedConstructorTestCases on PubPackageResolutionTest {
test_default() async {
await assertErrorsInCode('''
class A {
@@ -28,6 +34,43 @@
]);
}
+ test_default_noKeyword() async {
+ await assertErrorsInCode('''
+class A {
+ A.name() {}
+}
+f() {
+ A();
+}
+''', [
+ error(CompileTimeErrorCode.NEW_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT, 34, 1),
+ ]);
+ }
+
+ test_default_unnamedViaNew() async {
+ await assertErrorsInCode('''
+class A {
+ A.name() {}
+}
+f() {
+ A.new();
+}
+''', [
+ error(CompileTimeErrorCode.NEW_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT, 36, 3),
+ ]);
+ }
+
+ test_defaultViaNew() async {
+ await assertNoErrorsInCode('''
+class A {
+ A.new() {}
+}
+f() {
+ A();
+}
+''');
+ }
+
test_defined_named() async {
await assertNoErrorsInCode(r'''
class A {
@@ -111,3 +154,33 @@
]);
}
}
+
+@reflectiveTest
+class NewWithUndefinedConstructorWithoutConstructorTearoffsTest
+ extends PubPackageResolutionTest with WithoutConstructorTearoffsMixin {
+ test_defaultViaNew() async {
+ await assertErrorsInCode('''
+class A {
+ A.new() {}
+}
+f() {
+ A();
+}
+''', [
+ error(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 14, 3),
+ ]);
+ }
+
+ test_unnamedViaNew() async {
+ await assertErrorsInCode('''
+class A {
+ A.named() {}
+}
+f() {
+ A.new();
+}
+''', [
+ error(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 37, 3),
+ ]);
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/subtype_of_struct_class_test.dart b/pkg/analyzer/test/src/diagnostics/subtype_of_struct_class_test.dart
index ab9e982..026be64 100644
--- a/pkg/analyzer/test/src/diagnostics/subtype_of_struct_class_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/subtype_of_struct_class_test.dart
@@ -51,7 +51,7 @@
class S extends Struct {}
class C implements S {}
''', [
- error(FfiCode.EMPTY_STRUCT, 19, 25),
+ error(FfiCode.EMPTY_STRUCT, 25, 1),
error(FfiCode.SUBTYPE_OF_STRUCT_CLASS_IN_IMPLEMENTS, 64, 1),
]);
}
@@ -62,7 +62,7 @@
class S extends Union {}
class C implements S {}
''', [
- error(FfiCode.EMPTY_STRUCT, 19, 24),
+ error(FfiCode.EMPTY_STRUCT, 25, 1),
error(FfiCode.SUBTYPE_OF_STRUCT_CLASS_IN_IMPLEMENTS, 63, 1),
]);
}
@@ -76,7 +76,7 @@
class S extends Struct {}
class C with S {}
''', [
- error(FfiCode.EMPTY_STRUCT, 19, 25),
+ error(FfiCode.EMPTY_STRUCT, 25, 1),
error(CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT_OBJECT, 58, 1),
error(FfiCode.SUBTYPE_OF_STRUCT_CLASS_IN_WITH, 58, 1),
]);
@@ -88,7 +88,7 @@
class S extends Union {}
class C with S {}
''', [
- error(FfiCode.EMPTY_STRUCT, 19, 24),
+ error(FfiCode.EMPTY_STRUCT, 25, 1),
error(CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT_OBJECT, 57, 1),
error(FfiCode.SUBTYPE_OF_STRUCT_CLASS_IN_WITH, 57, 1),
]);
diff --git a/pkg/analyzer/test/src/diagnostics/test_all.dart b/pkg/analyzer/test/src/diagnostics/test_all.dart
index fd81c75..49fbffe 100644
--- a/pkg/analyzer/test/src/diagnostics/test_all.dart
+++ b/pkg/analyzer/test/src/diagnostics/test_all.dart
@@ -193,6 +193,7 @@
as ffi_array_multi_non_positive_input_test;
import 'ffi_leaf_call_must_not_use_handle_test.dart'
as ffi_leaf_call_must_not_use_handle;
+import 'ffi_native_test.dart' as ffi_native_test;
import 'field_in_struct_with_initializer_test.dart'
as field_in_struct_with_initializer;
import 'field_initialized_by_multiple_initializers_test.dart'
@@ -844,6 +845,7 @@
extra_size_annotation_carray.main();
ffi_array_multi_non_positive_input_test.main();
ffi_leaf_call_must_not_use_handle.main();
+ ffi_native_test.main();
field_in_struct_with_initializer.main();
field_initialized_by_multiple_initializers.main();
final_initialized_in_declaration_and_constructor.main();
diff --git a/pkg/analyzer/test/src/diagnostics/type_argument_not_matching_bounds_test.dart b/pkg/analyzer/test/src/diagnostics/type_argument_not_matching_bounds_test.dart
index 72f8042..79ab24a 100644
--- a/pkg/analyzer/test/src/diagnostics/type_argument_not_matching_bounds_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/type_argument_not_matching_bounds_test.dart
@@ -300,7 +300,7 @@
error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 65, 3),
]);
// Instantiate-to-bounds should have instantiated "Bar" to "Bar<Foo>".
- assertType(result.unit!.declaredElement!.getType('Baz')!.supertype,
+ assertType(result.unit.declaredElement!.getType('Baz')!.supertype,
'Bar<Foo<dynamic>>');
}
@@ -453,17 +453,19 @@
test_functionReference() async {
await assertErrorsInCode('''
-void bar(void Function<T extends num>(T a) foo) {
+void foo<T extends num>(T a) {}
+void bar() {
foo<String>;
}
''', [
- error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 56, 6),
+ error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 51, 6),
]);
}
test_functionReference_matching() async {
await assertNoErrorsInCode('''
-void bar(void Function<T extends num>(T a) foo) {
+void foo<T extends num>(T a) {}
+void bar() {
foo<int>;
}
''');
@@ -471,7 +473,8 @@
test_functionReference_regularBounded() async {
await assertNoErrorsInCode('''
-void bar(void Function<T>(T a) foo) {
+void foo<T>(T a) {}
+void bar() {
foo<String>;
}
''');
@@ -689,4 +692,32 @@
A get foo => throw 0;
''');
}
+
+ test_typeLiteral_class() async {
+ await assertErrorsInCode('''
+class C<T extends int> {}
+var t = C<String>;
+''', [
+ error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 36, 6),
+ ]);
+ }
+
+ test_typeLiteral_functionTypeAlias() async {
+ await assertErrorsInCode('''
+typedef Cb<T extends int> = void Function();
+var t = Cb<String>;
+''', [
+ error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 56, 6),
+ ]);
+ }
+
+ test_typeLiteral_typeAlias() async {
+ await assertErrorsInCode('''
+class C {}
+typedef D<T extends int> = C;
+var t = D<String>;
+''', [
+ error(CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 51, 6),
+ ]);
+ }
}
diff --git a/pkg/analyzer/test/src/diagnostics/unqualified_reference_to_non_local_static_member_test.dart b/pkg/analyzer/test/src/diagnostics/unqualified_reference_to_non_local_static_member_test.dart
index 6551ffe..8e24064 100644
--- a/pkg/analyzer/test/src/diagnostics/unqualified_reference_to_non_local_static_member_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/unqualified_reference_to_non_local_static_member_test.dart
@@ -50,6 +50,21 @@
]);
}
+ test_methodTearoff() async {
+ await assertErrorsInCode('''
+class A {
+ static void a<T>() {}
+}
+class B extends A {
+ void b() {
+ a<int>;
+ }
+}
+''', [
+ error(_errorCode, 73, 1),
+ ]);
+ }
+
test_readWrite() async {
await assertErrorsInCode(r'''
class A {
diff --git a/pkg/analyzer/test/src/diagnostics/unqualified_reference_to_static_member_of_extended_type_test.dart b/pkg/analyzer/test/src/diagnostics/unqualified_reference_to_static_member_of_extended_type_test.dart
index 8525aa2..1cf7168 100644
--- a/pkg/analyzer/test/src/diagnostics/unqualified_reference_to_static_member_of_extended_type_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/unqualified_reference_to_static_member_of_extended_type_test.dart
@@ -51,6 +51,21 @@
]);
}
+ test_methodTearoff() async {
+ await assertErrorsInCode('''
+class MyClass {
+ static void sm<T>() {}
+}
+extension MyExtension on MyClass {
+ void m() {
+ sm<int>;
+ }
+}
+''', [
+ error(_errorCode, 95, 2),
+ ]);
+ }
+
test_readWrite() async {
await assertErrorsInCode('''
class MyClass {
diff --git a/pkg/analyzer/test/src/diagnostics/wrong_number_of_type_arguments_test.dart b/pkg/analyzer/test/src/diagnostics/wrong_number_of_type_arguments_test.dart
index ae55d6f..d743c6e 100644
--- a/pkg/analyzer/test/src/diagnostics/wrong_number_of_type_arguments_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/wrong_number_of_type_arguments_test.dart
@@ -95,23 +95,52 @@
test_functionReference_tooFew() async {
await assertErrorsInCode('''
-f(void Function<T, U>() foo) {
+f() {
+ void foo<T, U>() {}
foo<int>;
}
''', [
error(
- CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION, 36, 5),
+ CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION, 33, 5),
]);
}
test_functionReference_tooMany() async {
await assertErrorsInCode('''
-f(void Function<T>() foo) {
+f() {
+ void foo<T>() {}
foo<int, int>;
}
''', [
error(
- CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION, 33, 10),
+ CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION, 30, 10),
+ ]);
+ }
+
+ test_functionTypeExpression_tooFew() async {
+ await assertErrorsInCode('''
+f(void Function<T, U>() foo, void Function<T, U>() bar) {
+ (1 == 2 ? foo : bar)<int>;
+}
+''', [
+ error(CompileTimeErrorCode.DISALLOWED_TYPE_INSTANTIATION_EXPRESSION, 60,
+ 20),
+ error(
+ CompileTimeErrorCode
+ .WRONG_NUMBER_OF_TYPE_ARGUMENTS_ANONYMOUS_FUNCTION,
+ 80,
+ 5),
+ ]);
+ }
+
+ test_functionTypeExpression_tooMany() async {
+ await assertErrorsInCode('''
+f(void Function<T>() foo, void Function<T, U>() bar) {
+ (1 == 2 ? foo : bar)<int, String>;
+}
+''', [
+ error(CompileTimeErrorCode.DISALLOWED_TYPE_INSTANTIATION_EXPRESSION, 57,
+ 20),
]);
}
diff --git a/pkg/analyzer/test/src/lint/linter/linter_context_impl_test.dart b/pkg/analyzer/test/src/lint/linter/linter_context_impl_test.dart
index 399d2e4..4212464 100644
--- a/pkg/analyzer/test/src/lint/linter/linter_context_impl_test.dart
+++ b/pkg/analyzer/test/src/lint/linter/linter_context_impl_test.dart
@@ -28,7 +28,7 @@
Future<void> resolve(String content) async {
await resolveTestCode(content);
- var contextUnit = LinterContextUnit(result.content!, result.unit!);
+ var contextUnit = LinterContextUnit(result.content, result.unit);
final libraryElement = result.libraryElement;
final analysisContext = libraryElement.session.analysisContext;
diff --git a/pkg/analyzer/test/src/services/available_declarations_test.dart b/pkg/analyzer/test/src/services/available_declarations_test.dart
index a2e41c6..a939f53 100644
--- a/pkg/analyzer/test/src/services/available_declarations_test.dart
+++ b/pkg/analyzer/test/src/services/available_declarations_test.dart
@@ -3496,9 +3496,9 @@
newFile(a, content: 'class A {}');
newFile(b, content: 'class B {}');
newFile(c, content: 'class C {}');
- testAnalysisContext.currentSession.getFile2(a);
- testAnalysisContext.currentSession.getFile2(b);
- testAnalysisContext.currentSession.getFile2(c);
+ testAnalysisContext.currentSession.getFile(a);
+ testAnalysisContext.currentSession.getFile(b);
+ testAnalysisContext.currentSession.getFile(c);
var context = tracker.addContext(testAnalysisContext);
await _doAllTrackerWork();
diff --git a/pkg/analyzer/test/src/summary/element_text.dart b/pkg/analyzer/test/src/summary/element_text.dart
index 4243b45..f8366c5 100644
--- a/pkg/analyzer/test/src/summary/element_text.dart
+++ b/pkg/analyzer/test/src/summary/element_text.dart
@@ -361,6 +361,7 @@
});
_withIndent(() {
+ _writeMacro(e);
_writeDocumentation(e);
_writeMetadata(e);
_writeCodeRange(e);
@@ -395,17 +396,14 @@
expect(e.nameOffset, -1);
expect(e.nonSynthetic, same(e.enclosingElement));
} else {
- expect(e.nameOffset, isPositive);
+ expect(e.nameOffset, isNonNegative);
}
}
void _writeDocumentation(Element element) {
var documentation = element.documentationComment;
if (documentation != null) {
- var str = documentation;
- str = str.replaceAll('\n', r'\n');
- str = str.replaceAll('\r', r'\r');
- _writelnWithIndent('documentationComment: $str');
+ _writelnMultiLineWithIndent('documentationComment: $documentation');
}
}
@@ -521,11 +519,30 @@
buffer.writeln();
}
+ void _writelnMultiLineWithIndent(String str) {
+ str = str.replaceAll('\n', r'\n');
+ str = str.replaceAll('\r', r'\r');
+ _writelnWithIndent(str);
+ }
+
void _writelnWithIndent(String line) {
buffer.write(indent);
buffer.writeln(line);
}
+ void _writeMacro(Element e) {
+ if (e is HasMacroGenerationData) {
+ var macro = (e as HasMacroGenerationData).macro;
+ if (macro != null) {
+ _writelnWithIndent('macro');
+ _withIndent(() {
+ _writelnWithIndent('id: ${macro.id}');
+ _writelnMultiLineWithIndent('code: ${macro.code}');
+ });
+ }
+ }
+ }
+
void _writeMetadata(Element element) {
var annotations = element.metadata;
if (annotations.isNotEmpty) {
@@ -551,6 +568,7 @@
});
_withIndent(() {
+ _writeMacro(e);
_writeDocumentation(e);
_writeMetadata(e);
_writeCodeRange(e);
@@ -645,6 +663,8 @@
}
void _writePropertyAccessorElement(PropertyAccessorElement e) {
+ e as PropertyAccessorElementImpl;
+
PropertyInducingElement variable = e.variable;
expect(variable, isNotNull);
@@ -691,6 +711,7 @@
});
_withIndent(() {
+ _writeMacro(e);
_writeDocumentation(e);
_writeMetadata(e);
_writeCodeRange(e);
@@ -752,15 +773,14 @@
_writelnWithIndent('$typeStr');
}
- var aliasElement = type.aliasElement;
- var aliasArguments = type.aliasArguments;
- if (aliasElement is TypeAliasElementImpl && aliasArguments != null) {
+ var alias = type.alias;
+ if (alias != null) {
_withIndent(() {
- _createAstPrinter().writeElement('aliasElement', aliasElement);
+ _createAstPrinter().writeElement('aliasElement', alias.element);
_writeElements<DartType>(
'aliasArguments',
- aliasArguments,
+ alias.typeArguments,
_writeType,
);
});
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index 3859042..8473b16 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -16762,8 +16762,8 @@
var unit = library.definingCompilationUnit;
var type = unit.topLevelVariables[0].type as FunctionType;
- expect(type.aliasElement, same(unit.typeAliases[0]));
- _assertTypeStrings(type.aliasArguments!, ['int']);
+ expect(type.alias!.element, same(unit.typeAliases[0]));
+ _assertTypeStrings(type.alias!.typeArguments, ['int']);
}
test_functionTypeAlias_typeParameters_variance_contravariant() async {
@@ -21246,6 +21246,359 @@
''');
}
+ test_macro_autoConstructor() async {
+ addLibrarySource('/macro_annotations.dart', r'''
+library analyzer.macro.annotations;
+const autoConstructor = 0;
+''');
+ var library = await checkLibrary(r'''
+import 'macro_annotations.dart';
+@autoConstructor
+class A {
+ final int a;
+ final int? b;
+}
+''');
+ checkElementText(library, r'''
+library
+ imports
+ macro_annotations.dart
+ definingUnit
+ classes
+ class A @56
+ metadata
+ Annotation
+ atSign: @ @33
+ element: macro_annotations.dart::@getter::autoConstructor
+ name: SimpleIdentifier
+ staticElement: macro_annotations.dart::@getter::autoConstructor
+ staticType: null
+ token: autoConstructor @34
+ fields
+ final a @72
+ type: int
+ final b @88
+ type: int?
+ constructors
+ @0
+ macro
+ id: 0
+ code: A({required this.a, this.b});
+ parameters
+ requiredName final this.a @17
+ type: int
+ optionalNamed final this.b @25
+ type: int?
+ accessors
+ synthetic get a @-1
+ returnType: int
+ synthetic get b @-1
+ returnType: int?
+''');
+ }
+
+ test_macro_hashCode() async {
+ addLibrarySource('/macro_annotations.dart', r'''
+library analyzer.macro.annotations;
+const hashCode = 0;
+''');
+ var library = await checkLibrary(r'''
+import 'macro_annotations.dart';
+@hashCode
+class A {
+ final int a;
+ final int b;
+}
+''');
+ checkElementText(library, r'''
+library
+ imports
+ macro_annotations.dart
+ definingUnit
+ classes
+ class A @49
+ metadata
+ Annotation
+ atSign: @ @33
+ element: macro_annotations.dart::@getter::hashCode
+ name: SimpleIdentifier
+ staticElement: macro_annotations.dart::@getter::hashCode
+ staticType: null
+ token: hashCode @34
+ fields
+ final a @65
+ type: int
+ final b @80
+ type: int
+ synthetic hashCode @-1
+ type: int
+ constructors
+ synthetic @-1
+ accessors
+ synthetic get a @-1
+ returnType: int
+ synthetic get b @-1
+ returnType: int
+ get hashCode @18
+ macro
+ id: 0
+ code: @override\nint get hashCode => a.hashCode ^ b.hashCode;
+ metadata
+ Annotation
+ atSign: @ @0
+ element: dart:core::@getter::override
+ name: SimpleIdentifier
+ staticElement: dart:core::@getter::override
+ staticType: null
+ token: override @1
+ returnType: int
+''');
+ }
+
+ test_macro_hashCode_withSuper() async {
+ addLibrarySource('/macro_annotations.dart', r'''
+library analyzer.macro.annotations;
+const hashCode = 0;
+''');
+ var library = await checkLibrary(r'''
+import 'macro_annotations.dart';
+
+class A {
+ final int a;
+}
+
+@hashCode
+class B extends A {
+ final int b;
+}
+''');
+ checkElementText(library, r'''
+library
+ imports
+ macro_annotations.dart
+ definingUnit
+ classes
+ class A @40
+ fields
+ final a @56
+ type: int
+ constructors
+ synthetic @-1
+ accessors
+ synthetic get a @-1
+ returnType: int
+ class B @78
+ metadata
+ Annotation
+ atSign: @ @62
+ element: macro_annotations.dart::@getter::hashCode
+ name: SimpleIdentifier
+ staticElement: macro_annotations.dart::@getter::hashCode
+ staticType: null
+ token: hashCode @63
+ supertype: A
+ fields
+ final b @104
+ type: int
+ synthetic hashCode @-1
+ type: int
+ constructors
+ synthetic @-1
+ accessors
+ synthetic get b @-1
+ returnType: int
+ get hashCode @18
+ macro
+ id: 0
+ code: @override\nint get hashCode => b.hashCode ^ a.hashCode;
+ metadata
+ Annotation
+ atSign: @ @0
+ element: dart:core::@getter::override
+ name: SimpleIdentifier
+ staticElement: dart:core::@getter::override
+ staticType: null
+ token: override @1
+ returnType: int
+''');
+ }
+
+ test_macro_observable() async {
+ addLibrarySource('/macro_annotations.dart', r'''
+library analyzer.macro.annotations;
+const observable = 0;
+''');
+ var library = await checkLibrary(r'''
+import 'macro_annotations.dart';
+class A {
+ @observable
+ int _f = 0;
+}
+''');
+ checkElementText(library, r'''
+library
+ imports
+ macro_annotations.dart
+ definingUnit
+ classes
+ class A @39
+ fields
+ _f @63
+ metadata
+ Annotation
+ atSign: @ @45
+ element: macro_annotations.dart::@getter::observable
+ name: SimpleIdentifier
+ staticElement: macro_annotations.dart::@getter::observable
+ staticType: null
+ token: observable @46
+ type: int
+ synthetic f @-1
+ type: int
+ constructors
+ synthetic @-1
+ accessors
+ synthetic get _f @-1
+ returnType: int
+ synthetic set _f @-1
+ parameters
+ requiredPositional __f @-1
+ type: int
+ returnType: void
+ get f @8
+ macro
+ id: 0
+ code: int get f => _f;
+ returnType: int
+ set f @4
+ macro
+ id: 1
+ code: set f(int val) {\n print('Setting f to ${val}');\n _f = val;\n}
+ parameters
+ requiredPositional val @10
+ type: int
+ returnType: void
+''');
+ }
+
+ test_macro_observable_generic() async {
+ addLibrarySource('/macro_annotations.dart', r'''
+library analyzer.macro.annotations;
+const observable = 0;
+''');
+ var library = await checkLibrary(r'''
+import 'macro_annotations.dart';
+class A<T> {
+ @observable
+ T _f;
+}
+''');
+ checkElementText(library, r'''
+library
+ imports
+ macro_annotations.dart
+ definingUnit
+ classes
+ class A @39
+ typeParameters
+ covariant T @41
+ defaultType: dynamic
+ fields
+ _f @64
+ metadata
+ Annotation
+ atSign: @ @48
+ element: macro_annotations.dart::@getter::observable
+ name: SimpleIdentifier
+ staticElement: macro_annotations.dart::@getter::observable
+ staticType: null
+ token: observable @49
+ type: T
+ synthetic f @-1
+ type: T
+ constructors
+ synthetic @-1
+ accessors
+ synthetic get _f @-1
+ returnType: T
+ synthetic set _f @-1
+ parameters
+ requiredPositional __f @-1
+ type: T
+ returnType: void
+ get f @6
+ macro
+ id: 0
+ code: T get f => _f;
+ returnType: T
+ set f @4
+ macro
+ id: 1
+ code: set f(T val) {\n print('Setting f to ${val}');\n _f = val;\n}
+ parameters
+ requiredPositional val @8
+ type: T
+ returnType: void
+''');
+ }
+
+ test_macro_toString() async {
+ addLibrarySource('/macro_annotations.dart', r'''
+library analyzer.macro.annotations;
+const toString = 0;
+''');
+ var library = await checkLibrary(r'''
+import 'macro_annotations.dart';
+@toString
+class A {
+ final int a;
+ final int b;
+}
+''');
+ checkElementText(library, r'''
+library
+ imports
+ macro_annotations.dart
+ definingUnit
+ classes
+ class A @49
+ metadata
+ Annotation
+ atSign: @ @33
+ element: macro_annotations.dart::@getter::toString
+ name: SimpleIdentifier
+ staticElement: macro_annotations.dart::@getter::toString
+ staticType: null
+ token: toString @34
+ fields
+ final a @65
+ type: int
+ final b @80
+ type: int
+ constructors
+ synthetic @-1
+ accessors
+ synthetic get a @-1
+ returnType: int
+ synthetic get b @-1
+ returnType: int
+ methods
+ toString @17
+ macro
+ id: 0
+ code: @override\nString toString() => 'A(a: $a, b: $b)';
+ metadata
+ Annotation
+ atSign: @ @0
+ element: dart:core::@getter::override
+ name: SimpleIdentifier
+ staticElement: dart:core::@getter::override
+ staticType: null
+ token: override @1
+ returnType: String
+''');
+ }
+
test_main_class() async {
var library = await checkLibrary('class main {}');
checkElementText(library, r'''
diff --git a/pkg/analyzer/test/src/summary/top_level_inference_test.dart b/pkg/analyzer/test/src/summary/top_level_inference_test.dart
index b10c777..feb2509 100644
--- a/pkg/analyzer/test/src/summary/top_level_inference_test.dart
+++ b/pkg/analyzer/test/src/summary/top_level_inference_test.dart
@@ -6116,7 +6116,7 @@
var path = convertPath(testFilePath);
var analysisSession = contextFor(path).currentSession;
- var result = await analysisSession.getUnitElement2(path);
+ var result = await analysisSession.getUnitElement(path);
result as UnitElementResult;
return result.element.library;
}
diff --git a/pkg/analyzer/test/src/task/strong/dart2_inference_test.dart b/pkg/analyzer/test/src/task/strong/dart2_inference_test.dart
index e7b1ac5..87a1477 100644
--- a/pkg/analyzer/test/src/task/strong/dart2_inference_test.dart
+++ b/pkg/analyzer/test/src/task/strong/dart2_inference_test.dart
@@ -347,8 +347,8 @@
}
void _assertTypeAnnotations() {
- var code = result.content!;
- var unit = result.unit!;
+ var code = result.content;
+ var unit = result.unit;
var types = <int, String>{};
{
diff --git a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
index 21fa9c9..4840db6 100644
--- a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
+++ b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
@@ -22,7 +22,7 @@
// TODO(https://github.com/dart-lang/sdk/issues/44666): Use null safety in
// test cases.
CompilationUnitElement get _resultUnitElement {
- return result.unit!.declaredElement!;
+ return result.unit.declaredElement!;
}
test_asyncClosureReturnType_flatten() async {
diff --git a/pkg/analyzer/test/util/id_testing_helper.dart b/pkg/analyzer/test/util/id_testing_helper.dart
index 6d75b6f..f192694 100644
--- a/pkg/analyzer/test/util/id_testing_helper.dart
+++ b/pkg/analyzer/test/util/id_testing_helper.dart
@@ -196,7 +196,7 @@
});
} else {
String _formatError(AnalysisError e) {
- var locationInfo = result.unit!.lineInfo!.getLocation(e.offset);
+ var locationInfo = result.unit.lineInfo!.getLocation(e.offset);
return '$locationInfo: ${e.errorCode}: ${e.message}';
}
@@ -209,7 +209,7 @@
results.forEach((testUri, result) {
dataComputer.computeUnitData(
- driver.testingData!, result.unit!, actualMapFor(testUri));
+ driver.testingData!, result.unit, actualMapFor(testUri));
});
var compiledData = AnalyzerCompiledData<T>(
testData.code, testData.entryPoint, actualMaps, globalData);
diff --git a/pkg/analyzer/test/verify_diagnostics_test.dart b/pkg/analyzer/test/verify_diagnostics_test.dart
index 648fbf0..d8d7076 100644
--- a/pkg/analyzer/test/verify_diagnostics_test.dart
+++ b/pkg/analyzer/test/verify_diagnostics_test.dart
@@ -287,7 +287,7 @@
/// [path] and return the result.
ParsedUnitResult _parse(AnalysisContextCollection collection, String path) {
AnalysisSession session = collection.contextFor(path).currentSession;
- var result = session.getParsedUnit2(path);
+ var result = session.getParsedUnit(path);
if (result is! ParsedUnitResult) {
throw StateError('Unable to parse "$path"');
}
@@ -321,7 +321,7 @@
/// Extract documentation from the file that was parsed to produce the given
/// [result].
Future<void> _validateFile(ParsedUnitResult result) async {
- filePath = result.path!;
+ filePath = result.path;
hasWrittenFilePath = false;
CompilationUnit unit = result.unit;
for (CompilationUnitMember declaration in unit.declarations) {
@@ -420,6 +420,7 @@
/// codes.
@reflectiveTest
class VerifyDiagnosticsTest {
+ @TestTimeout(Timeout.factor(4))
test_diagnostics() async {
Context pathContext = PhysicalResourceProvider.INSTANCE.pathContext;
List<CodePath> codePaths = computeCodePaths();
diff --git a/pkg/analyzer/test/verify_docs_test.dart b/pkg/analyzer/test/verify_docs_test.dart
index 8ffc750..b01d307 100644
--- a/pkg/analyzer/test/verify_docs_test.dart
+++ b/pkg/analyzer/test/verify_docs_test.dart
@@ -118,7 +118,7 @@
if (contexts.length != 1) {
fail('The snippets directory contains multiple analysis contexts.');
}
- var results = await contexts[0].currentSession.getErrors2(snippetPath);
+ var results = await contexts[0].currentSession.getErrors(snippetPath);
if (results is ErrorsResult) {
Iterable<AnalysisError> errors = results.errors.where((error) {
ErrorCode errorCode = error.errorCode;
diff --git a/pkg/analyzer/tool/diagnostics/generate.dart b/pkg/analyzer/tool/diagnostics/generate.dart
index 927bbf2..e431fb0 100644
--- a/pkg/analyzer/tool/diagnostics/generate.dart
+++ b/pkg/analyzer/tool/diagnostics/generate.dart
@@ -363,7 +363,7 @@
/// [path] and return the result.
ParsedUnitResult _parse(AnalysisContextCollection collection, String path) {
AnalysisSession session = collection.contextFor(path).currentSession;
- var result = session.getParsedUnit2(path);
+ var result = session.getParsedUnit(path);
if (result is! ParsedUnitResult) {
throw StateError('Unable to parse "$path"');
}
diff --git a/pkg/analyzer_cli/lib/src/driver.dart b/pkg/analyzer_cli/lib/src/driver.dart
index 5b0948e..28e3590 100644
--- a/pkg/analyzer_cli/lib/src/driver.dart
+++ b/pkg/analyzer_cli/lib/src/driver.dart
@@ -382,7 +382,7 @@
Iterable<io.File> _collectFiles(String filePath, AnalysisOptions options) {
var files = <io.File>[];
var file = io.File(filePath);
- if (file.existsSync() && !pathFilter.ignored(filePath)) {
+ if (file.existsSync()) {
files.add(file);
} else {
var directory = io.Directory(filePath);
@@ -431,7 +431,7 @@
}
void _verifyAnalysisOptionsFileExists(CommandLineOptions options) {
- var path = options.analysisOptionsFile;
+ var path = options.defaultAnalysisOptionsPath;
if (path != null) {
if (!resourceProvider.getFile(path).exists) {
printAndFail('Options file not found: $path',
@@ -449,8 +449,8 @@
CommandLineOptions previous, CommandLineOptions newOptions) {
return previous != null &&
newOptions != null &&
- newOptions.packageConfigPath == previous.packageConfigPath &&
- _equalMaps(newOptions.definedVariables, previous.definedVariables) &&
+ newOptions.defaultPackagesPath == previous.defaultPackagesPath &&
+ _equalMaps(newOptions.declaredVariables, previous.declaredVariables) &&
newOptions.log == previous.log &&
newOptions.disableHints == previous.disableHints &&
newOptions.showPackageWarnings == previous.showPackageWarnings &&
@@ -554,8 +554,8 @@
_collection = AnalysisContextCollectionImpl(
byteStore: Driver.analysisDriverMemoryByteStore,
includedPaths: _pathList,
- optionsFile: _commandLineOptions.analysisOptionsFile,
- packagesFile: _commandLineOptions.packageConfigPath,
+ optionsFile: _commandLineOptions.defaultAnalysisOptionsPath,
+ packagesFile: _commandLineOptions.defaultPackagesPath,
resourceProvider: _resourceProvider,
sdkPath: _commandLineOptions.dartSdkPath,
updateAnalysisOptions: _updateAnalysisOptions,
diff --git a/pkg/analyzer_cli/lib/src/options.dart b/pkg/analyzer_cli/lib/src/options.dart
index bb2da44..7ec27d6 100644
--- a/pkg/analyzer_cli/lib/src/options.dart
+++ b/pkg/analyzer_cli/lib/src/options.dart
@@ -6,7 +6,6 @@
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/src/context/builder.dart';
import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
import 'package:analyzer/src/util/file_paths.dart' as file_paths;
@@ -51,8 +50,18 @@
class CommandLineOptions {
final ArgResults _argResults;
- /// The options defining the context in which analysis is performed.
- final ContextBuilderOptions contextBuilderOptions;
+ /// The file path of the analysis options file that should be used in place of
+ /// any file in the root directory or a parent of the root directory,
+ /// or `null` if the normal lookup mechanism should be used.
+ String defaultAnalysisOptionsPath;
+
+ /// The file path of the .packages file that should be used in place of any
+ /// file found using the normal (Package Specification DEP) lookup mechanism,
+ /// or `null` if the normal lookup mechanism should be used.
+ String defaultPackagesPath;
+
+ /// A table mapping variable names to values for the declared variables.
+ final Map<String, String> declaredVariables = {};
/// The path to the dart SDK.
String dartSdkPath;
@@ -124,10 +133,6 @@
ResourceProvider resourceProvider,
ArgResults args,
) : _argResults = args,
- contextBuilderOptions = _createContextBuilderOptions(
- resourceProvider,
- args,
- ),
dartSdkPath = cast(args[_sdkPathOption]),
disableCacheFlushing = cast(args['disable-cache-flushing']),
disableHints = cast(args['no-hints']),
@@ -149,11 +154,41 @@
lintsAreFatal = cast(args['fatal-lints']),
trainSnapshot = cast(args['train-snapshot']),
verbose = cast(args['verbose']),
- color = cast(args['color']);
+ color = cast(args['color']) {
+ //
+ // File locations.
+ //
+ defaultAnalysisOptionsPath = _absoluteNormalizedPath(
+ resourceProvider,
+ cast(args[_analysisOptionsFileOption]),
+ );
+ defaultPackagesPath = _absoluteNormalizedPath(
+ resourceProvider,
+ cast(args[_packagesOption]),
+ );
- /// The path to an analysis options file
- String get analysisOptionsFile =>
- contextBuilderOptions.defaultAnalysisOptionsFilePath;
+ //
+ // Declared variables.
+ //
+ var variables = (args[_defineVariableOption] as List).cast<String>();
+ for (var variable in variables) {
+ var index = variable.indexOf('=');
+ if (index < 0) {
+ // TODO (brianwilkerson) Decide the semantics we want in this case.
+ // The VM prints "No value given to -D option", then tries to load '-Dfoo'
+ // as a file and dies. Unless there was nothing after the '-D', in which
+ // case it prints the warning and ignores the option.
+ } else {
+ var name = variable.substring(0, index);
+ if (name.isNotEmpty) {
+ // TODO (brianwilkerson) Decide the semantics we want in the case where
+ // there is no name. If there is no name, the VM tries to load a file
+ // named '-D' and dies.
+ declaredVariables[name] = variable.substring(index + 1);
+ }
+ }
+ }
+ }
/// The default language version for files that are not in a package.
/// (Or null if no default language version to force.)
@@ -161,10 +196,6 @@
return cast(_argResults[_defaultLanguageVersionOption]);
}
- /// A table mapping the names of defined variables to their values.
- Map<String, String> get definedVariables =>
- contextBuilderOptions.declaredVariables;
-
/// A list of the names of the experiments that are to be enabled.
List<String> get enabledExperiments {
return cast(_argResults[_enableExperimentOption]);
@@ -176,9 +207,6 @@
bool get noImplicitDynamic => _argResults[_noImplicitDynamicFlag] as bool;
- /// The path to a `.packages` configuration file
- String get packageConfigPath => contextBuilderOptions.defaultPackageFilePath;
-
/// Update the [analysisOptions] with flags that the user specified
/// explicitly. The [analysisOptions] are usually loaded from one of
/// `analysis_options.yaml` files, possibly with includes. We consider
@@ -307,57 +335,17 @@
return options;
}
- /// Use the command-line [args] to create a context builder options.
- static ContextBuilderOptions _createContextBuilderOptions(
+ static String _absoluteNormalizedPath(
ResourceProvider resourceProvider,
- ArgResults args,
+ String path,
) {
- String absoluteNormalizedPath(String path) {
- if (path == null) {
- return null;
- }
- var pathContext = resourceProvider.pathContext;
- return pathContext.normalize(
- pathContext.absolute(path),
- );
+ if (path == null) {
+ return null;
}
-
- var builderOptions = ContextBuilderOptions();
-
- //
- // File locations.
- //
- builderOptions.defaultAnalysisOptionsFilePath = absoluteNormalizedPath(
- cast(args[_analysisOptionsFileOption]),
+ var pathContext = resourceProvider.pathContext;
+ return pathContext.normalize(
+ pathContext.absolute(path),
);
- builderOptions.defaultPackageFilePath = absoluteNormalizedPath(
- cast(args[_packagesOption]),
- );
- //
- // Declared variables.
- //
- var declaredVariables = <String, String>{};
- var variables = (args[_defineVariableOption] as List).cast<String>();
- for (var variable in variables) {
- var index = variable.indexOf('=');
- if (index < 0) {
- // TODO (brianwilkerson) Decide the semantics we want in this case.
- // The VM prints "No value given to -D option", then tries to load '-Dfoo'
- // as a file and dies. Unless there was nothing after the '-D', in which
- // case it prints the warning and ignores the option.
- } else {
- var name = variable.substring(0, index);
- if (name.isNotEmpty) {
- // TODO (brianwilkerson) Decide the semantics we want in the case where
- // there is no name. If there is no name, the VM tries to load a file
- // named '-D' and dies.
- declaredVariables[name] = variable.substring(index + 1);
- }
- }
- }
- builderOptions.declaredVariables = declaredVariables;
-
- return builderOptions;
}
/// Add the standard flags and options to the given [parser]. The standard flags
diff --git a/pkg/analyzer_cli/lib/src/perf_report.dart b/pkg/analyzer_cli/lib/src/perf_report.dart
index 25c21c5..04caa35 100644
--- a/pkg/analyzer_cli/lib/src/perf_report.dart
+++ b/pkg/analyzer_cli/lib/src/perf_report.dart
@@ -38,8 +38,8 @@
'showPackageWarnings': options.showPackageWarnings,
'showPackageWarningsPrefix': options.showPackageWarningsPrefix,
'showSdkWarnings': options.showSdkWarnings,
- 'definedVariables': options.definedVariables,
- 'packageConfigPath': options.packageConfigPath,
+ 'definedVariables': options.declaredVariables,
+ 'packageConfigPath': options.defaultPackagesPath,
'sourceFiles': options.sourceFiles,
};
diff --git a/pkg/analyzer_cli/test/driver_test.dart b/pkg/analyzer_cli/test/driver_test.dart
index 419aceb..19d778d 100644
--- a/pkg/analyzer_cli/test/driver_test.dart
+++ b/pkg/analyzer_cli/test/driver_test.dart
@@ -73,7 +73,9 @@
path.join(testDirectory, options),
];
}
- cmd..addAll(sources.map(_adjustFileSpec))..addAll(args);
+ cmd
+ ..addAll(sources.map(_adjustFileSpec))
+ ..addAll(args);
await driver.start(cmd);
}
@@ -390,6 +392,20 @@
ErrorProcessor processorFor(AnalysisError error) =>
processors.firstWhere((p) => p.appliesTo(error));
+ /// If a file is specified explicitly, it should be analyzed, even if
+ /// it is excluded. Excludes work when an including directory is specified.
+ Future<void> test_analysisOptions_excluded_requested() async {
+ await drive(
+ 'data/exclude_test_project/lib/excluded_error.dart',
+ options: 'data/exclude_test_project/$analysisOptionsYaml',
+ );
+ expect(
+ bulletToDash(outSink),
+ contains("error - Undefined class 'ExcludedUndefinedClass'"),
+ );
+ expect(outSink.toString(), contains('1 error found.'));
+ }
+
Future<void> test_analysisOptions_excludes() async {
await drive('data/exclude_test_project',
options: 'data/exclude_test_project/$analysisOptionsYaml');
diff --git a/pkg/analyzer_cli/test/options_test.dart b/pkg/analyzer_cli/test/options_test.dart
index 242c86d..4b7167b 100644
--- a/pkg/analyzer_cli/test/options_test.dart
+++ b/pkg/analyzer_cli/test/options_test.dart
@@ -84,8 +84,8 @@
test('defined variables', () {
var options = parse(['--dart-sdk', '.', '-Dfoo=bar', 'foo.dart']);
- expect(options.definedVariables['foo'], equals('bar'));
- expect(options.definedVariables['bar'], isNull);
+ expect(options.declaredVariables['foo'], equals('bar'));
+ expect(options.declaredVariables['bar'], isNull);
});
test('disable cache flushing', () {
@@ -210,7 +210,7 @@
test('options', () {
var options =
parse(['--dart-sdk', '.', '--options', 'options.yaml', 'foo.dart']);
- expect(options.analysisOptionsFile, endsWith('options.yaml'));
+ expect(options.defaultAnalysisOptionsPath, endsWith('options.yaml'));
});
test('lints', () {
@@ -284,8 +284,7 @@
void test_declaredVariables() {
_parse(['-Da=0', '-Db=', 'a.dart']);
- var options = commandLineOptions.contextBuilderOptions;
- var definedVariables = options.declaredVariables;
+ var definedVariables = commandLineOptions.declaredVariables;
expect(definedVariables['a'], '0');
expect(definedVariables['b'], '');
@@ -296,9 +295,8 @@
var expected = 'my_options.yaml';
_parse(['--options=$expected', 'a.dart']);
- var builderOptions = commandLineOptions.contextBuilderOptions;
expect(
- builderOptions.defaultAnalysisOptionsFilePath,
+ commandLineOptions.defaultAnalysisOptionsPath,
endsWith(expected),
);
}
@@ -307,21 +305,17 @@
var expected = 'my_package_config.json';
_parse(['--packages=$expected', 'a.dart']);
- var builderOptions = commandLineOptions.contextBuilderOptions;
expect(
- builderOptions.defaultPackageFilePath,
+ commandLineOptions.defaultPackagesPath,
endsWith(expected),
);
}
void test_defaults() {
_parse(['a.dart']);
- var builderOptions = commandLineOptions.contextBuilderOptions;
- expect(builderOptions, isNotNull);
- expect(builderOptions.dartSdkSummaryPath, isNull);
- expect(builderOptions.declaredVariables, isEmpty);
- expect(builderOptions.defaultAnalysisOptionsFilePath, isNull);
- expect(builderOptions.defaultPackageFilePath, isNull);
+ expect(commandLineOptions.declaredVariables, isEmpty);
+ expect(commandLineOptions.defaultAnalysisOptionsPath, isNull);
+ expect(commandLineOptions.defaultPackagesPath, isNull);
}
void test_filterUnknownArguments() {
diff --git a/pkg/analyzer_plugin/CHANGELOG.md b/pkg/analyzer_plugin/CHANGELOG.md
index a2d2707..3ee89a3 100644
--- a/pkg/analyzer_plugin/CHANGELOG.md
+++ b/pkg/analyzer_plugin/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.7.0
+
+- Support verison `2.x` of the `analyzer` package
+
## 0.6.0
- Bug fixes to the protocol.
diff --git a/pkg/analyzer_plugin/doc/api.html b/pkg/analyzer_plugin/doc/api.html
index dbe9f26..96c8505 100644
--- a/pkg/analyzer_plugin/doc/api.html
+++ b/pkg/analyzer_plugin/doc/api.html
@@ -1579,13 +1579,13 @@
The one-based index of the column containing the first character of
the range.
</p>
- </dd><dt class="field"><b>endLine: int</b></dt><dd>
+ </dd><dt class="field"><b>endLine: int<span style="color:#999999"> (optional)</span></b></dt><dd>
<p>
The one-based index of the line containing the character immediately
following the range.
</p>
- </dd><dt class="field"><b>endColumn: int</b></dt><dd>
+ </dd><dt class="field"><b>endColumn: int<span style="color:#999999"> (optional)</span></b></dt><dd>
<p>
The one-based index of the column containing the character immediately
diff --git a/pkg/analyzer_plugin/lib/plugin/navigation_mixin.dart b/pkg/analyzer_plugin/lib/plugin/navigation_mixin.dart
index de11deb..07dbddb 100644
--- a/pkg/analyzer_plugin/lib/plugin/navigation_mixin.dart
+++ b/pkg/analyzer_plugin/lib/plugin/navigation_mixin.dart
@@ -27,7 +27,7 @@
var length = parameters.length;
if (offset < 0 && length < 0) {
offset = 0;
- length = result.content?.length ?? 0;
+ length = result.content.length;
}
return DartNavigationRequestImpl(resourceProvider, offset, length, result);
}
diff --git a/pkg/analyzer_plugin/lib/protocol/protocol_common.dart b/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
index 691c48d..e437a89 100644
--- a/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
+++ b/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
@@ -2884,8 +2884,8 @@
/// "length": int
/// "startLine": int
/// "startColumn": int
-/// "endLine": int
-/// "endColumn": int
+/// "endLine": optional int
+/// "endColumn": optional int
/// }
///
/// Clients may not extend, implement or mix-in this class.
@@ -2909,14 +2909,15 @@
/// The one-based index of the line containing the character immediately
/// following the range.
- int endLine;
+ int? endLine;
/// The one-based index of the column containing the character immediately
/// following the range.
- int endColumn;
+ int? endColumn;
- Location(this.file, this.offset, this.length, this.startLine,
- this.startColumn, this.endLine, this.endColumn);
+ Location(
+ this.file, this.offset, this.length, this.startLine, this.startColumn,
+ {this.endLine, this.endColumn});
factory Location.fromJson(
JsonDecoder jsonDecoder, String jsonPath, Object? json) {
@@ -2954,21 +2955,17 @@
} else {
throw jsonDecoder.mismatch(jsonPath, 'startColumn');
}
- int endLine;
+ int? endLine;
if (json.containsKey('endLine')) {
endLine = jsonDecoder.decodeInt(jsonPath + '.endLine', json['endLine']);
- } else {
- throw jsonDecoder.mismatch(jsonPath, 'endLine');
}
- int endColumn;
+ int? endColumn;
if (json.containsKey('endColumn')) {
endColumn =
jsonDecoder.decodeInt(jsonPath + '.endColumn', json['endColumn']);
- } else {
- throw jsonDecoder.mismatch(jsonPath, 'endColumn');
}
- return Location(
- file, offset, length, startLine, startColumn, endLine, endColumn);
+ return Location(file, offset, length, startLine, startColumn,
+ endLine: endLine, endColumn: endColumn);
} else {
throw jsonDecoder.mismatch(jsonPath, 'Location', json);
}
@@ -2982,8 +2979,14 @@
result['length'] = length;
result['startLine'] = startLine;
result['startColumn'] = startColumn;
- result['endLine'] = endLine;
- result['endColumn'] = endColumn;
+ var endLine = this.endLine;
+ if (endLine != null) {
+ result['endLine'] = endLine;
+ }
+ var endColumn = this.endColumn;
+ if (endColumn != null) {
+ result['endColumn'] = endColumn;
+ }
return result;
}
diff --git a/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_core.dart b/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_core.dart
index ab273d2..0e6ea1a 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_core.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_core.dart
@@ -246,13 +246,13 @@
}
var session = workspace.getSession(path);
- var result = await session?.getResolvedUnit2(path);
+ var result = await session?.getResolvedUnit(path);
if (result is! ResolvedUnitResult) {
throw AnalysisException('Cannot analyze "$path"');
}
var timeStamp = result.exists ? 0 : -1;
- var declaredUnit = result.unit?.declaredElement;
+ var declaredUnit = result.unit.declaredElement;
var libraryUnit = declaredUnit?.library.definingCompilationUnit;
DartFileEditBuilderImpl? libraryEditBuilder;
diff --git a/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart b/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
index 12e92b5..7d86a7f 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
@@ -1155,12 +1155,11 @@
return false;
}
- var aliasElement = type.aliasElement;
- var aliasArguments = type.aliasArguments;
- if (aliasElement != null && aliasArguments != null) {
+ var alias = type.alias;
+ if (alias != null) {
_writeTypeElementArguments(
- element: aliasElement,
- typeArguments: aliasArguments,
+ element: alias.element,
+ typeArguments: alias.typeArguments,
methodBeingCopied: methodBeingCopied,
);
_writeTypeNullability(type);
@@ -1281,7 +1280,7 @@
/// the given [resolvedUnit] and [timeStamp].
DartFileEditBuilderImpl(ChangeBuilderImpl changeBuilder, this.resolvedUnit,
int timeStamp, this.libraryChangeBuilder)
- : super(changeBuilder, resolvedUnit.path!, timeStamp);
+ : super(changeBuilder, resolvedUnit.path, timeStamp);
@override
bool get hasEdits =>
@@ -1353,7 +1352,7 @@
@override
void format(SourceRange range) {
- var newContent = resolvedUnit.content!;
+ var newContent = resolvedUnit.content;
var newRangeOffset = range.offset;
var newRangeLength = range.length;
for (var edit in fileEdit.edits) {
@@ -1437,7 +1436,7 @@
LibraryDirective? libraryDirective;
var importDirectives = <ImportDirective>[];
PartDirective? partDirective;
- var unit = resolvedUnit.unit!;
+ var unit = resolvedUnit.unit;
for (var directive in unit.directives) {
if (directive is LibraryDirective) {
libraryDirective = directive;
diff --git a/pkg/analyzer_plugin/lib/src/utilities/folding/folding.dart b/pkg/analyzer_plugin/lib/src/utilities/folding/folding.dart
index a302a76..d424abf 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/folding/folding.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/folding/folding.dart
@@ -21,7 +21,7 @@
DartFoldingRequestImpl(this.resourceProvider, this.result);
@override
- String get path => result.path!;
+ String get path => result.path;
}
/// A concrete implementation of [FoldingCollector].
diff --git a/pkg/analyzer_plugin/lib/src/utilities/highlights/highlights.dart b/pkg/analyzer_plugin/lib/src/utilities/highlights/highlights.dart
index 5e55b48..95bd889 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/highlights/highlights.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/highlights/highlights.dart
@@ -21,7 +21,7 @@
DartHighlightsRequestImpl(this.resourceProvider, this.result);
@override
- String get path => result.path!;
+ String get path => result.path;
}
/// A concrete implementation of [HighlightsCollector].
diff --git a/pkg/analyzer_plugin/lib/src/utilities/kythe/entries.dart b/pkg/analyzer_plugin/lib/src/utilities/kythe/entries.dart
index 191101c..684e9e7 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/kythe/entries.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/kythe/entries.dart
@@ -19,7 +19,7 @@
DartEntryRequestImpl(this.resourceProvider, this.result);
@override
- String get path => result.path!;
+ String get path => result.path;
}
/// A concrete implementation of [EntryCollector].
diff --git a/pkg/analyzer_plugin/lib/src/utilities/navigation/navigation.dart b/pkg/analyzer_plugin/lib/src/utilities/navigation/navigation.dart
index 4e1850c..23709a3 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/navigation/navigation.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/navigation/navigation.dart
@@ -28,7 +28,7 @@
this.resourceProvider, this.offset, this.length, this.result);
@override
- String get path => result.path!;
+ String get path => result.path;
}
/// A concrete implementation of [NavigationCollector].
diff --git a/pkg/analyzer_plugin/lib/src/utilities/occurrences/occurrences.dart b/pkg/analyzer_plugin/lib/src/utilities/occurrences/occurrences.dart
index 6bd0592..f436774 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/occurrences/occurrences.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/occurrences/occurrences.dart
@@ -20,7 +20,7 @@
DartOccurrencesRequestImpl(this.resourceProvider, this.result);
@override
- String get path => result.path!;
+ String get path => result.path;
}
/// A concrete implementation of [OccurrencesCollector].
diff --git a/pkg/analyzer_plugin/lib/src/utilities/outline/outline.dart b/pkg/analyzer_plugin/lib/src/utilities/outline/outline.dart
index 44d4dd9..284f140 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/outline/outline.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/outline/outline.dart
@@ -20,7 +20,7 @@
DartOutlineRequestImpl(this.resourceProvider, this.result);
@override
- String get path => result.path!;
+ String get path => result.path;
}
/// A concrete implementation of [OutlineCollector].
diff --git a/pkg/analyzer_plugin/lib/utilities/analyzer_converter.dart b/pkg/analyzer_plugin/lib/utilities/analyzer_converter.dart
index 87af1a3..575cd5b 100644
--- a/pkg/analyzer_plugin/lib/utilities/analyzer_converter.dart
+++ b/pkg/analyzer_plugin/lib/utilities/analyzer_converter.dart
@@ -48,8 +48,9 @@
return plugin.AnalysisError(
convertErrorSeverity(severity),
convertErrorType(errorCode.type),
- plugin.Location(error.source.fullName, offset, error.length, startLine,
- startColumn, endLine, endColumn),
+ plugin.Location(
+ error.source.fullName, offset, error.length, startLine, startColumn,
+ endLine: endLine, endColumn: endColumn),
error.message,
errorCode.name.toLowerCase(),
contextMessages: contextMessages,
@@ -107,8 +108,8 @@
}
return plugin.DiagnosticMessage(
message.messageText(includeUrl: true),
- plugin.Location(
- file, offset, length, startLine, startColumn, endLine, endColumn));
+ plugin.Location(file, offset, length, startLine, startColumn,
+ endLine: endLine, endColumn: endColumn));
}
/// Convert the given [element] from the 'analyzer' package to an element
@@ -407,6 +408,7 @@
// Ignore exceptions
}
return plugin.Location(unitElement.source.fullName, range.offset,
- range.length, startLine, startColumn, endLine, endColumn);
+ range.length, startLine, startColumn,
+ endLine: endLine, endColumn: endColumn);
}
}
diff --git a/pkg/analyzer_plugin/lib/utilities/completion/inherited_reference_contributor.dart b/pkg/analyzer_plugin/lib/utilities/completion/inherited_reference_contributor.dart
index a605f4e..cf0a57b 100644
--- a/pkg/analyzer_plugin/lib/utilities/completion/inherited_reference_contributor.dart
+++ b/pkg/analyzer_plugin/lib/utilities/completion/inherited_reference_contributor.dart
@@ -35,7 +35,7 @@
Future<void> computeSuggestions(
DartCompletionRequest request, CompletionCollector collector) async {
var target =
- CompletionTarget.forOffset(request.result.unit!, request.offset);
+ CompletionTarget.forOffset(request.result.unit, request.offset);
var optype = OpType.forCompletion(target, request.offset);
if (!optype.includeIdentifiers) {
return;
@@ -59,7 +59,7 @@
CompletionTarget? target,
OpType? optype,
}) async {
- target ??= CompletionTarget.forOffset(request.result.unit!, request.offset,
+ target ??= CompletionTarget.forOffset(request.result.unit, request.offset,
entryPoint: entryPoint);
optype ??= OpType.forCompletion(target, request.offset);
if (!optype.includeIdentifiers) {
diff --git a/pkg/analyzer_plugin/lib/utilities/completion/type_member_contributor.dart b/pkg/analyzer_plugin/lib/utilities/completion/type_member_contributor.dart
index 1009c12..d190e3d 100644
--- a/pkg/analyzer_plugin/lib/utilities/completion/type_member_contributor.dart
+++ b/pkg/analyzer_plugin/lib/utilities/completion/type_member_contributor.dart
@@ -53,7 +53,7 @@
Expression? _computeDotTarget(
DartCompletionRequest request, AstNode? entryPoint) {
var target = CompletionTarget.forOffset(
- request.result.unit!, request.offset,
+ request.result.unit, request.offset,
entryPoint: entryPoint);
var node = target.containingNode;
if (node is MethodInvocation) {
diff --git a/pkg/analyzer_plugin/lib/utilities/navigation/navigation_dart.dart b/pkg/analyzer_plugin/lib/utilities/navigation/navigation_dart.dart
index e409097a..c161993 100644
--- a/pkg/analyzer_plugin/lib/utilities/navigation/navigation_dart.dart
+++ b/pkg/analyzer_plugin/lib/utilities/navigation/navigation_dart.dart
@@ -178,7 +178,7 @@
return null;
}
- var parsedLibrary = session.getParsedLibrary2(libraryPath);
+ var parsedLibrary = session.getParsedLibrary(libraryPath);
if (parsedLibrary is! ParsedLibraryResult) {
return null;
}
@@ -261,7 +261,8 @@
uriNode.offset,
uriNode.length,
protocol.ElementKind.LIBRARY,
- protocol.Location(source.fullName, 0, 0, 0, 0, 0, 0));
+ protocol.Location(source.fullName, 0, 0, 0, 0,
+ endLine: 0, endColumn: 0));
}
}
}
diff --git a/pkg/analyzer_plugin/pubspec.yaml b/pkg/analyzer_plugin/pubspec.yaml
index 1ee70fe..7b0003e 100644
--- a/pkg/analyzer_plugin/pubspec.yaml
+++ b/pkg/analyzer_plugin/pubspec.yaml
@@ -1,13 +1,13 @@
name: analyzer_plugin
description: A framework and support code for building plugins for the analysis server.
-version: 0.6.0
+version: 0.7.0
homepage: https://github.com/dart-lang/sdk/tree/master/pkg/analyzer_plugin
environment:
sdk: '>=2.12.0 <3.0.0'
dependencies:
- analyzer: ^1.5.0
+ analyzer: ^2.0.0
collection: ^1.15.0
dart_style: ^2.0.0
pub_semver: ^2.0.0
diff --git a/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart b/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
index 5c52f19..4ed7683 100644
--- a/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
+++ b/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
@@ -591,15 +591,16 @@
/// "length": int
/// "startLine": int
/// "startColumn": int
-/// "endLine": int
-/// "endColumn": int
+/// "endLine": optional int
+/// "endColumn": optional int
/// }
final Matcher isLocation = LazyMatcher(() => MatchesJsonObject('Location', {
'file': isFilePath,
'offset': isInt,
'length': isInt,
'startLine': isInt,
- 'startColumn': isInt,
+ 'startColumn': isInt
+ }, optionalFields: {
'endLine': isInt,
'endColumn': isInt
}));
diff --git a/pkg/analyzer_plugin/test/plugin/navigation_mixin_test.dart b/pkg/analyzer_plugin/test/plugin/navigation_mixin_test.dart
index 2c3dcfd..3c29dfb 100644
--- a/pkg/analyzer_plugin/test/plugin/navigation_mixin_test.dart
+++ b/pkg/analyzer_plugin/test/plugin/navigation_mixin_test.dart
@@ -80,8 +80,8 @@
void computeNavigation(
NavigationRequest request, NavigationCollector collector) {
for (var i = 0; i < regionCount; i++) {
- collector.addRegion(
- i, 5, ElementKind.METHOD, Location('a', 5, 5, 1, 5, 1, 10));
+ collector.addRegion(i, 5, ElementKind.METHOD,
+ Location('a', 5, 5, 1, 5, endLine: 1, endColumn: 10));
}
}
}
diff --git a/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart b/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart
index 7d3e886..fd398ed 100644
--- a/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart
+++ b/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart
@@ -790,7 +790,7 @@
addSource(path, content);
var unit = (await resolveFile(path)).unit;
- var A = unit?.declarations[1] as ClassDeclaration;
+ var A = unit.declarations[1] as ClassDeclaration;
var builder = newBuilder();
await builder.addDartFileEdit(path, (builder) {
@@ -821,7 +821,7 @@
addSource(path, content);
var unit = (await resolveFile(path)).unit;
- var A = unit?.declarations[1] as ClassDeclaration;
+ var A = unit.declarations[1] as ClassDeclaration;
var builder = newBuilder();
await builder.addDartFileEdit(path, (builder) {
@@ -857,7 +857,7 @@
addSource(path, content);
var unit = (await resolveFile(path)).unit;
- var A = unit?.declarations[1] as ClassDeclaration;
+ var A = unit.declarations[1] as ClassDeclaration;
var builder = newBuilder();
await builder.addDartFileEdit(path, (builder) {
@@ -1026,7 +1026,7 @@
''';
addSource(path, content);
var unit = (await resolveFile(path)).unit;
- var g = unit?.declarations[1] as FunctionDeclaration;
+ var g = unit.declarations[1] as FunctionDeclaration;
var body = g.functionExpression.body as BlockFunctionBody;
var statement = body.block.statements[0] as ExpressionStatement;
var invocation = statement.expression as MethodInvocation;
@@ -1048,7 +1048,7 @@
addSource(path, content);
var unit = (await resolveFile(path)).unit;
- var f = unit?.declarations[0] as FunctionDeclaration;
+ var f = unit.declarations[0] as FunctionDeclaration;
var parameters = f.functionExpression.parameters;
var elements = parameters?.parameters.map((p) => p.declaredElement!);
@@ -1068,7 +1068,7 @@
var content = 'f(int a, [bool b = false, String c]) {}';
addSource(path, content);
var unit = (await resolveFile(path)).unit;
- var f = unit?.declarations[0] as FunctionDeclaration;
+ var f = unit.declarations[0] as FunctionDeclaration;
var parameters = f.functionExpression.parameters;
var elements = parameters?.parameters.map((p) => p.declaredElement!);
@@ -1088,7 +1088,7 @@
var content = 'f(int i, String s) {}';
addSource(path, content);
var unit = (await resolveFile(path)).unit;
- var f = unit?.declarations[0] as FunctionDeclaration;
+ var f = unit.declarations[0] as FunctionDeclaration;
var parameters = f.functionExpression.parameters;
var elements = parameters?.parameters.map((p) => p.declaredElement!);
@@ -1110,7 +1110,7 @@
}''';
addSource(path, content);
var unit = (await resolveFile(path)).unit;
- var f = unit?.declarations[0] as FunctionDeclaration;
+ var f = unit.declarations[0] as FunctionDeclaration;
var body = f.functionExpression.body as BlockFunctionBody;
var statement = body.block.statements[0] as ExpressionStatement;
var invocation = statement.expression as MethodInvocation;
@@ -1133,7 +1133,7 @@
}''';
addSource(path, content);
var unit = (await resolveFile(path)).unit;
- var f = unit?.declarations[0] as FunctionDeclaration;
+ var f = unit.declarations[0] as FunctionDeclaration;
var body = f.functionExpression.body as BlockFunctionBody;
var statement = body.block.statements[0] as ExpressionStatement;
var invocation = statement.expression as MethodInvocation;
@@ -1330,7 +1330,7 @@
var builder = newBuilder();
await builder.addDartFileEdit(path, (builder) {
builder.addInsertion(content.length - 1, (builder) {
- var typeProvider = unit!.declaredElement!.library.typeProvider;
+ var typeProvider = unit.declaredElement!.library.typeProvider;
builder.writeType(typeProvider.dynamicType);
});
});
@@ -1543,7 +1543,7 @@
var builder = newBuilder();
await builder.addDartFileEdit(path, (builder) {
builder.addInsertion(content.length - 1, (builder) {
- var typeProvider = unit!.declaredElement!.library.typeProvider;
+ var typeProvider = unit.declaredElement!.library.typeProvider;
builder.writeType(typeProvider.dynamicType, required: true);
});
});
@@ -1690,13 +1690,13 @@
Future<ClassElement> _getClassElement(String path, String name) async {
var result = (await resolveFile(path)).unit;
- return result!.declaredElement!.getType(name)!;
+ return result.declaredElement!.getType(name)!;
}
Future<PropertyAccessorElement> _getTopLevelAccessorElement(
String path, String name) async {
var result = (await resolveFile(path)).unit;
- return result!.declaredElement!.accessors.firstWhere((v) => v.name == name);
+ return result.declaredElement!.accessors.firstWhere((v) => v.name == name);
}
Future<InterfaceType> _getType(
@@ -1720,7 +1720,7 @@
addSource(path, '''var f = () {}''');
var resolvedUnit = await resolveFile(path);
- var findNode = FindNode(resolvedUnit.content!, resolvedUnit.unit!);
+ var findNode = FindNode(resolvedUnit.content, resolvedUnit.unit);
var body = findNode.functionBody('{}');
var builder = newBuilder();
@@ -1737,7 +1737,7 @@
addSource(path, 'String f() {}');
var resolvedUnit = await resolveFile(path);
- var findNode = FindNode(resolvedUnit.content!, resolvedUnit.unit!);
+ var findNode = FindNode(resolvedUnit.content, resolvedUnit.unit);
var body = findNode.functionBody('{}');
var builder = newBuilder();
@@ -1850,7 +1850,7 @@
addSource(path, 'String f() {}');
var resolvedUnit = await resolveFile(path);
- var findNode = FindNode(resolvedUnit.content!, resolvedUnit.unit!);
+ var findNode = FindNode(resolvedUnit.content, resolvedUnit.unit);
var type = findNode.typeAnnotation('String');
var builder = newBuilder();
@@ -1873,7 +1873,7 @@
class C extends B {}
''');
var unit = (await resolveFile(path)).unit;
- var classC = unit?.declarations[2] as ClassDeclaration;
+ var classC = unit.declarations[2] as ClassDeclaration;
var builder = DartLinkedEditBuilderImpl(MockEditBuilderImpl());
builder.addSuperTypesAsSuggestions(
classC.declaredElement?.instantiate(
@@ -2895,10 +2895,10 @@
{
var unitResult = (await resolveFile(path)).unit;
if (targetMixinName != null) {
- targetElement = unitResult!.declaredElement!.mixins
+ targetElement = unitResult.declaredElement!.mixins
.firstWhere((e) => e.name == targetMixinName);
} else {
- targetElement = unitResult!.declaredElement!.classes
+ targetElement = unitResult.declaredElement!.classes
.firstWhere((e) => e.name == targetClassName);
}
}
diff --git a/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_yaml_test.dart b/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_yaml_test.dart
index 866316c..00da884 100644
--- a/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_yaml_test.dart
+++ b/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_yaml_test.dart
@@ -21,7 +21,9 @@
}
class AbstractYamlChangeBuilderTest extends AbstractChangeBuilderTest {
- String get testFilePath => '/home/my/pubspec.yaml';
+ String get testFilePath {
+ return resourceProvider.convertPath('/home/my/pubspec.yaml');
+ }
void createPubspec(String content) {
resourceProvider.newFile(testFilePath, content);
diff --git a/pkg/analyzer_plugin/test/src/utilities/change_builder/dart/import_library_element_test.dart b/pkg/analyzer_plugin/test/src/utilities/change_builder/dart/import_library_element_test.dart
index 5239e00..cd2eefa 100644
--- a/pkg/analyzer_plugin/test/src/utilities/change_builder/dart/import_library_element_test.dart
+++ b/pkg/analyzer_plugin/test/src/utilities/change_builder/dart/import_library_element_test.dart
@@ -469,7 +469,7 @@
newFile(path, content: initialCode);
var requestedResult =
- await session.getLibraryByUri2(uriStr) as LibraryElementResult;
+ await session.getLibraryByUri(uriStr) as LibraryElementResult;
var requestedLibrary = requestedResult.element;
var requestedElement = requestedLibrary.exportNamespace.get(name);
expect(requestedElement, isNotNull, reason: '`$name` in $uriStr');
diff --git a/pkg/analyzer_plugin/test/src/utilities/completion/completion_target_test.dart b/pkg/analyzer_plugin/test/src/utilities/completion/completion_target_test.dart
index 71b649d..742f070 100644
--- a/pkg/analyzer_plugin/test/src/utilities/completion/completion_target_test.dart
+++ b/pkg/analyzer_plugin/test/src/utilities/completion/completion_target_test.dart
@@ -954,9 +954,9 @@
newFile(path, content: content);
var result = await resolveFile(path);
- findElement = FindElement(result.unit!);
+ findElement = FindElement(result.unit);
- target = CompletionTarget.forOffset(result.unit!, offset!);
+ target = CompletionTarget.forOffset(result.unit, offset!);
}
static String _executableNameStr(ExecutableElement executable) {
diff --git a/pkg/analyzer_plugin/test/src/utilities/completion/optype_test.dart b/pkg/analyzer_plugin/test/src/utilities/completion/optype_test.dart
index 3c8fe89..79c9e0c 100644
--- a/pkg/analyzer_plugin/test/src/utilities/completion/optype_test.dart
+++ b/pkg/analyzer_plugin/test/src/utilities/completion/optype_test.dart
@@ -50,7 +50,7 @@
//
var resolvedUnit = await resolveFile(testPath);
var completionTarget =
- CompletionTarget.forOffset(resolvedUnit.unit!, completionOffset);
+ CompletionTarget.forOffset(resolvedUnit.unit, completionOffset);
var opType = OpType.forCompletion(completionTarget, completionOffset);
//
// Validate the OpType.
diff --git a/pkg/analyzer_plugin/test/src/utilities/navigation/navigation_test.dart b/pkg/analyzer_plugin/test/src/utilities/navigation/navigation_test.dart
index 45179b0..5a76e0f 100644
--- a/pkg/analyzer_plugin/test/src/utilities/navigation/navigation_test.dart
+++ b/pkg/analyzer_plugin/test/src/utilities/navigation/navigation_test.dart
@@ -24,14 +24,16 @@
var targetStartColumnA1 = 4;
var targetKindA1 = ElementKind.CLASS;
var targetLocationA1 = Location(fileA, targetOffsetA1, targetLengthA1,
- targetStartLineA1, targetStartColumnA1, 0, 0);
+ targetStartLineA1, targetStartColumnA1,
+ endLine: 0, endColumn: 0);
var targetOffsetA2 = 5;
var targetLengthA2 = 6;
var targetStartLineA2 = 7;
var targetStartColumnA2 = 8;
var targetKindA2 = ElementKind.FUNCTION;
var targetLocationA2 = Location(fileA, targetOffsetA2, targetLengthA2,
- targetStartLineA2, targetStartColumnA2, 0, 0);
+ targetStartLineA2, targetStartColumnA2,
+ endLine: 0, endColumn: 0);
var fileB = 'b.dart';
var targetOffsetB1 = 9;
@@ -40,14 +42,16 @@
var targetStartColumnB1 = 12;
var targetKindB1 = ElementKind.ENUM;
var targetLocationB1 = Location(fileB, targetOffsetB1, targetLengthB1,
- targetStartLineB1, targetStartColumnB1, 0, 0);
+ targetStartLineB1, targetStartColumnB1,
+ endLine: 0, endColumn: 0);
var targetOffsetB2 = 13;
var targetLengthB2 = 14;
var targetStartLineB2 = 15;
var targetStartColumnB2 = 16;
var targetKindB2 = ElementKind.METHOD;
var targetLocationB2 = Location(fileB, targetOffsetB2, targetLengthB2,
- targetStartLineB2, targetStartColumnB2, 0, 0);
+ targetStartLineB2, targetStartColumnB2,
+ endLine: 0, endColumn: 0);
// Six regions targeting a1, b1, a2, b1, a1, b2
var regionOffsets = <int>[17, 18, 19, 20, 21, 22];
@@ -112,7 +116,8 @@
var targetStartLine = 5;
var targetStartColumn = 1;
var targetLocation = Location(targetFile, targetOffset, targetLength,
- targetStartLine, targetStartColumn, 0, 0);
+ targetStartLine, targetStartColumn,
+ endLine: 0, endColumn: 0);
collector.addRegion(regionOffset, regionLength, targetKind, targetLocation);
collector.createRegions();
expect(collector.files, [targetFile]);
diff --git a/pkg/analyzer_plugin/test/support/abstract_context.dart b/pkg/analyzer_plugin/test/support/abstract_context.dart
index 6bd18116..6d58ad9 100644
--- a/pkg/analyzer_plugin/test/support/abstract_context.dart
+++ b/pkg/analyzer_plugin/test/support/abstract_context.dart
@@ -98,7 +98,7 @@
Future<ResolvedUnitResult> resolveFile(String path) async {
var session = contextFor(path).currentSession;
- return await session.getResolvedUnit2(path) as ResolvedUnitResult;
+ return await session.getResolvedUnit(path) as ResolvedUnitResult;
}
void setUp() {
diff --git a/pkg/analyzer_plugin/test/support/abstract_single_unit.dart b/pkg/analyzer_plugin/test/support/abstract_single_unit.dart
index afa5699..bdd1c69 100644
--- a/pkg/analyzer_plugin/test/support/abstract_single_unit.dart
+++ b/pkg/analyzer_plugin/test/support/abstract_single_unit.dart
@@ -95,8 +95,8 @@
Future<void> resolveTestFile() async {
var result = await resolveFile(testFile);
- testCode = result.content!;
- testUnit = result.unit!;
+ testCode = result.content;
+ testUnit = result.unit;
if (verifyNoTestUnitErrors) {
expect(result.errors.where((AnalysisError error) {
return error.errorCode != HintCode.DEAD_CODE &&
diff --git a/pkg/analyzer_plugin/test/utilities/completion/completion_contributor_util.dart b/pkg/analyzer_plugin/test/utilities/completion/completion_contributor_util.dart
index d7cba95..a98ac39 100644
--- a/pkg/analyzer_plugin/test/utilities/completion/completion_contributor_util.dart
+++ b/pkg/analyzer_plugin/test/utilities/completion/completion_contributor_util.dart
@@ -418,7 +418,7 @@
DartCompletionRequestImpl(resourceProvider, completionOffset!, result);
var target =
- CompletionTarget.forOffset(request!.result.unit!, request!.offset);
+ CompletionTarget.forOffset(request!.result.unit, request!.offset);
var range = target.computeReplacementRange(request!.offset);
replacementOffset = range.offset;
replacementLength = range.length;
diff --git a/pkg/analyzer_plugin/tool/spec/common_types_spec.html b/pkg/analyzer_plugin/tool/spec/common_types_spec.html
index 1ec7a90..412fcb7 100644
--- a/pkg/analyzer_plugin/tool/spec/common_types_spec.html
+++ b/pkg/analyzer_plugin/tool/spec/common_types_spec.html
@@ -1057,14 +1057,14 @@
the range.
</p>
</field>
- <field name="endLine">
+ <field name="endLine" optional="true">
<ref>int</ref>
<p>
The one-based index of the line containing the character immediately
following the range.
</p>
</field>
- <field name="endColumn">
+ <field name="endColumn" optional="true">
<ref>int</ref>
<p>
The one-based index of the column containing the character immediately
diff --git a/pkg/analyzer_utilities/lib/verify_tests.dart b/pkg/analyzer_utilities/lib/verify_tests.dart
index 201e88d..de1bf43 100644
--- a/pkg/analyzer_utilities/lib/verify_tests.dart
+++ b/pkg/analyzer_utilities/lib/verify_tests.dart
@@ -103,7 +103,7 @@
if (isOkForTestAllToBeMissing(directory)) {
fail('Found "test_all.dart" in $relativePath but did not expect one');
}
- var result = session.getParsedUnit2(testAllFile.path);
+ var result = session.getParsedUnit(testAllFile.path);
if (result is! ParsedUnitResult) {
fail('Could not parse ${testAllFile.path}');
}
diff --git a/pkg/build_integration/lib/file_system/multi_root.dart b/pkg/build_integration/lib/file_system/multi_root.dart
index bfaead5..14772cc 100644
--- a/pkg/build_integration/lib/file_system/multi_root.dart
+++ b/pkg/build_integration/lib/file_system/multi_root.dart
@@ -47,7 +47,7 @@
class MultiRootFileSystemEntity implements FileSystemEntity {
final MultiRootFileSystem multiRootFileSystem;
final Uri uri;
- FileSystemEntity _delegate;
+ FileSystemEntity? _delegate;
Future<FileSystemEntity> get delegate async =>
_delegate ??= await _resolveEntity();
diff --git a/pkg/build_integration/pubspec.yaml b/pkg/build_integration/pubspec.yaml
index a7b79b1..899a5ed 100644
--- a/pkg/build_integration/pubspec.yaml
+++ b/pkg/build_integration/pubspec.yaml
@@ -6,7 +6,7 @@
publish_to: none
environment:
- sdk: '>=2.1.0 <3.0.0'
+ sdk: '>=2.12.0 <3.0.0'
dependencies:
front_end:
diff --git a/pkg/build_integration/test/file_system/multi_root_test.dart b/pkg/build_integration/test/file_system/multi_root_test.dart
index e92249a..09d3cc9 100644
--- a/pkg/build_integration/test/file_system/multi_root_test.dart
+++ b/pkg/build_integration/test/file_system/multi_root_test.dart
@@ -15,9 +15,8 @@
var root = Uri.parse('org-dartlang-test:///');
main() {
- var memoryFs;
- var rootUris;
- var multiRoot;
+ late MemoryFileSystem memoryFs;
+ late MultiRootFileSystem multiRoot;
write(String multiRoot, String path) {
var realPath = multiRoot == '' ? path : '$multiRoot/$path';
@@ -32,11 +31,15 @@
multiRoot.entityForUri(Uri.parse(uri)).exists();
Future<String> effectiveUriOf(String uri) async =>
- (await multiRoot.entityForUri(Uri.parse(uri)).delegate).uri.toString();
+ (await (multiRoot.entityForUri(Uri.parse(uri))
+ as MultiRootFileSystemEntity)
+ .delegate)
+ .uri
+ .toString();
setUp(() {
memoryFs = new MemoryFileSystem(root);
- rootUris = ['r1', 'r2/', 'A/B/', ''].map((r) => root.resolve(r)).toList();
+ final rootUris = ['r1', 'r2/', 'A/B/', ''].map((r) => root.resolve(r)).toList();
multiRoot = new MultiRootFileSystem('multi-root', rootUris, memoryFs);
});
diff --git a/pkg/build_integration/test/file_system/single_root_test.dart b/pkg/build_integration/test/file_system/single_root_test.dart
index 38ed4f8..50fb984 100644
--- a/pkg/build_integration/test/file_system/single_root_test.dart
+++ b/pkg/build_integration/test/file_system/single_root_test.dart
@@ -13,7 +13,7 @@
'single-root', root.resolve('A/B'), new MemoryFileSystem(root));
SingleRootFileSystemEntity entityOf(String uri) =>
- fileSystem.entityForUri(Uri.parse(uri));
+ fileSystem.entityForUri(Uri.parse(uri)) as SingleRootFileSystemEntity;
String effectiveUriOf(String uri) => '${entityOf(uri).delegate.uri}';
diff --git a/pkg/compiler/README.md b/pkg/compiler/README.md
index 6c9621a..3f493c5 100644
--- a/pkg/compiler/README.md
+++ b/pkg/compiler/README.md
@@ -351,11 +351,11 @@
representation of JSInt31, JSArray, and other implementation-specific
elements.
-* `lib/src/deferred_load.dart`: general analysis for deferred loading. This is
- where we compute how to split the code in different JS chunks or fragments.
- This is run after resolution, but at a time when no code is generated yet, so
- the decisions made here are used later on by the emitter to dump code into
- different files.
+* `lib/src/deferred_load/deferred_load.dart`: general analysis for deferred
+ loading. This is where we compute how to split the code in different JS chunks
+ or fragments. This is run after resolution, but at a time when no code is
+ generated yet, so the decisions made here are used later on by the emitter to
+ dump code into different files.
* `lib/src/dump_info.dart`: a special phase used to create a .info.json file.
This file contains lots of information computed by dart2js including decisions
diff --git a/pkg/compiler/lib/src/backend_strategy.dart b/pkg/compiler/lib/src/backend_strategy.dart
index 92966bc..add5771 100644
--- a/pkg/compiler/lib/src/backend_strategy.dart
+++ b/pkg/compiler/lib/src/backend_strategy.dart
@@ -7,7 +7,7 @@
import 'common.dart';
import 'common/codegen.dart';
import 'common/tasks.dart';
-import 'deferred_load.dart' show OutputUnitData;
+import 'deferred_load/deferred_load.dart' show OutputUnitData;
import 'enqueue.dart';
import 'elements/entities.dart';
import 'inferrer/types.dart';
diff --git a/pkg/compiler/lib/src/commandline_options.dart b/pkg/compiler/lib/src/commandline_options.dart
index 771756b..57ecf0f 100644
--- a/pkg/compiler/lib/src/commandline_options.dart
+++ b/pkg/compiler/lib/src/commandline_options.dart
@@ -2,6 +2,8 @@
// 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.
+// @dart=2.12
+
library dart2js.cmdline.options;
/// Commandline flags used in `dart2js.dart` and/or `apiimpl.dart`.
diff --git a/pkg/compiler/lib/src/common/codegen.dart b/pkg/compiler/lib/src/common/codegen.dart
index 93bf848..bec3d57 100644
--- a/pkg/compiler/lib/src/common/codegen.dart
+++ b/pkg/compiler/lib/src/common/codegen.dart
@@ -9,7 +9,7 @@
import '../common.dart';
import '../common_elements.dart';
import '../constants/values.dart';
-import '../deferred_load.dart';
+import '../deferred_load/deferred_load.dart';
import '../elements/entities.dart';
import '../elements/types.dart' show DartType, InterfaceType;
import '../inferrer/abstract_value_domain.dart';
diff --git a/pkg/compiler/lib/src/common_elements.dart b/pkg/compiler/lib/src/common_elements.dart
index c8cd6d7..8fdefc4 100644
--- a/pkg/compiler/lib/src/common_elements.dart
+++ b/pkg/compiler/lib/src/common_elements.dart
@@ -217,7 +217,7 @@
InterfaceType getConstantListTypeFor(InterfaceType sourceType);
InterfaceType getConstantMapTypeFor(InterfaceType sourceType,
- {bool hasProtoKey: false, bool onlyStringKeys: false});
+ {bool onlyStringKeys: false});
InterfaceType getConstantSetTypeFor(InterfaceType sourceType);
@@ -362,7 +362,6 @@
ClassEntity get constantMapClass;
ClassEntity get constantStringMapClass;
- ClassEntity get constantProtoMapClass;
ClassEntity get generalConstantMapClass;
ClassEntity get annotationCreatesClass;
@@ -1037,10 +1036,9 @@
@override
InterfaceType getConstantMapTypeFor(InterfaceType sourceType,
- {bool hasProtoKey: false, bool onlyStringKeys: false}) {
- ClassEntity classElement = onlyStringKeys
- ? (hasProtoKey ? constantProtoMapClass : constantStringMapClass)
- : generalConstantMapClass;
+ {bool onlyStringKeys: false}) {
+ ClassEntity classElement =
+ onlyStringKeys ? constantStringMapClass : generalConstantMapClass;
if (dartTypes.treatAsRawType(sourceType)) {
return _env.getRawType(classElement);
} else {
@@ -1619,9 +1617,6 @@
ClassEntity get constantStringMapClass =>
_findHelperClass(constant_system.JavaScriptMapConstant.DART_STRING_CLASS);
@override
- ClassEntity get constantProtoMapClass =>
- _findHelperClass(constant_system.JavaScriptMapConstant.DART_PROTO_CLASS);
- @override
ClassEntity get generalConstantMapClass => _findHelperClass(
constant_system.JavaScriptMapConstant.DART_GENERAL_CLASS);
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index 9d3ca36..d9303a6 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -18,7 +18,7 @@
import 'common/work.dart' show WorkItem;
import 'common.dart';
import 'common_elements.dart' show ElementEnvironment;
-import 'deferred_load.dart' show DeferredLoadTask, OutputUnitData;
+import 'deferred_load/deferred_load.dart' show DeferredLoadTask, OutputUnitData;
import 'diagnostics/code_location.dart';
import 'diagnostics/messages.dart' show Message, MessageTemplate;
import 'dump_info.dart' show DumpInfoTask;
@@ -91,10 +91,6 @@
ImpactCacheDeleter get impactCacheDeleter => _impactCacheDeleter;
final Environment environment;
- // TODO(sigmund): delete once we migrate the rest of the compiler to use
- // `environment` directly.
- @deprecated
- fromEnvironment(String name) => environment.valueOf(name);
Entity get currentElement => _reporter.currentElement;
diff --git a/pkg/compiler/lib/src/constants/constant_system.dart b/pkg/compiler/lib/src/constants/constant_system.dart
index b10c628..d2d5b8f 100644
--- a/pkg/compiler/lib/src/constants/constant_system.dart
+++ b/pkg/compiler/lib/src/constants/constant_system.dart
@@ -157,23 +157,10 @@
InterfaceType sourceType,
List<ConstantValue> keys,
List<ConstantValue> values) {
- bool onlyStringKeys = true;
- ConstantValue protoValue = null;
- for (int i = 0; i < keys.length; i++) {
- dynamic key = keys[i];
- if (key.isString) {
- if (key.stringValue == JavaScriptMapConstant.PROTO_PROPERTY) {
- protoValue = values[i];
- }
- } else {
- onlyStringKeys = false;
- // Don't handle __proto__ values specially in the general map case.
- protoValue = null;
- break;
- }
- }
+ bool onlyStringKeys = keys.every((key) =>
+ key is StringConstantValue &&
+ key.stringValue != JavaScriptMapConstant.PROTO_PROPERTY);
- bool hasProtoKey = (protoValue != null);
InterfaceType keysType;
if (commonElements.dartTypes.treatAsRawType(sourceType)) {
keysType = commonElements.listType();
@@ -182,9 +169,8 @@
}
ListConstantValue keysList = createList(commonElements, keysType, keys);
InterfaceType type = commonElements.getConstantMapTypeFor(sourceType,
- hasProtoKey: hasProtoKey, onlyStringKeys: onlyStringKeys);
- return new JavaScriptMapConstant(
- type, keysList, values, protoValue, onlyStringKeys);
+ onlyStringKeys: onlyStringKeys);
+ return JavaScriptMapConstant(type, keysList, values, onlyStringKeys);
}
ConstantValue createSymbol(CommonElements commonElements, String text) {
@@ -1035,20 +1021,17 @@
/// The dart class implementing constant map literals.
static const String DART_CLASS = "ConstantMap";
static const String DART_STRING_CLASS = "ConstantStringMap";
- static const String DART_PROTO_CLASS = "ConstantProtoMap";
static const String DART_GENERAL_CLASS = "GeneralConstantMap";
static const String LENGTH_NAME = "_length";
static const String JS_OBJECT_NAME = "_jsObject";
static const String KEYS_NAME = "_keys";
- static const String PROTO_VALUE = "_protoValue";
static const String JS_DATA_NAME = "_jsData";
final ListConstantValue keyList;
- final ConstantValue protoValue;
final bool onlyStringKeys;
JavaScriptMapConstant(InterfaceType type, ListConstantValue keyList,
- List<ConstantValue> values, this.protoValue, this.onlyStringKeys)
+ List<ConstantValue> values, this.onlyStringKeys)
: this.keyList = keyList,
super(type, keyList.entries, values);
@override
diff --git a/pkg/compiler/lib/src/constants/values.dart b/pkg/compiler/lib/src/constants/values.dart
index f33c13b..4ef3a07 100644
--- a/pkg/compiler/lib/src/constants/values.dart
+++ b/pkg/compiler/lib/src/constants/values.dart
@@ -8,7 +8,7 @@
import '../common_elements.dart';
import '../elements/entities.dart';
import '../elements/types.dart';
-import '../deferred_load.dart' show OutputUnit;
+import '../deferred_load/deferred_load.dart' show OutputUnit;
import '../js/js.dart' as js;
import '../util/util.dart';
@@ -741,8 +741,7 @@
int get length => keys.length;
ConstantValue lookup(ConstantValue key) {
- var lookupMap = _lookupMap ??=
- new Map<ConstantValue, ConstantValue>.fromIterables(keys, values);
+ var lookupMap = _lookupMap ??= Map.fromIterables(keys, values);
return lookupMap[key];
}
diff --git a/pkg/compiler/lib/src/deferred_load.dart b/pkg/compiler/lib/src/deferred_load/deferred_load.dart
similarity index 98%
rename from pkg/compiler/lib/src/deferred_load.dart
rename to pkg/compiler/lib/src/deferred_load/deferred_load.dart
index f3f6bac..bf7a202 100644
--- a/pkg/compiler/lib/src/deferred_load.dart
+++ b/pkg/compiler/lib/src/deferred_load/deferred_load.dart
@@ -10,31 +10,31 @@
import 'package:kernel/ast.dart' as ir;
import 'package:kernel/type_environment.dart' as ir;
-import '../compiler_new.dart' show OutputType;
-import 'common/metrics.dart' show Metric, Metrics, CountMetric, DurationMetric;
-import 'common/tasks.dart' show CompilerTask;
-import 'common.dart';
-import 'common_elements.dart' show CommonElements, KElementEnvironment;
-import 'compiler.dart' show Compiler;
-import 'constants/values.dart'
+import '../../compiler_new.dart' show OutputType;
+import '../common/metrics.dart' show Metric, Metrics, CountMetric, DurationMetric;
+import '../common/tasks.dart' show CompilerTask;
+import '../common.dart';
+import '../common_elements.dart' show CommonElements, KElementEnvironment;
+import '../compiler.dart' show Compiler;
+import '../constants/values.dart'
show
ConstantValue,
ConstructedConstantValue,
DeferredGlobalConstantValue,
InstantiationConstantValue;
-import 'elements/types.dart';
-import 'elements/entities.dart';
-import 'ir/util.dart';
-import 'kernel/kelements.dart' show KLocalFunction;
-import 'kernel/element_map.dart';
-import 'serialization/serialization.dart';
-import 'options.dart';
-import 'universe/use.dart';
-import 'universe/world_impact.dart'
+import '../elements/types.dart';
+import '../elements/entities.dart';
+import '../ir/util.dart';
+import '../kernel/kelements.dart' show KLocalFunction;
+import '../kernel/element_map.dart';
+import '../serialization/serialization.dart';
+import '../options.dart';
+import '../universe/use.dart';
+import '../universe/world_impact.dart'
show ImpactUseCase, WorldImpact, WorldImpactVisitorImpl;
-import 'util/maplet.dart';
-import 'util/util.dart' show makeUnique;
-import 'world.dart' show KClosedWorld;
+import '../util/maplet.dart';
+import '../util/util.dart' show makeUnique;
+import '../world.dart' show KClosedWorld;
/// A "hunk" of the program that will be loaded whenever one of its [imports]
/// are loaded.
@@ -114,7 +114,7 @@
/// Will be `true` if the program contains deferred libraries.
bool isProgramSplit = false;
- static const ImpactUseCase IMPACT_USE = const ImpactUseCase('Deferred load');
+ static const ImpactUseCase IMPACT_USE = ImpactUseCase('Deferred load');
/// A cache of the result of calling `computeImportDeferName` on the keys of
/// this map.
@@ -257,7 +257,7 @@
// Fetch the internal node in order to skip annotations on the member.
// TODO(sigmund): replace this pattern when the kernel-ast provides a better
// way to skip annotations (issue 31565).
- var visitor = new ConstantCollector(
+ var visitor = ConstantCollector(
_elementMap, _elementMap.getStaticTypeContext(element), dependencies);
if (node is ir.Field) {
node.initializer?.accept(visitor);
@@ -1540,7 +1540,7 @@
/// Returns the [OutputUnit] where [cls] belongs.
// TODO(johnniwinther): Remove the need for [allowNull]. Dump-info currently
// needs it.
- OutputUnit outputUnitForClass(ClassEntity cls, {bool allowNull: false}) {
+ OutputUnit outputUnitForClass(ClassEntity cls, {bool allowNull = false}) {
if (!isProgramSplit) return mainOutputUnit;
OutputUnit unit = _classToUnit[cls];
assert(allowNull || unit != null, 'No output unit for class $cls');
@@ -1551,7 +1551,7 @@
/// Returns the [OutputUnit] where [cls]'s type belongs.
// TODO(joshualitt): see above TODO regarding allowNull.
- OutputUnit outputUnitForClassType(ClassEntity cls, {bool allowNull: false}) {
+ OutputUnit outputUnitForClassType(ClassEntity cls, {bool allowNull = false}) {
if (!isProgramSplit) return mainOutputUnit;
OutputUnit unit = _classTypeToUnit[cls];
assert(allowNull || unit != null, 'No output unit for type $cls');
@@ -1665,7 +1665,7 @@
/// The filename is of the form "<main output file>_<name>.part.js".
/// If [addExtension] is false, the ".part.js" suffix is left out.
String deferredPartFileName(CompilerOptions options, String name,
- {bool addExtension: true}) {
+ {bool addExtension = true}) {
assert(name != "");
String outPath = options.outputUri != null ? options.outputUri.path : "out";
String outName = outPath.substring(outPath.lastIndexOf('/') + 1);
@@ -1811,7 +1811,7 @@
CommonElements get commonElements => elementMap.commonElements;
- void add(ir.Expression node, {bool required: true}) {
+ void add(ir.Expression node, {bool required = true}) {
ConstantValue constant = elementMap
.getConstantValue(staticTypeContext, node, requireConstant: required);
if (constant != null) {
diff --git a/pkg/compiler/lib/src/dump_info.dart b/pkg/compiler/lib/src/dump_info.dart
index aff886a..c6448fb 100644
--- a/pkg/compiler/lib/src/dump_info.dart
+++ b/pkg/compiler/lib/src/dump_info.dart
@@ -19,7 +19,7 @@
import 'common_elements.dart' show JElementEnvironment;
import 'compiler.dart' show Compiler;
import 'constants/values.dart' show ConstantValue, InterceptorConstantValue;
-import 'deferred_load.dart' show OutputUnit, deferredPartFileName;
+import 'deferred_load/deferred_load.dart' show OutputUnit, deferredPartFileName;
import 'elements/entities.dart';
import 'inferrer/abstract_value_domain.dart';
import 'inferrer/types.dart'
diff --git a/pkg/compiler/lib/src/elements/entity_utils.dart b/pkg/compiler/lib/src/elements/entity_utils.dart
index 82be8db..2942392 100644
--- a/pkg/compiler/lib/src/elements/entity_utils.dart
+++ b/pkg/compiler/lib/src/elements/entity_utils.dart
@@ -7,6 +7,7 @@
import 'package:front_end/src/api_unstable/dart2js.dart'
show isUserDefinableOperator, isMinusOperator;
+import '../js_backend/namer.dart';
import 'entities.dart';
// Somewhat stable ordering for libraries using [Uri]s
@@ -154,7 +155,7 @@
} else if (name == 'unary-') {
return r'operator$negate';
} else {
- return name;
+ return Namer.replaceNonIdentifierCharacters(name);
}
}
diff --git a/pkg/compiler/lib/src/elements/types.dart b/pkg/compiler/lib/src/elements/types.dart
index 41e58eb..7b34a8a 100644
--- a/pkg/compiler/lib/src/elements/types.dart
+++ b/pkg/compiler/lib/src/elements/types.dart
@@ -911,86 +911,29 @@
R visit(covariant DartType type, A argument) => type.accept(this, argument);
- R visitLegacyType(covariant LegacyType type, A argument) => null;
+ R visitLegacyType(covariant LegacyType type, A argument);
- R visitNullableType(covariant NullableType type, A argument) => null;
+ R visitNullableType(covariant NullableType type, A argument);
- R visitNeverType(covariant NeverType type, A argument) => null;
+ R visitNeverType(covariant NeverType type, A argument);
- R visitVoidType(covariant VoidType type, A argument) => null;
+ R visitVoidType(covariant VoidType type, A argument);
- R visitTypeVariableType(covariant TypeVariableType type, A argument) => null;
+ R visitTypeVariableType(covariant TypeVariableType type, A argument);
- R visitFunctionTypeVariable(
- covariant FunctionTypeVariable type, A argument) =>
- null;
+ R visitFunctionTypeVariable(covariant FunctionTypeVariable type, A argument);
- R visitFunctionType(covariant FunctionType type, A argument) => null;
+ R visitFunctionType(covariant FunctionType type, A argument);
- R visitInterfaceType(covariant InterfaceType type, A argument) => null;
+ R visitInterfaceType(covariant InterfaceType type, A argument);
- R visitDynamicType(covariant DynamicType type, A argument) => null;
+ R visitDynamicType(covariant DynamicType type, A argument);
- R visitErasedType(covariant ErasedType type, A argument) => null;
+ R visitErasedType(covariant ErasedType type, A argument);
- R visitAnyType(covariant AnyType type, A argument) => null;
+ R visitAnyType(covariant AnyType type, A argument);
- R visitFutureOrType(covariant FutureOrType type, A argument) => null;
-}
-
-abstract class BaseDartTypeVisitor<R, A> extends DartTypeVisitor<R, A> {
- const BaseDartTypeVisitor();
-
- R visitType(covariant DartType type, A argument);
-
- @override
- R visitLegacyType(covariant LegacyType type, A argument) =>
- visitType(type, argument);
-
- @override
- R visitNullableType(covariant NullableType type, A argument) =>
- visitType(type, argument);
-
- @override
- R visitNeverType(covariant NeverType type, A argument) =>
- visitType(type, argument);
-
- @override
- R visitVoidType(covariant VoidType type, A argument) =>
- visitType(type, argument);
-
- @override
- R visitTypeVariableType(covariant TypeVariableType type, A argument) =>
- visitType(type, argument);
-
- @override
- R visitFunctionTypeVariable(
- covariant FunctionTypeVariable type, A argument) =>
- visitType(type, argument);
-
- @override
- R visitFunctionType(covariant FunctionType type, A argument) =>
- visitType(type, argument);
-
- @override
- R visitInterfaceType(covariant InterfaceType type, A argument) =>
- visitType(type, argument);
-
- @override
- R visitDynamicType(covariant DynamicType type, A argument) =>
- visitType(type, argument);
-
- @override
- R visitErasedType(covariant ErasedType type, A argument) =>
- visitType(type, argument);
-
- @override
- R visitAnyType(covariant AnyType type, A argument) =>
- visitType(type, argument);
-
- @override
- R visitFutureOrType(covariant FutureOrType type, A argument) =>
- visitType(type, argument);
+ R visitFutureOrType(covariant FutureOrType type, A argument);
}
class _LegacyErasureVisitor extends DartTypeVisitor<DartType, Null> {
diff --git a/pkg/compiler/lib/src/frontend_strategy.dart b/pkg/compiler/lib/src/frontend_strategy.dart
index 3ea0ee2..5fb4571 100644
--- a/pkg/compiler/lib/src/frontend_strategy.dart
+++ b/pkg/compiler/lib/src/frontend_strategy.dart
@@ -8,7 +8,7 @@
import 'common/tasks.dart';
import 'common_elements.dart';
import 'compiler.dart' show Compiler;
-import 'deferred_load.dart' show DeferredLoadTask;
+import 'deferred_load/deferred_load.dart' show DeferredLoadTask;
import 'elements/entities.dart';
import 'enqueue.dart';
import 'js_backend/native_data.dart';
diff --git a/pkg/compiler/lib/src/helpers/helpers.dart b/pkg/compiler/lib/src/helpers/helpers.dart
index a59366a..9828b7f 100644
--- a/pkg/compiler/lib/src/helpers/helpers.dart
+++ b/pkg/compiler/lib/src/helpers/helpers.dart
@@ -7,9 +7,10 @@
library dart2js.helpers;
+import 'package:kernel/text/indentation.dart' show Indentation;
+
import '../common.dart';
import '../diagnostics/invariant.dart' show DEBUG_MODE;
-import '../util/util.dart';
export 'debug_collection.dart';
export 'expensive_map.dart';
@@ -89,6 +90,7 @@
/// Implementation of [reportHere]
_reportHere(DiagnosticReporter reporter, Spannable node, String debugMessage) {
+ // ignore: deprecated_member_use_from_same_package
reporter.reportInfoMessage(
node, MessageKind.GENERIC, {'text': 'HERE: $debugMessage'});
}
diff --git a/pkg/compiler/lib/src/helpers/stats.dart b/pkg/compiler/lib/src/helpers/stats.dart
index e524b54..7ca7960 100644
--- a/pkg/compiler/lib/src/helpers/stats.dart
+++ b/pkg/compiler/lib/src/helpers/stats.dart
@@ -6,6 +6,8 @@
import 'dart:collection';
import 'dart:convert';
+import 'package:kernel/text/indentation.dart' show Indentation;
+
import '../../compiler.dart';
import '../common.dart';
import '../compiler.dart' show Compiler;
diff --git a/pkg/compiler/lib/src/inferrer/builder_kernel.dart b/pkg/compiler/lib/src/inferrer/builder_kernel.dart
index 6c90fb2..fe3d41c 100644
--- a/pkg/compiler/lib/src/inferrer/builder_kernel.dart
+++ b/pkg/compiler/lib/src/inferrer/builder_kernel.dart
@@ -1049,32 +1049,6 @@
node, node.receiver, receiverType, selector, arguments, null);
}
- @override
- TypeInformation visitMethodInvocation(ir.MethodInvocation node) {
- Selector selector = _elementMap.getSelector(node);
- ir.Expression receiver = node.receiver;
- if (receiver is ir.VariableGet &&
- receiver.variable.parent is ir.FunctionDeclaration) {
- // TODO(johnniwinther). This triggers the computation of the mask for the
- // receiver of the call to `call`. Remove this when the ssa builder
- // recognizes local function invocation directly.
- _typeOfReceiver(node, node.receiver);
- // This is an invocation of a named local function.
- return _handleLocalFunctionInvocation(
- node, receiver.variable.parent, node.arguments, selector);
- }
-
- TypeInformation receiverType = visit(receiver);
- ArgumentsTypes arguments = analyzeArguments(node.arguments);
- if (selector.name == '==') {
- return _handleEqualsCall(node, node.receiver, receiverType,
- node.arguments.positional.first, arguments.positional[0]);
- }
-
- return _handleMethodInvocation(node, node.receiver, receiverType, selector,
- arguments, node.interfaceTarget);
- }
-
ir.VariableDeclaration _getVariableDeclaration(ir.Expression node) {
return node is ir.VariableGet ? node.variable : null;
}
@@ -1671,12 +1645,6 @@
return _handlePropertyGet(node, node.receiver);
}
- @override
- TypeInformation visitPropertyGet(ir.PropertyGet node) {
- return _handlePropertyGet(node, node.receiver,
- interfaceTarget: node.interfaceTarget);
- }
-
TypeInformation _handlePropertySet(
ir.Expression node, ir.Expression receiver, ir.Expression value,
{ir.Member interfaceTarget}) {
@@ -1716,12 +1684,6 @@
}
@override
- TypeInformation visitPropertySet(ir.PropertySet node) {
- return _handlePropertySet(node, node.receiver, node.value,
- interfaceTarget: node.interfaceTarget);
- }
-
- @override
TypeInformation visitInstanceSet(ir.InstanceSet node) {
return _handlePropertySet(node, node.receiver, node.value,
interfaceTarget: node.interfaceTarget);
@@ -2314,7 +2276,7 @@
@override
TypeInformation visitStaticTearOffConstant(ir.StaticTearOffConstant node) {
- return builder.createStaticGetTypeInformation(node, node.procedure);
+ return builder.createStaticGetTypeInformation(node, node.target);
}
@override
diff --git a/pkg/compiler/lib/src/inferrer/inferrer_engine.dart b/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
index 45dea65..defc8a7 100644
--- a/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
+++ b/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
@@ -650,20 +650,17 @@
// TODO(johnniwinther): Implement the ad-hoc check in ast inferrer? This
// mimicks that ast inferrer which return `true` for [ast.Send] and
// non-const [ast.NewExpression].
- if (initializer is ir.MethodInvocation ||
- initializer is ir.InstanceInvocation ||
+ if (initializer is ir.InstanceInvocation ||
initializer is ir.InstanceGetterInvocation ||
initializer is ir.DynamicInvocation ||
initializer is ir.FunctionInvocation ||
initializer is ir.LocalFunctionInvocation ||
initializer is ir.EqualsNull ||
initializer is ir.EqualsCall ||
- initializer is ir.PropertyGet ||
initializer is ir.InstanceGet ||
initializer is ir.DynamicGet ||
initializer is ir.InstanceTearOff ||
initializer is ir.FunctionTearOff ||
- initializer is ir.PropertySet ||
initializer is ir.InstanceSet ||
initializer is ir.DynamicSet ||
initializer is ir.StaticInvocation ||
diff --git a/pkg/compiler/lib/src/ir/cached_static_type.dart b/pkg/compiler/lib/src/ir/cached_static_type.dart
index 2aca746..9fdb34b 100644
--- a/pkg/compiler/lib/src/ir/cached_static_type.dart
+++ b/pkg/compiler/lib/src/ir/cached_static_type.dart
@@ -46,17 +46,10 @@
ir.DartType visitVariableGet(ir.VariableGet node) => _getStaticType(node);
@override
- ir.DartType visitPropertyGet(ir.PropertyGet node) => _getStaticType(node);
-
- @override
ir.DartType visitSuperPropertyGet(ir.SuperPropertyGet node) =>
_getStaticType(node);
@override
- ir.DartType visitMethodInvocation(ir.MethodInvocation node) =>
- _getStaticType(node);
-
- @override
ir.DartType visitStaticInvocation(ir.StaticInvocation node) =>
_getStaticType(node);
diff --git a/pkg/compiler/lib/src/ir/closure.dart b/pkg/compiler/lib/src/ir/closure.dart
index f129216..39ceeb5 100644
--- a/pkg/compiler/lib/src/ir/closure.dart
+++ b/pkg/compiler/lib/src/ir/closure.dart
@@ -399,6 +399,11 @@
}
@override
+ R accept1<R, A>(ir.Visitor1<R, A> v, A arg) {
+ throw new UnsupportedError('TypeVariableTypeWithContext.accept1');
+ }
+
+ @override
visitChildren(ir.Visitor v) {
throw new UnsupportedError('TypeVariableTypeWithContext.visitChildren');
}
diff --git a/pkg/compiler/lib/src/ir/impact.dart b/pkg/compiler/lib/src/ir/impact.dart
index 33640a7..16fbc15 100644
--- a/pkg/compiler/lib/src/ir/impact.dart
+++ b/pkg/compiler/lib/src/ir/impact.dart
@@ -678,7 +678,8 @@
@override
void handleConstantExpression(ir.ConstantExpression node) {
ir.LibraryDependency import = getDeferredImport(node);
- new ConstantImpactVisitor(this, import, node).visitConstant(node.constant);
+ new ConstantImpactVisitor(this, import, node, staticTypeContext)
+ .visitConstant(node.constant);
}
}
@@ -727,8 +728,10 @@
final ImpactRegistry registry;
final ir.LibraryDependency import;
final ir.ConstantExpression expression;
+ final ir.StaticTypeContext staticTypeContext;
- ConstantImpactVisitor(this.registry, this.import, this.expression);
+ ConstantImpactVisitor(
+ this.registry, this.import, this.expression, this.staticTypeContext);
@override
void defaultConstant(ir.Constant node) {
@@ -749,20 +752,13 @@
@override
void visitStaticTearOffConstant(ir.StaticTearOffConstant node) {
- ir.Member member = node.procedure;
- if (member is ir.Procedure) {
- registry.registerStaticTearOff(member, import);
- } else {
- throw new UnsupportedError("Unexpected member (${member.runtimeType}).");
- }
+ registry.registerStaticTearOff(node.target, import);
}
@override
void visitInstantiationConstant(ir.InstantiationConstant node) {
registry.registerGenericInstantiation(
- node.tearOffConstant.function.computeFunctionType(
- node.tearOffConstant.member.enclosingLibrary.nonNullable),
- node.types);
+ node.tearOffConstant.getType(staticTypeContext), node.types);
visitConstant(node.tearOffConstant);
}
diff --git a/pkg/compiler/lib/src/ir/runtime_type_analysis.dart b/pkg/compiler/lib/src/ir/runtime_type_analysis.dart
index 2fe49b8..3286fc3 100644
--- a/pkg/compiler/lib/src/ir/runtime_type_analysis.dart
+++ b/pkg/compiler/lib/src/ir/runtime_type_analysis.dart
@@ -90,16 +90,14 @@
/// Returns `true` if [node] is of the form `e.runtimeType`.
bool isGetRuntimeType(ir.TreeNode node) {
- return node is ir.PropertyGet &&
+ return node is ir.InstanceGet &&
node.name.text == Identifiers.runtimeType_ ||
- node is ir.InstanceGet && node.name.text == Identifiers.runtimeType_ ||
node is ir.DynamicGet && node.name.text == Identifiers.runtimeType_;
}
/// Returns `true` if [node] is of the form `e.toString()`.
bool isInvokeToString(ir.TreeNode node) {
- return node is ir.MethodInvocation && node.name.text == 'toString' ||
- node is ir.InstanceInvocation && node.name.text == 'toString';
+ return node is ir.InstanceInvocation && node.name.text == 'toString';
}
assert(isGetRuntimeType(node));
@@ -427,17 +425,13 @@
/// Returns `true` if [node] is a potential invocation of an Object method.
bool _isObjectMethodInvocation(ir.TreeNode node) {
- return node is ir.MethodInvocation ||
- node is ir.InstanceInvocation ||
- node is ir.EqualsCall;
+ return node is ir.InstanceInvocation || node is ir.EqualsCall;
}
/// Returns the [_RuntimeTypeAccess] corresponding to [node] if it is an access
/// of `.runtimeType`, and `null` otherwise.
_RuntimeTypeAccess _getRuntimeTypeAccess(ir.TreeNode node) {
- if (node is ir.PropertyGet && node.name.text == 'runtimeType') {
- return _RuntimeTypeAccess(node, node.receiver);
- } else if (node is ir.InstanceGet && node.name.text == 'runtimeType') {
+ if (node is ir.InstanceGet && node.name.text == 'runtimeType') {
return _RuntimeTypeAccess(node, node.receiver);
} else if (node is ir.DynamicGet && node.name.text == 'runtimeType') {
return _RuntimeTypeAccess(node, node.receiver);
@@ -455,10 +449,7 @@
/// Returns the [_EqualsInvocation] corresponding to [node] if it is a call to
/// of `==`, and `null` otherwise.
_EqualsInvocation _getEqualsInvocation(ir.TreeNode node) {
- if (node is ir.MethodInvocation && node.name.text == '==') {
- return _EqualsInvocation(
- node, node.receiver, node.arguments.positional.single);
- } else if (node is ir.EqualsCall) {
+ if (node is ir.EqualsCall) {
return _EqualsInvocation(node, node.left, node.right);
}
return null;
diff --git a/pkg/compiler/lib/src/ir/scope_visitor.dart b/pkg/compiler/lib/src/ir/scope_visitor.dart
index 075e6aa..6fe6cff 100644
--- a/pkg/compiler/lib/src/ir/scope_visitor.dart
+++ b/pkg/compiler/lib/src/ir/scope_visitor.dart
@@ -1026,35 +1026,6 @@
}
@override
- EvaluationComplexity visitMethodInvocation(ir.MethodInvocation node) {
- node.receiver = _handleExpression(node.receiver);
- EvaluationComplexity receiverComplexity = _lastExpressionComplexity;
- ir.TreeNode receiver = node.receiver;
- if (node.arguments.types.isNotEmpty) {
- VariableUse usage;
- if (receiver is ir.VariableGet &&
- (receiver.variable.parent is ir.LocalFunction)) {
- usage =
- new VariableUse.localTypeArgument(receiver.variable.parent, node);
- } else {
- usage = new VariableUse.instanceTypeArgument(node);
- }
- visitNodesInContext(node.arguments.types, usage);
- }
- EvaluationComplexity complexity = visitArguments(node.arguments);
- ir.Member interfaceTarget = node.interfaceTarget;
- if (receiverComplexity.combine(complexity).isConstant &&
- interfaceTarget is ir.Procedure &&
- interfaceTarget.kind == ir.ProcedureKind.Operator) {
- // Only operator invocations can be part of constant expressions so we
- // only try to compute an implicit constant when the receiver and all
- // arguments are constant - and are used in an operator call.
- return _evaluateImplicitConstant(node);
- }
- return const EvaluationComplexity.lazy();
- }
-
- @override
EvaluationComplexity visitInstanceInvocation(ir.InstanceInvocation node) {
node.receiver = _handleExpression(node.receiver);
EvaluationComplexity receiverComplexity = _lastExpressionComplexity;
@@ -1169,16 +1140,6 @@
}
@override
- EvaluationComplexity visitPropertyGet(ir.PropertyGet node) {
- node.receiver = _handleExpression(node.receiver);
- EvaluationComplexity complexity = _lastExpressionComplexity;
- if (complexity.isConstant && node.name.text == 'length') {
- return _evaluateImplicitConstant(node);
- }
- return const EvaluationComplexity.lazy();
- }
-
- @override
EvaluationComplexity visitInstanceGet(ir.InstanceGet node) {
node.receiver = _handleExpression(node.receiver);
EvaluationComplexity complexity = _lastExpressionComplexity;
@@ -1211,13 +1172,6 @@
}
@override
- EvaluationComplexity visitPropertySet(ir.PropertySet node) {
- node.receiver = _handleExpression(node.receiver);
- node.value = _handleExpression(node.value);
- return const EvaluationComplexity.lazy();
- }
-
- @override
EvaluationComplexity visitInstanceSet(ir.InstanceSet node) {
node.receiver = _handleExpression(node.receiver);
node.value = _handleExpression(node.value);
diff --git a/pkg/compiler/lib/src/ir/static_type.dart b/pkg/compiler/lib/src/ir/static_type.dart
index 0ea8c89..1baf922 100644
--- a/pkg/compiler/lib/src/ir/static_type.dart
+++ b/pkg/compiler/lib/src/ir/static_type.dart
@@ -14,7 +14,6 @@
import 'scope.dart';
import 'static_type_base.dart';
import 'static_type_cache.dart';
-import 'util.dart';
/// Enum values for how the target of a static type should be interpreted.
enum ClassRelation {
@@ -268,28 +267,6 @@
.substituteType(interfaceTarget.getterType);
}
- /// Computes the result type of the property access [node] on a receiver of
- /// type [receiverType].
- ///
- /// If the `node.interfaceTarget` is `null` but matches an `Object` member
- /// it is updated to target this member.
- ir.DartType _computePropertyGetType(
- ir.PropertyGet node, ir.DartType receiverType) {
- node.interfaceTarget ??= _resolveDynamicTarget(receiverType, node.name);
- ir.Member interfaceTarget = node.interfaceTarget;
- if (interfaceTarget != null) {
- return _computeInstanceGetType(receiverType, interfaceTarget);
- }
- // Treat the properties of Object specially.
- String nameString = node.name.text;
- if (nameString == 'hashCode') {
- return typeEnvironment.coreTypes.intNonNullableRawType;
- } else if (nameString == 'runtimeType') {
- return typeEnvironment.coreTypes.typeNonNullableRawType;
- }
- return const ir.DynamicType();
- }
-
/// Replaces [original] with [replacement] in the AST and removes cached
/// expression type information for [original].
void _replaceExpression(ir.Expression original, ir.Expression replacement) {
@@ -308,23 +285,6 @@
void handleRuntimeTypeUse(ir.Expression node, RuntimeTypeUseKind kind,
ir.DartType receiverType, ir.DartType argumentType) {}
- @override
- ir.DartType visitPropertyGet(ir.PropertyGet node) {
- ir.DartType receiverType = visitNode(node.receiver);
- ir.DartType resultType = _staticTypeCache._expressionTypes[node] =
- _computePropertyGetType(node, receiverType);
- receiverType = _narrowInstanceReceiver(node.interfaceTarget, receiverType);
- if (node.interfaceTarget != null) {
- handleInstanceGet(node, receiverType, node.interfaceTarget, resultType);
- } else {
- handleDynamicGet(node, receiverType, node.name, resultType);
- }
- if (node.name.text == Identifiers.runtimeType_) {
- handleRuntimeTypeGet(receiverType, node);
- }
- return resultType;
- }
-
void handleRuntimeTypeGet(ir.DartType receiverType, ir.Expression node) {
RuntimeTypeUseData data =
computeRuntimeTypeUse(_pendingRuntimeTypeUseData, node);
@@ -461,37 +421,6 @@
}
@override
- ir.DartType visitPropertySet(ir.PropertySet node) {
- ir.DartType receiverType = visitNode(node.receiver);
- ir.DartType valueType = super.visitPropertySet(node);
- ir.Member interfaceTarget = node.interfaceTarget;
- if (interfaceTarget == null) {
- interfaceTarget = _resolveDynamicSet(receiverType, node.name);
- if (interfaceTarget != null) {
- ir.DartType setterType =
- _computeInstanceSetType(receiverType, interfaceTarget);
- ir.AsExpression implicitCast =
- _createImplicitAsIfNeeded(node.value, valueType, setterType);
- if (implicitCast != null) {
- node.value = implicitCast..parent = node;
- // Visit the newly created as expression; the original value has
- // already been visited.
- handleAsExpression(implicitCast, valueType);
- valueType = setterType;
- }
- node.interfaceTarget = interfaceTarget;
- }
- }
- receiverType = _narrowInstanceReceiver(interfaceTarget, receiverType);
- if (interfaceTarget != null) {
- handleInstanceSet(node, receiverType, node.interfaceTarget, valueType);
- } else {
- handleDynamicSet(node, receiverType, node.name, valueType);
- }
- return valueType;
- }
-
- @override
ir.DartType visitDynamicSet(ir.DynamicSet node) {
ir.DartType receiverType = visitNode(node.receiver);
ir.DartType valueType = visitNode(node.value);
@@ -911,69 +840,6 @@
}
@override
- ir.DartType visitMethodInvocation(ir.MethodInvocation node) {
- ArgumentTypes argumentTypes = _visitArguments(node.arguments);
- ir.DartType receiverType = visitNode(node.receiver);
- ir.Member interfaceTarget = node.interfaceTarget ??
- _resolveDynamicInvocationTarget(
- receiverType, node.name, node.arguments);
- ir.DartType returnType;
- if (interfaceTarget != null) {
- ir.DartType functionType = _computeInstanceInvocationType(
- receiverType, interfaceTarget, node.arguments, argumentTypes);
- if (node.interfaceTarget == null) {
- // We change [node] from being a dynamic invocation to an instance
- // invocation, so we need to add static type checks to the arguments to
- // match instance invocations created by the CFE.
- // TODO(johnniwinther): Handle incremental target improvement.
- _updateMethodInvocationTarget(node, argumentTypes, functionType);
- node.interfaceTarget = interfaceTarget;
- }
- returnType = _getFunctionReturnType(functionType);
- } else {
- returnType = _computeDynamicInvocationReturnType(node, receiverType);
- }
- receiverType = _narrowInstanceReceiver(node.interfaceTarget, receiverType);
- if (node.name.text == '==') {
- TypeMap afterInvocation = typeMap;
- ir.Expression left = node.receiver;
- ir.Expression right = node.arguments.positional[0];
- if (isNullLiteral(right)) {
- _registerEqualsNull(afterInvocation, left);
- }
- if (isNullLiteral(left)) {
- _registerEqualsNull(afterInvocation, right);
- }
- assert(node.interfaceTarget != null);
- handleEqualsCall(left, receiverType, right, argumentTypes.positional[0],
- node.interfaceTarget);
- } else if (node.interfaceTarget != null) {
- handleInstanceInvocation(
- node, receiverType, interfaceTarget, argumentTypes);
- } else {
- ir.Expression receiver = node.receiver;
- if (receiver is ir.VariableGet &&
- receiver.variable.isFinal &&
- receiver.variable.parent is ir.FunctionDeclaration) {
- handleLocalFunctionInvocation(
- node, receiver.variable.parent, argumentTypes, returnType);
- } else {
- handleDynamicInvocation(node, receiverType, argumentTypes, returnType);
- // TODO(johnniwinther): Avoid treating a known function call as a
- // dynamic call when CFE provides a way to distinguish the two.
- if (operatorFromString(node.name.text) == null &&
- receiverType is ir.DynamicType) {
- // We might implicitly call a getter that returns a function.
- handleFunctionInvocation(
- node, const ir.DynamicType(), argumentTypes, returnType);
- }
- }
- }
- _staticTypeCache._expressionTypes[node] = returnType;
- return returnType;
- }
-
- @override
ir.DartType visitInstanceInvocation(ir.InstanceInvocation node) {
ArgumentTypes argumentTypes = _visitArguments(node.arguments);
ir.DartType receiverType = visitNode(node.receiver);
@@ -1060,9 +926,6 @@
receiverType = _narrowInstanceReceiver(interfaceTarget, receiverType);
handleInstanceInvocation(
replacement, receiverType, interfaceTarget, argumentTypes);
- if (replacement is ir.MethodInvocation) {
- _staticTypeCache._expressionTypes[replacement] = resultType;
- }
return resultType;
} else if (node.name == ir.Name.callName &&
(receiverType is ir.FunctionType ||
diff --git a/pkg/compiler/lib/src/ir/static_type_base.dart b/pkg/compiler/lib/src/ir/static_type_base.dart
index 315ee23..05a45ee1 100644
--- a/pkg/compiler/lib/src/ir/static_type_base.dart
+++ b/pkg/compiler/lib/src/ir/static_type_base.dart
@@ -157,11 +157,6 @@
}
@override
- ir.DartType visitPropertySet(ir.PropertySet node) {
- return visitNode(node.value);
- }
-
- @override
ThisInterfaceType visitThisExpression(ir.ThisExpression node) => thisType;
@override
diff --git a/pkg/compiler/lib/src/ir/util.dart b/pkg/compiler/lib/src/ir/util.dart
index eab6a08..5c5021f 100644
--- a/pkg/compiler/lib/src/ir/util.dart
+++ b/pkg/compiler/lib/src/ir/util.dart
@@ -119,18 +119,7 @@
if (node.variable.name == null &&
node.variable.isFinal &&
body is ir.ConditionalExpression) {
- if (body.condition is ir.MethodInvocation && isNullLiteral(body.then)) {
- ir.MethodInvocation invocation = body.condition;
- ir.Expression receiver = invocation.receiver;
- if (invocation.name.text == '==' &&
- receiver is ir.VariableGet &&
- receiver.variable == node.variable &&
- isNullLiteral(invocation.arguments.positional.single)) {
- // We have
- // let #t1 = e0 in #t1 == null ? null : e1
- return new NullAwareExpression(node.variable, body.otherwise);
- }
- } else if (body.condition is ir.EqualsNull) {
+ if (body.condition is ir.EqualsNull) {
ir.EqualsNull equalsNull = body.condition;
ir.Expression receiver = equalsNull.expression;
if (receiver is ir.VariableGet && receiver.variable == node.variable) {
@@ -161,12 +150,10 @@
//
// (let _ = check(prefix) in prefix::field).property
if (node is ir.StaticGet || node is ir.ConstantExpression) {
- while (parent is ir.PropertyGet ||
- parent is ir.InstanceGet ||
+ while (parent is ir.InstanceGet ||
parent is ir.DynamicGet ||
parent is ir.InstanceTearOff ||
parent is ir.FunctionTearOff ||
- parent is ir.MethodInvocation ||
parent is ir.InstanceInvocation ||
parent is ir.InstanceGetterInvocation ||
parent is ir.DynamicInvocation ||
diff --git a/pkg/compiler/lib/src/ir/visitors.dart b/pkg/compiler/lib/src/ir/visitors.dart
index 0335a73..cbcfda9 100644
--- a/pkg/compiler/lib/src/ir/visitors.dart
+++ b/pkg/compiler/lib/src/ir/visitors.dart
@@ -213,15 +213,10 @@
@override
ConstantValue visitStaticTearOffConstant(ir.StaticTearOffConstant node) {
- ir.Member member = node.procedure;
- if (member is ir.Procedure) {
- FunctionEntity function = elementMap.getMethod(member);
- DartType type = elementMap.getFunctionType(member.function);
- return new FunctionConstantValue(function, type);
- } else {
- throw new UnsupportedError(
- "Unexpected torn off member kind (${member.runtimeType}).");
- }
+ ir.Procedure member = node.target;
+ FunctionEntity function = elementMap.getMethod(member);
+ DartType type = elementMap.getFunctionType(member.function);
+ return new FunctionConstantValue(function, type);
}
@override
diff --git a/pkg/compiler/lib/src/js/js_debug.dart b/pkg/compiler/lib/src/js/js_debug.dart
index 9eaca9f..f37ce23 100644
--- a/pkg/compiler/lib/src/js/js_debug.dart
+++ b/pkg/compiler/lib/src/js/js_debug.dart
@@ -7,9 +7,9 @@
library js.debug;
import 'package:js_ast/js_ast.dart';
+import 'package:kernel/text/indentation.dart' show Indentation, Tagging;
import '../io/code_output.dart' show BufferedCodeOutput;
-import '../util/util.dart' show Indentation, Tagging;
/// Unparse the JavaScript [node].
String nodeToString(Node node, {bool pretty: false}) {
diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart
index d17db87..8d15b8c 100644
--- a/pkg/compiler/lib/src/js_backend/backend.dart
+++ b/pkg/compiler/lib/src/js_backend/backend.dart
@@ -6,7 +6,7 @@
import '../common.dart';
import '../common/codegen.dart';
-import '../deferred_load.dart' show DeferredLoadTask;
+import '../deferred_load/deferred_load.dart' show DeferredLoadTask;
import '../dump_info.dart' show DumpInfoTask;
import '../elements/entities.dart';
import '../enqueue.dart' show ResolutionEnqueuer;
diff --git a/pkg/compiler/lib/src/js_backend/backend_impact.dart b/pkg/compiler/lib/src/js_backend/backend_impact.dart
index d50ddc1b..4dcff21 100644
--- a/pkg/compiler/lib/src/js_backend/backend_impact.dart
+++ b/pkg/compiler/lib/src/js_backend/backend_impact.dart
@@ -284,7 +284,6 @@
BackendImpact get constantMapLiteral {
return _constantMapLiteral ??= new BackendImpact(instantiatedClasses: [
_commonElements.constantMapClass,
- _commonElements.constantProtoMapClass,
_commonElements.constantStringMapClass,
_commonElements.generalConstantMapClass,
]);
diff --git a/pkg/compiler/lib/src/js_backend/constant_emitter.dart b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
index dd67c4a..b05bc22 100644
--- a/pkg/compiler/lib/src/js_backend/constant_emitter.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
@@ -330,10 +330,6 @@
constant_system.JavaScriptMapConstant.KEYS_NAME) {
arguments.add(_constantReferenceGenerator(constant.keyList));
} else if (field.name ==
- constant_system.JavaScriptMapConstant.PROTO_VALUE) {
- assert(constant.protoValue != null);
- arguments.add(_constantReferenceGenerator(constant.protoValue));
- } else if (field.name ==
constant_system.JavaScriptMapConstant.JS_DATA_NAME) {
arguments.add(jsGeneralMap());
} else {
@@ -344,8 +340,6 @@
});
if ((className == constant_system.JavaScriptMapConstant.DART_STRING_CLASS &&
emittedArgumentCount != 3) ||
- (className == constant_system.JavaScriptMapConstant.DART_PROTO_CLASS &&
- emittedArgumentCount != 4) ||
(className ==
constant_system.JavaScriptMapConstant.DART_GENERAL_CLASS &&
emittedArgumentCount != 1)) {
diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart
index e8b00b7..359d642 100644
--- a/pkg/compiler/lib/src/js_backend/namer.dart
+++ b/pkg/compiler/lib/src/js_backend/namer.dart
@@ -435,6 +435,26 @@
..remove('P')
..remove('W');
+ static final RegExp _identifierStartRE = RegExp(r'[A-Za-z_$]');
+ static final RegExp _nonIdentifierRE = RegExp(r'[^A-Za-z0-9_$]');
+
+ /// Returns `true` iff [s] begins with an ASCII character that can begin a
+ /// JavaScript identifier.
+ ///
+ /// In particular, [s] must begin with an ASCII letter, an underscore, or a
+ /// dollar sign.
+ static bool startsWithIdentifierCharacter(String s) =>
+ s.startsWith(_identifierStartRE);
+
+ /// Returns a copy of [s] in which characters which cannot be part of an ASCII
+ /// JavaScript identifier have been replaced by underscores.
+ ///
+ /// Note that the result may not be unconditionally used as a JavaScript
+ /// identifier. For example, the result may still begin with a digit or it may
+ /// be a reserved keyword.
+ static String replaceNonIdentifierCharacters(String s) =>
+ s.replaceAll(_nonIdentifierRE, '_');
+
Set<String> _jsReserved = null;
/// Names that cannot be used by members, top level and static
@@ -557,9 +577,12 @@
/// key into maps.
final Map<LibraryEntity, String> _libraryKeys = {};
+ _TypeConstantRepresentationVisitor _typeConstantRepresenter;
+
Namer(this._closedWorld, this.fixedNames) {
_literalGetterPrefix = new StringBackedName(fixedNames.getterPrefix);
_literalSetterPrefix = new StringBackedName(fixedNames.setterPrefix);
+ _typeConstantRepresenter = _TypeConstantRepresentationVisitor(this);
}
JElementEnvironment get _elementEnvironment =>
@@ -618,9 +641,7 @@
///
/// The resulting name is a *proposed name* and is never minified.
String privateName(Name originalName) {
- String text = originalName.text;
-
- text = text.replaceAll(_nonIdentifierRE, '_');
+ String text = replaceNonIdentifierCharacters(originalName.text);
// Public names are easy.
if (!originalName.isPrivate) return text;
@@ -670,7 +691,7 @@
// TODO(sra): If the generator is for a closure's 'call' method, we don't
// need to incorporate the enclosing class.
String className =
- method.enclosingClass.name.replaceAll(_nonIdentifierRE, '_');
+ replaceNonIdentifierCharacters(method.enclosingClass.name);
return '${invocationName}\$body\$${className}';
});
}
@@ -844,9 +865,8 @@
if (element is JSEntity) {
return _disambiguateInternalMember(
element,
- () => (element as JSEntity)
- .declaredName
- .replaceAll(_nonIdentifierRE, '_'));
+ () => replaceNonIdentifierCharacters(
+ (element as JSEntity).declaredName));
}
// If the name of the field might clash with another field,
@@ -859,8 +879,8 @@
if (_closedWorld.isUsedAsMixin(enclosingClass) ||
_isShadowingSuperField(element) ||
_isUserClassExtendingNative(enclosingClass)) {
- String proposeName() => '${enclosingClass.name}_${element.name}'
- .replaceAll(_nonIdentifierRE, '_');
+ String proposeName() => replaceNonIdentifierCharacters(
+ '${enclosingClass.name}_${element.name}');
return _disambiguateInternalMember(element, proposeName);
}
@@ -1204,11 +1224,9 @@
/// Returns a proposed name for the given typedef or class [element].
/// The returned id is guaranteed to be a valid JavaScript identifier.
String _proposeNameForType(Entity element) {
- return element.name.replaceAll(_nonIdentifierRE, '_');
+ return replaceNonIdentifierCharacters(element.name);
}
- static RegExp _nonIdentifierRE = new RegExp(r'[^A-Za-z0-9_$]');
-
/// Returns a proposed name for the given top-level or static member
/// [element]. The returned id is guaranteed to be a valid JavaScript
/// identifier.
@@ -1219,10 +1237,10 @@
return _proposeNameForMember(element.function) + r'$body';
} else if (element.enclosingClass != null) {
ClassEntity enclosingClass = element.enclosingClass;
- return '${enclosingClass.name}_${element.name}'
- .replaceAll(_nonIdentifierRE, '_');
+ return replaceNonIdentifierCharacters(
+ '${enclosingClass.name}_${element.name}');
}
- return element.name.replaceAll(_nonIdentifierRE, '_');
+ return replaceNonIdentifierCharacters(element.name);
}
String _proposeNameForLazyStaticGetter(MemberEntity element) {
@@ -1357,7 +1375,7 @@
String enclosing =
element.enclosingClass == null ? "" : element.enclosingClass.name;
String library = _proposeNameForLibrary(element.library);
- String name = element.name.replaceAll(_nonIdentifierRE, '_');
+ String name = replaceNonIdentifierCharacters(element.name);
return _disambiguateInternalGlobal(
"${library}_${enclosing}_${name}\$closure");
}
@@ -1460,32 +1478,79 @@
}
}
- String getTypeRepresentationForTypeConstant(DartType type) {
- type = type.withoutNullability;
- if (type is DynamicType) return "dynamic";
- if (type is NeverType) return "Never";
- if (type is FutureOrType) {
- return "FutureOr<dynamic>";
- }
- if (type is FunctionType) {
- // TODO(johnniwinther): Add naming scheme for function type literals.
- // These currently only occur from kernel.
- return '()->';
- }
- InterfaceType interface = type;
- String name = uniqueNameForTypeConstantElement(
- interface.element.library, interface.element);
+ String getTypeRepresentationForTypeConstant(DartType type) =>
+ _typeConstantRepresenter.visit(type, null);
+}
+
+class _TypeConstantRepresentationVisitor extends DartTypeVisitor<String, Null> {
+ final Namer _namer;
+
+ _TypeConstantRepresentationVisitor(this._namer);
+
+ String _represent(DartType type) => visit(type, null);
+
+ @override
+ String visitLegacyType(LegacyType type, _) => '${_represent(type.baseType)}*';
+
+ @override
+ String visitNullableType(NullableType type, _) =>
+ '${_represent(type.baseType)}?';
+
+ @override
+ String visitNeverType(NeverType type, _) => 'Never';
+
+ @override
+ String visitVoidType(VoidType type, _) => 'void';
+
+ @override
+ String visitTypeVariableType(TypeVariableType type, _) {
+ throw StateError('Unexpected TypeVariableType $type');
+ }
+
+ @override
+ String visitFunctionTypeVariable(FunctionTypeVariable type, _) {
+ throw StateError('Unexpected FunctionTypeVariable $type');
+ }
+
+ @override
+ String visitFunctionType(FunctionType type, _) {
+ // TODO(johnniwinther): Add naming scheme for function type literals.
+ // These currently only occur from kernel.
+ return '()->';
+ }
+
+ @override
+ String visitInterfaceType(InterfaceType type, _) {
+ String name = _namer.uniqueNameForTypeConstantElement(
+ type.element.library, type.element);
// Type constants can currently only be raw types, so there is no point
// adding ground-term type parameters, as they would just be 'dynamic'.
// TODO(sra): Since the result string is used only in constructing constant
// names, it would result in more readable names if the final string was a
// legal JavaScript identifier.
- if (interface.typeArguments.isEmpty) return name;
+ if (type.typeArguments.isEmpty) return name;
String arguments =
- new List.filled(interface.typeArguments.length, 'dynamic').join(', ');
+ new List.filled(type.typeArguments.length, 'dynamic').join(', ');
return '$name<$arguments>';
}
+
+ @override
+ String visitDynamicType(DynamicType type, _) => 'dynamic';
+
+ @override
+ String visitErasedType(ErasedType type, _) {
+ throw StateError('Unexpected ErasedType $type');
+ }
+
+ @override
+ String visitAnyType(AnyType type, _) {
+ throw StateError('Unexpected AnyType $type');
+ }
+
+ @override
+ String visitFutureOrType(FutureOrType type, _) =>
+ 'FutureOr<${_represent(type.typeArgument)}>';
}
/// Returns a unique suffix for an intercepted accesses to [classes]. This is
diff --git a/pkg/compiler/lib/src/js_backend/resolution_listener.dart b/pkg/compiler/lib/src/js_backend/resolution_listener.dart
index faff4b7..0239d25 100644
--- a/pkg/compiler/lib/src/js_backend/resolution_listener.dart
+++ b/pkg/compiler/lib/src/js_backend/resolution_listener.dart
@@ -7,7 +7,7 @@
import '../common/names.dart' show Identifiers;
import '../common_elements.dart' show KCommonElements, KElementEnvironment;
import '../constants/values.dart';
-import '../deferred_load.dart';
+import '../deferred_load/deferred_load.dart';
import '../elements/entities.dart';
import '../elements/types.dart';
import '../enqueue.dart' show Enqueuer, EnqueuerListener;
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types.dart b/pkg/compiler/lib/src/js_backend/runtime_types.dart
index e7113df..90b7b7c 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types.dart
@@ -829,8 +829,23 @@
}
@override
- void visitFutureOrType(FutureOrType type, _) {
- collect(type.typeArgument);
+ void visitNeverType(NeverType type, _) {}
+
+ @override
+ void visitVoidType(VoidType type, _) {}
+
+ @override
+ void visitTypeVariableType(TypeVariableType type, _) {}
+
+ @override
+ void visitFunctionTypeVariable(FunctionTypeVariable type, _) {}
+
+ @override
+ void visitFunctionType(FunctionType type, _) {
+ collect(type.returnType);
+ collectAll(type.parameterTypes);
+ collectAll(type.optionalParameterTypes);
+ collectAll(type.namedParameterTypes);
}
@override
@@ -840,11 +855,17 @@
}
@override
- void visitFunctionType(FunctionType type, _) {
- collect(type.returnType);
- collectAll(type.parameterTypes);
- collectAll(type.optionalParameterTypes);
- collectAll(type.namedParameterTypes);
+ void visitDynamicType(DynamicType type, _) {}
+
+ @override
+ void visitErasedType(ErasedType type, _) {}
+
+ @override
+ void visitAnyType(AnyType type, _) {}
+
+ @override
+ void visitFutureOrType(FutureOrType type, _) {
+ collect(type.typeArgument);
}
}
@@ -913,8 +934,10 @@
visitType(type.baseType, state);
@override
- void visitFutureOrType(FutureOrType type, TypeVisitorState state) =>
- visitType(type.typeArgument, state);
+ void visitNeverType(NeverType type, TypeVisitorState state) {}
+
+ @override
+ void visitVoidType(VoidType type, TypeVisitorState state) {}
@override
void visitTypeVariableType(TypeVariableType type, TypeVisitorState state) {
@@ -924,15 +947,14 @@
}
@override
- visitInterfaceType(InterfaceType type, TypeVisitorState state) {
- if (onClass != null) {
- onClass(type.element, state: state);
+ visitFunctionTypeVariable(FunctionTypeVariable type, TypeVisitorState state) {
+ if (_visitedFunctionTypeVariables.add(type)) {
+ visitType(type.bound, state);
}
- visitTypes(type.typeArguments, covariantArgument(state));
}
@override
- visitFunctionType(FunctionType type, TypeVisitorState state) {
+ void visitFunctionType(FunctionType type, TypeVisitorState state) {
if (onFunctionType != null) {
onFunctionType(type, state: state);
}
@@ -946,11 +968,25 @@
}
@override
- visitFunctionTypeVariable(FunctionTypeVariable type, TypeVisitorState state) {
- if (_visitedFunctionTypeVariables.add(type)) {
- visitType(type.bound, state);
+ void visitInterfaceType(InterfaceType type, TypeVisitorState state) {
+ if (onClass != null) {
+ onClass(type.element, state: state);
}
+ visitTypes(type.typeArguments, covariantArgument(state));
}
+
+ @override
+ void visitDynamicType(DynamicType type, TypeVisitorState state) {}
+
+ @override
+ void visitErasedType(ErasedType type, TypeVisitorState state) {}
+
+ @override
+ void visitAnyType(AnyType type, TypeVisitorState state) {}
+
+ @override
+ void visitFutureOrType(FutureOrType type, TypeVisitorState state) =>
+ visitType(type.typeArgument, state);
}
/// Runtime type usage for a class.
diff --git a/pkg/compiler/lib/src/js_backend/specialized_checks.dart b/pkg/compiler/lib/src/js_backend/specialized_checks.dart
index dfaabfd..41e8ea7 100644
--- a/pkg/compiler/lib/src/js_backend/specialized_checks.dart
+++ b/pkg/compiler/lib/src/js_backend/specialized_checks.dart
@@ -3,7 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import '../common_elements.dart' show ElementEnvironment, JCommonElements;
-import '../deferred_load.dart';
+import '../deferred_load/deferred_load.dart';
import '../elements/entities.dart';
import '../elements/types.dart';
import '../js_backend/interceptor_data.dart' show InterceptorData;
diff --git a/pkg/compiler/lib/src/js_backend/type_reference.dart b/pkg/compiler/lib/src/js_backend/type_reference.dart
index 4ec5745..a845b95 100644
--- a/pkg/compiler/lib/src/js_backend/type_reference.dart
+++ b/pkg/compiler/lib/src/js_backend/type_reference.dart
@@ -77,6 +77,7 @@
import '../serialization/serialization.dart';
import '../util/util.dart' show Hashing;
import 'frequency_assignment.dart';
+import 'namer.dart';
import 'runtime_types_new.dart' show RecipeEncoder;
/// Run the minifier for 'type$' property names even in non-minified mode,
@@ -582,9 +583,6 @@
final Map<DartType, int> _backrefs = Map.identity();
final List<String> _fragments = [];
- static RegExp identifierStartRE = RegExp(r'[A-Za-z_$]');
- static RegExp nonIdentifierRE = RegExp(r'[^A-Za-z0-9_$]');
-
String run(TypeRecipe recipe) {
if (recipe is TypeExpressionRecipe) {
_visit(recipe.type, null);
@@ -605,7 +603,7 @@
throw StateError('Unexpected recipe: $recipe');
}
String result = _fragments.join('_');
- if (result.startsWith(identifierStartRE)) return result;
+ if (Namer.startsWithIdentifierCharacter(result)) return result;
return 'z' + result;
}
@@ -614,7 +612,7 @@
}
void _identifier(String text) {
- _add(text.replaceAll(nonIdentifierRE, '_'));
+ _add(Namer.replaceNonIdentifierCharacters(text));
}
bool _comma(bool needsComma) {
diff --git a/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart b/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
index 18f96cd..0a0a8f7 100644
--- a/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
+++ b/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
@@ -9,12 +9,14 @@
import '../common/tasks.dart' show CompilerTask;
import '../compiler.dart' show Compiler;
import '../constants/values.dart';
-import '../deferred_load.dart' show OutputUnit;
+import '../deferred_load/deferred_load.dart' show OutputUnit;
import '../elements/entities.dart';
import '../js/js.dart' as jsAst;
import '../js_backend/backend.dart' show CodegenInputs;
import '../js_backend/inferred_data.dart';
import '../js_backend/namer.dart' show Namer;
+import '../js_backend/runtime_types.dart'
+ show RuntimeTypesChecks;
import '../js_model/js_strategy.dart';
import '../options.dart';
import '../universe/codegen_world_builder.dart';
@@ -26,14 +28,13 @@
import 'metadata_collector.dart' show MetadataCollector;
import 'model.dart';
import 'native_emitter.dart' show NativeEmitter;
-import 'type_test_registry.dart' show TypeTestRegistry;
/// Generates the code for all used classes in the program. Static fields (even
/// in classes) are ignored, since they can be treated as non-class elements.
///
/// The code for the containing (used) methods must exist in the `universe`.
class CodeEmitterTask extends CompilerTask {
- TypeTestRegistry typeTestRegistry;
+ RuntimeTypesChecks _rtiChecks;
NativeEmitter _nativeEmitter;
MetadataCollector metadataCollector;
Emitter _emitter;
@@ -77,8 +78,7 @@
void _finalizeRti(CodegenInputs codegen, CodegenWorld codegenWorld) {
// Compute the required type checks to know which classes need a
// 'is$' method.
- typeTestRegistry.computeRequiredTypeChecks(
- _backendStrategy.rtiChecksBuilder, codegenWorld);
+ _rtiChecks = _backendStrategy.rtiChecksBuilder.computeRequiredChecks(codegenWorld, options);
}
/// Creates the [Emitter] for this task.
@@ -101,7 +101,6 @@
_generateSourceMap);
metadataCollector = new MetadataCollector(
_compiler.reporter, _emitter, codegen.rtiRecipeEncoder);
- typeTestRegistry = new TypeTestRegistry(_compiler.options);
});
}
@@ -126,7 +125,7 @@
closedWorld.nativeData,
closedWorld.rtiNeed,
closedWorld.interceptorData,
- typeTestRegistry.rtiChecks,
+ _rtiChecks,
codegenInputs.rtiRecipeEncoder,
codegenWorld.oneShotInterceptorData,
_backendStrategy.customElementsCodegenAnalysis,
@@ -138,7 +137,7 @@
inferredData,
_backendStrategy.sourceInformationStrategy,
closedWorld.sorter,
- typeTestRegistry.rtiNeededClasses,
+ _rtiChecks.requiredClasses,
closedWorld.elementEnvironment.mainFunction);
int size = emitter.emitProgram(programBuilder, codegenWorld);
// TODO(floitsch): we shouldn't need the `neededClasses` anymore.
diff --git a/pkg/compiler/lib/src/js_emitter/js_emitter.dart b/pkg/compiler/lib/src/js_emitter/js_emitter.dart
index 7ad49b8..b5d4f85 100644
--- a/pkg/compiler/lib/src/js_emitter/js_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/js_emitter.dart
@@ -14,4 +14,3 @@
export 'native_generator.dart';
export 'parameter_stub_generator.dart';
export 'runtime_type_generator.dart';
-export 'type_test_registry.dart';
diff --git a/pkg/compiler/lib/src/js_emitter/metadata_collector.dart b/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
index 4923f10..6e1cfaa 100644
--- a/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
+++ b/pkg/compiler/lib/src/js_emitter/metadata_collector.dart
@@ -7,7 +7,7 @@
import 'package:js_ast/src/precedence.dart' as js_precedence;
import '../common.dart';
-import '../deferred_load.dart' show OutputUnit;
+import '../deferred_load/deferred_load.dart' show OutputUnit;
import '../elements/types.dart';
import '../js/js.dart' as jsAst;
diff --git a/pkg/compiler/lib/src/js_emitter/model.dart b/pkg/compiler/lib/src/js_emitter/model.dart
index 156ccb1..147a80c 100644
--- a/pkg/compiler/lib/src/js_emitter/model.dart
+++ b/pkg/compiler/lib/src/js_emitter/model.dart
@@ -6,7 +6,7 @@
import '../common_elements.dart';
import '../constants/values.dart' show ConstantValue;
-import '../deferred_load.dart' show OutputUnit;
+import '../deferred_load/deferred_load.dart' show OutputUnit;
import '../elements/entities.dart';
import '../elements/types.dart';
import '../js/js.dart' as js show Expression, Name, Statement, TokenFinalizer;
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
index b6144a9..f11fd8b 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
@@ -9,7 +9,7 @@
import '../../constants/values.dart'
show ConstantValue, InterceptorConstantValue;
import '../../common_elements.dart' show JCommonElements, JElementEnvironment;
-import '../../deferred_load.dart'
+import '../../deferred_load/deferred_load.dart'
show deferredPartFileName, OutputUnit, OutputUnitData;
import '../../elements/entities.dart';
import '../../elements/types.dart';
diff --git a/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart b/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
index d9bfaab..d77743f 100644
--- a/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
@@ -5,7 +5,7 @@
library dart2js.js_emitter.runtime_type_generator;
import '../common_elements.dart' show CommonElements;
-import '../deferred_load.dart' show OutputUnit, OutputUnitData;
+import '../deferred_load/deferred_load.dart' show OutputUnit, OutputUnitData;
import '../elements/entities.dart';
import '../elements/types.dart';
import '../js/js.dart' as jsAst;
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart
index 0d7a896..3ca343dd 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart
@@ -8,7 +8,7 @@
import '../../common.dart';
import '../../common/codegen.dart';
import '../../constants/values.dart';
-import '../../deferred_load.dart' show OutputUnit;
+import '../../deferred_load/deferred_load.dart' show OutputUnit;
import '../../dump_info.dart';
import '../../elements/entities.dart';
import '../../io/source_information.dart';
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_merger.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_merger.dart
index 9fae89c..58fc707 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_merger.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_merger.dart
@@ -4,7 +4,7 @@
import 'dart:collection';
import '../../common_elements.dart' show ElementEnvironment;
-import '../../deferred_load.dart'
+import '../../deferred_load/deferred_load.dart'
show ImportDescription, OutputUnit, OutputUnitData, deferredPartFileName;
import '../../elements/entities.dart';
import '../../js/js.dart' as js;
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
index d660d94..f905d82 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
@@ -37,7 +37,7 @@
import '../../constants/values.dart'
show ConstantValue, FunctionConstantValue, LateSentinelConstantValue;
import '../../common_elements.dart' show CommonElements, JElementEnvironment;
-import '../../deferred_load.dart' show OutputUnit;
+import '../../deferred_load/deferred_load.dart' show OutputUnit;
import '../../dump_info.dart';
import '../../elements/entities.dart';
import '../../elements/types.dart';
@@ -352,17 +352,17 @@
/// Generates a simple header that provides the compiler's build id.
js.Comment buildGeneratedBy() {
- StringBuffer flavor = new StringBuffer();
- flavor.write('fast startup emitter');
- // TODO(johnniwinther): Remove this flavor.
- flavor.write(', strong');
+ final flavor = StringBuffer();
+ flavor.write(_options.nullSafetyMode);
if (_options.trustPrimitives) flavor.write(', trust primitives');
if (_options.omitImplicitChecks) flavor.write(', omit checks');
if (_options.laxRuntimeTypeToString) {
flavor.write(', lax runtime type');
}
if (_options.useContentSecurityPolicy) flavor.write(', CSP');
- return new js.Comment(generatedBy(_options, flavor: '$flavor'));
+ var featureString = _options.features.flavorString();
+ if (featureString.isNotEmpty) flavor.write(', $featureString');
+ return js.Comment(generatedBy(_options, flavor: '$flavor'));
}
js.Statement buildDeferredInitializerGlobal() {
diff --git a/pkg/compiler/lib/src/js_emitter/type_test_registry.dart b/pkg/compiler/lib/src/js_emitter/type_test_registry.dart
deleted file mode 100644
index c61de53..0000000
--- a/pkg/compiler/lib/src/js_emitter/type_test_registry.dart
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (c) 2014, 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.
-
-library dart2js.js_emitter.type_test_registry;
-
-import '../common.dart';
-import '../elements/entities.dart';
-import '../js_backend/runtime_types.dart'
- show RuntimeTypesChecks, RuntimeTypesChecksBuilder;
-import '../options.dart';
-import '../universe/codegen_world_builder.dart';
-
-/// TODO(joshualitt): Delete this class and store [RuntimeTypeChecks] on
-/// [CodeEmitterTask] directly.
-class TypeTestRegistry {
- final CompilerOptions _options;
-
- RuntimeTypesChecks _rtiChecks;
-
- TypeTestRegistry(this._options);
-
- RuntimeTypesChecks get rtiChecks {
- assert(
- _rtiChecks != null,
- failedAt(NO_LOCATION_SPANNABLE,
- "RuntimeTypesChecks has not been computed yet."));
- return _rtiChecks;
- }
-
- Iterable<ClassEntity> get rtiNeededClasses {
- return rtiChecks.requiredClasses;
- }
-
- void computeRequiredTypeChecks(
- RuntimeTypesChecksBuilder rtiChecksBuilder, CodegenWorld codegenWorld) {
- _rtiChecks = rtiChecksBuilder.computeRequiredChecks(codegenWorld, _options);
- }
-}
diff --git a/pkg/compiler/lib/src/js_model/element_map_impl.dart b/pkg/compiler/lib/src/js_model/element_map_impl.dart
index a1c35bf..a2f7118 100644
--- a/pkg/compiler/lib/src/js_model/element_map_impl.dart
+++ b/pkg/compiler/lib/src/js_model/element_map_impl.dart
@@ -9,7 +9,7 @@
import 'package:kernel/class_hierarchy.dart' as ir;
import 'package:kernel/core_types.dart' as ir;
import 'package:kernel/src/bounds_checks.dart' as ir;
-
+import 'package:kernel/text/debug_printer.dart';
import 'package:kernel/type_environment.dart' as ir;
import '../closure.dart' show BoxLocal, ThisLocal;
@@ -17,7 +17,7 @@
import '../common/names.dart';
import '../common_elements.dart';
import '../constants/values.dart';
-import '../deferred_load.dart';
+import '../deferred_load/deferred_load.dart';
import '../elements/entities.dart';
import '../elements/entity_utils.dart' as utils;
import '../elements/indexed.dart';
@@ -27,7 +27,6 @@
import '../ir/cached_static_type.dart';
import '../ir/closure.dart';
import '../ir/constants.dart';
-import '../ir/debug.dart';
import '../ir/element_map.dart';
import '../ir/types.dart';
import '../ir/visitors.dart';
@@ -1245,9 +1244,6 @@
// TODO(efortuna): This is screaming for a common interface between
// PropertyGet and SuperPropertyGet (and same for *Get). Talk to kernel
// folks.
- if (node is ir.PropertyGet) {
- return getGetterSelector(node.name);
- }
if (node is ir.InstanceGet) {
return getGetterSelector(node.name);
}
@@ -1263,9 +1259,6 @@
if (node is ir.SuperPropertyGet) {
return getGetterSelector(node.name);
}
- if (node is ir.PropertySet) {
- return getSetterSelector(node.name);
- }
if (node is ir.InstanceSet) {
return getSetterSelector(node.name);
}
diff --git a/pkg/compiler/lib/src/js_model/js_strategy.dart b/pkg/compiler/lib/src/js_model/js_strategy.dart
index 431efc6..c24a46b 100644
--- a/pkg/compiler/lib/src/js_model/js_strategy.dart
+++ b/pkg/compiler/lib/src/js_model/js_strategy.dart
@@ -13,7 +13,7 @@
import '../common/work.dart';
import '../common_elements.dart' show CommonElements, ElementEnvironment;
import '../compiler.dart';
-import '../deferred_load.dart' hide WorkItem;
+import '../deferred_load/deferred_load.dart' hide WorkItem;
import '../dump_info.dart';
import '../elements/entities.dart';
import '../enqueue.dart';
diff --git a/pkg/compiler/lib/src/js_model/js_world.dart b/pkg/compiler/lib/src/js_model/js_world.dart
index 66f8efc..f2c3c08 100644
--- a/pkg/compiler/lib/src/js_model/js_world.dart
+++ b/pkg/compiler/lib/src/js_model/js_world.dart
@@ -9,7 +9,7 @@
import '../common.dart';
import '../common/names.dart';
import '../common_elements.dart' show JCommonElements, JElementEnvironment;
-import '../deferred_load.dart';
+import '../deferred_load/deferred_load.dart';
import '../elements/entities.dart';
import '../elements/entity_utils.dart' as utils;
import '../elements/names.dart';
diff --git a/pkg/compiler/lib/src/js_model/js_world_builder.dart b/pkg/compiler/lib/src/js_model/js_world_builder.dart
index 8a4928d..087d57a 100644
--- a/pkg/compiler/lib/src/js_model/js_world_builder.dart
+++ b/pkg/compiler/lib/src/js_model/js_world_builder.dart
@@ -9,7 +9,7 @@
import '../common_elements.dart';
import '../constants/constant_system.dart' as constant_system;
import '../constants/values.dart';
-import '../deferred_load.dart';
+import '../deferred_load/deferred_load.dart';
import '../elements/entities.dart';
import '../elements/indexed.dart';
import '../elements/names.dart';
@@ -944,15 +944,13 @@
DartType type = typeConverter.visit(constant.type, toBackendEntity);
ListConstantValue keys = constant.keyList.accept(this, null);
List<ConstantValue> values = _handleValues(constant.values);
- ConstantValue protoValue = constant.protoValue?.accept(this, null);
if (identical(keys, constant.keys) &&
identical(values, constant.values) &&
- type == constant.type &&
- protoValue == constant.protoValue) {
+ type == constant.type) {
return constant;
}
return new constant_system.JavaScriptMapConstant(
- type, keys, values, protoValue, constant.onlyStringKeys);
+ type, keys, values, constant.onlyStringKeys);
}
@override
diff --git a/pkg/compiler/lib/src/kernel/dart2js_target.dart b/pkg/compiler/lib/src/kernel/dart2js_target.dart
index dc97091..74ad9f6 100644
--- a/pkg/compiler/lib/src/kernel/dart2js_target.dart
+++ b/pkg/compiler/lib/src/kernel/dart2js_target.dart
@@ -2,6 +2,8 @@
// 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.
+// @dart=2.12
+
// TODO(johnniwinther): Add a test that ensure that this library doesn't depend
// on the dart2js internals.
library compiler.src.kernel.dart2js_target;
@@ -78,9 +80,7 @@
@override
final String name;
- final CompilerOptions options;
-
- Map<String, ir.Class> _nativeClasses;
+ final CompilerOptions? options;
Dart2jsTarget(this.name, this.flags, {this.options});
@@ -89,7 +89,7 @@
@override
int get enabledLateLowerings =>
- (options != null && options.experimentLateInstanceVariables)
+ (options != null && options!.experimentLateInstanceVariables)
? LateLowering.none
: _enabledLateLowerings;
@@ -105,13 +105,10 @@
bool get supportsExplicitGetterCalls => false;
@override
- bool get supportsNewMethodInvocationEncoding => true;
-
- @override
int get enabledConstructorTearOffLowerings => ConstructorTearOffLowering.none;
@override
- List<String> get extraRequiredLibraries => _requiredLibraries[name];
+ List<String> get extraRequiredLibraries => _requiredLibraries[name]!;
@override
List<String> get extraIndexedLibraries => const [
@@ -151,12 +148,12 @@
CoreTypes coreTypes,
ClassHierarchy hierarchy,
List<ir.Library> libraries,
- Map<String, String> environmentDefines,
+ Map<String, String>? environmentDefines,
DiagnosticReporter diagnosticReporter,
- ReferenceFromIndex referenceFromIndex,
- {void logger(String msg),
- ChangedStructureNotifier changedStructureNotifier}) {
- _nativeClasses ??= JsInteropChecks.getNativeClasses(component);
+ ReferenceFromIndex? referenceFromIndex,
+ {void Function(String msg)? logger,
+ ChangedStructureNotifier? changedStructureNotifier}) {
+ var nativeClasses = JsInteropChecks.getNativeClasses(component);
var jsUtilOptimizer = JsUtilOptimizer(coreTypes, hierarchy);
for (var library in libraries) {
// TODO (rileyporter): Merge js_util optimizations with other lowerings
@@ -165,7 +162,7 @@
JsInteropChecks(
coreTypes,
diagnosticReporter as DiagnosticReporter<Message, LocatedMessage>,
- _nativeClasses)
+ nativeClasses)
.visitLibrary(library);
}
lowering.transformLibraries(libraries, coreTypes, hierarchy, options);
@@ -192,7 +189,7 @@
}
return new ir.StaticInvocation(
coreTypes.index
- .getTopLevelMember('dart:core', '_createInvocationMirror'),
+ .getTopLevelProcedure('dart:core', '_createInvocationMirror'),
new ir.Arguments(<ir.Expression>[
new ir.StringLiteral(name)..fileOffset = offset,
new ir.ListLiteral(
@@ -282,7 +279,7 @@
@override
final bool supportsUnevaluatedConstants;
- const Dart2jsConstantsBackend({this.supportsUnevaluatedConstants});
+ const Dart2jsConstantsBackend({required this.supportsUnevaluatedConstants});
@override
NumberSemantics get numberSemantics => NumberSemantics.js;
diff --git a/pkg/compiler/lib/src/kernel/element_map_impl.dart b/pkg/compiler/lib/src/kernel/element_map_impl.dart
index d568cea..7bf5db7 100644
--- a/pkg/compiler/lib/src/kernel/element_map_impl.dart
+++ b/pkg/compiler/lib/src/kernel/element_map_impl.dart
@@ -11,6 +11,7 @@
import 'package:kernel/class_hierarchy.dart' as ir;
import 'package:kernel/core_types.dart' as ir;
import 'package:kernel/src/bounds_checks.dart' as ir;
+import 'package:kernel/text/debug_printer.dart';
import 'package:kernel/type_environment.dart' as ir;
import '../common.dart';
@@ -26,7 +27,6 @@
import '../frontend_strategy.dart';
import '../ir/annotations.dart';
import '../ir/constants.dart';
-import '../ir/debug.dart';
import '../ir/element_map.dart';
import '../ir/impact.dart';
import '../ir/impact_data.dart';
diff --git a/pkg/compiler/lib/src/kernel/invocation_mirror_constants.dart b/pkg/compiler/lib/src/kernel/invocation_mirror_constants.dart
index 246429e..1d24a30 100644
--- a/pkg/compiler/lib/src/kernel/invocation_mirror_constants.dart
+++ b/pkg/compiler/lib/src/kernel/invocation_mirror_constants.dart
@@ -2,6 +2,8 @@
// 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.
+// @dart=2.12
+
const int invocationMirrorMethodKind = 0;
const int invocationMirrorGetterKind = 1;
const int invocationMirrorSetterKind = 2;
diff --git a/pkg/compiler/lib/src/kernel/kernel_strategy.dart b/pkg/compiler/lib/src/kernel/kernel_strategy.dart
index eb961d7..43b81f4 100644
--- a/pkg/compiler/lib/src/kernel/kernel_strategy.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_strategy.dart
@@ -15,7 +15,7 @@
import '../common/work.dart';
import '../common_elements.dart';
import '../compiler.dart';
-import '../deferred_load.dart' show DeferredLoadTask;
+import '../deferred_load/deferred_load.dart' show DeferredLoadTask;
import '../elements/entities.dart';
import '../enqueue.dart';
import '../environment.dart' as env;
diff --git a/pkg/compiler/lib/src/kernel/transformations/factory_specializer.dart b/pkg/compiler/lib/src/kernel/transformations/factory_specializer.dart
index ebc00ae..87ad9f3 100644
--- a/pkg/compiler/lib/src/kernel/transformations/factory_specializer.dart
+++ b/pkg/compiler/lib/src/kernel/transformations/factory_specializer.dart
@@ -2,6 +2,8 @@
// 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.
+// @dart=2.12
+
import 'package:kernel/kernel.dart';
import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
import 'package:kernel/core_types.dart';
@@ -26,10 +28,6 @@
TreeNode transformStaticInvocation(
StaticInvocation invocation, Member contextMember) {
final target = invocation.target;
- if (target == null) {
- return invocation;
- }
-
final transformer = transformers[target];
if (transformer != null) {
return transformer(invocation, contextMember);
diff --git a/pkg/compiler/lib/src/kernel/transformations/late_lowering.dart b/pkg/compiler/lib/src/kernel/transformations/late_lowering.dart
index 210bbcb..212aac6 100644
--- a/pkg/compiler/lib/src/kernel/transformations/late_lowering.dart
+++ b/pkg/compiler/lib/src/kernel/transformations/late_lowering.dart
@@ -2,6 +2,8 @@
// 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.
+// @dart=2.12
+
import 'package:kernel/ast.dart';
import 'package:kernel/core_types.dart';
import 'package:kernel/type_algebra.dart';
@@ -11,9 +13,9 @@
class _Reader {
final Procedure _procedure;
final FunctionType _type;
- FunctionType _typeWithoutTypeParameters;
+ late final FunctionType _typeWithoutTypeParameters;
- _Reader(this._procedure) : _type = _procedure.getterType {
+ _Reader(this._procedure) : _type = _procedure.getterType as FunctionType {
_typeWithoutTypeParameters = _type.withoutTypeParameters;
}
}
@@ -31,7 +33,8 @@
// Each map contains the mapping from late local variables to cells for a
// given function scope. All late local variables are lowered to cells.
- final List<Map<VariableDeclaration, VariableDeclaration>> _variableCells = [];
+ final List<Map<VariableDeclaration, VariableDeclaration>?> _variableCells =
+ [];
// Uninitialized late static fields are lowered to cells.
final Map<Field, Field> _fieldCells = {};
@@ -44,9 +47,9 @@
// [Reference] to its [Field].
final Map<Procedure, Field> _getterToField = {};
- Member _contextMember;
+ Member? _contextMember;
- LateLowering(this._coreTypes, CompilerOptions _options)
+ LateLowering(this._coreTypes, CompilerOptions? _options)
: _omitLateNames = _options?.omitLateNames ?? false,
_lowerInstanceVariables =
_options?.experimentLateInstanceVariables ?? false,
@@ -55,7 +58,7 @@
_readInitialized = _Reader(_coreTypes.initializedCellRead),
_readInitializedFinal = _Reader(_coreTypes.initializedCellReadFinal);
- Nullability get nonNullable => _contextMember.enclosingLibrary.nonNullable;
+ Nullability get nonNullable => _contextMember!.enclosingLibrary.nonNullable;
bool _shouldLowerVariable(VariableDeclaration variable) => variable.isLate;
@@ -73,7 +76,7 @@
String _mangleFieldName(Field field) {
assert(_shouldLowerInstanceField(field));
- Class cls = field.parent;
+ Class cls = field.enclosingClass!;
return '_#${cls.name}#${field.name.text}';
}
@@ -81,7 +84,7 @@
List<Reference> additionalExports = library.additionalExports;
Set<Reference> newExports = {};
additionalExports.removeWhere((Reference reference) {
- Field cell = _fieldCells[reference.node];
+ Field? cell = _fieldCells[reference.node];
if (cell == null) return false;
newExports.add(cell.getterReference);
return true;
@@ -123,7 +126,7 @@
Arguments([name, initializer])..fileOffset = fileOffset)
..fileOffset = fileOffset;
- StringLiteral _nameLiteral(String name, int fileOffset) =>
+ StringLiteral _nameLiteral(String? name, int fileOffset) =>
StringLiteral(name ?? '')..fileOffset = fileOffset;
InstanceInvocation _callReader(
@@ -138,7 +141,8 @@
interfaceTarget: procedure,
functionType:
Substitution.fromPairs(reader._type.typeParameters, typeArguments)
- .substituteType(reader._typeWithoutTypeParameters))
+ .substituteType(reader._typeWithoutTypeParameters)
+ as FunctionType)
..fileOffset = fileOffset;
}
@@ -161,7 +165,7 @@
_variableCells.removeLast();
}
- VariableDeclaration _lookupVariableCell(VariableDeclaration variable) {
+ VariableDeclaration? _lookupVariableCell(VariableDeclaration variable) {
assert(_shouldLowerVariable(variable));
for (final scope in _variableCells) {
if (scope == null) continue;
@@ -190,7 +194,7 @@
VariableDeclaration _uninitializedVariableCell(VariableDeclaration variable) {
assert(_shouldLowerUninitializedVariable(variable));
int fileOffset = variable.fileOffset;
- String name = variable.name;
+ String? name = variable.name;
final cell = VariableDeclaration(name,
initializer:
_callCellConstructor(_nameLiteral(name, fileOffset), fileOffset),
@@ -213,11 +217,11 @@
VariableDeclaration _initializedVariableCell(VariableDeclaration variable) {
assert(_shouldLowerInitializedVariable(variable));
int fileOffset = variable.fileOffset;
- String name = variable.name;
+ String? name = variable.name;
final cell = VariableDeclaration(name,
initializer: _callInitializedCellConstructor(
_nameLiteral(name, fileOffset),
- _initializerClosure(variable.initializer, variable.type),
+ _initializerClosure(variable.initializer!, variable.type),
fileOffset),
type: InterfaceType(_coreTypes.initializedCellClass, nonNullable),
isFinal: true)
@@ -226,7 +230,7 @@
}
TreeNode transformVariableDeclaration(
- VariableDeclaration variable, Member contextMember) {
+ VariableDeclaration variable, Member? contextMember) {
_contextMember = contextMember;
if (!_shouldLowerVariable(variable)) return variable;
@@ -309,8 +313,8 @@
Name name = field.name;
String nameText = name.text;
DartType type = field.type;
- Expression initializer = field.initializer;
- Class enclosingClass = field.enclosingClass;
+ Expression? initializer = field.initializer;
+ Class enclosingClass = field.enclosingClass!;
Name mangledName = Name(_mangleFieldName(field), field.enclosingLibrary);
Field backingField = Field.mutable(mangledName,
@@ -436,7 +440,7 @@
VariableGet setterValueRead() =>
VariableGet(setterValue)..fileOffset = fileOffset;
- Statement setterBody() {
+ Statement? setterBody() {
if (!field.isFinal) {
// The lowered setter for `late T field;` and `late T field = e;` is
//
@@ -470,7 +474,7 @@
}
}
- Statement body = setterBody();
+ Statement? body = setterBody();
if (body != null) {
Procedure setter = Procedure(
name,
@@ -506,17 +510,14 @@
// getter for the backing field.
// TODO(fishythefish): Clean this up when [FieldInitializer] maintains a
// correct [Reference] to its [Field].
- NamedNode node = initializer.fieldReference.node;
- assert(node != null);
+ NamedNode node = initializer.fieldReference.node!;
Field backingField;
if (node is Field) {
if (!_shouldLowerInstanceField(node)) return initializer;
backingField = _backingInstanceField(node);
} else {
- backingField = _getterToField[node];
+ backingField = _getterToField[node]!;
}
- assert(backingField != null);
-
return FieldInitializer(backingField, initializer.value)
..fileOffset = initializer.fileOffset;
}
diff --git a/pkg/compiler/lib/src/kernel/transformations/list_factory_specializer.dart b/pkg/compiler/lib/src/kernel/transformations/list_factory_specializer.dart
index c315199..7df3d66 100644
--- a/pkg/compiler/lib/src/kernel/transformations/list_factory_specializer.dart
+++ b/pkg/compiler/lib/src/kernel/transformations/list_factory_specializer.dart
@@ -2,6 +2,8 @@
// 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.
+// @dart=2.12
+
import 'package:kernel/ast.dart';
import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
import 'package:kernel/clone.dart' show CloneVisitorNotMembers;
@@ -26,11 +28,11 @@
ListFactorySpecializer(this.coreTypes, this.hierarchy)
: _listGenerateFactory =
- coreTypes.index.getMember('dart:core', 'List', 'generate'),
+ coreTypes.index.getProcedure('dart:core', 'List', 'generate'),
_arrayAllocateFixedFactory = coreTypes.index
- .getMember('dart:_interceptors', 'JSArray', 'allocateFixed'),
+ .getProcedure('dart:_interceptors', 'JSArray', 'allocateFixed'),
_arrayAllocateGrowableFactory = coreTypes.index
- .getMember('dart:_interceptors', 'JSArray', 'allocateGrowable'),
+ .getProcedure('dart:_interceptors', 'JSArray', 'allocateGrowable'),
_jsArrayClass =
coreTypes.index.getClass('dart:_interceptors', 'JSArray'),
_intClass = coreTypes.index.getClass('dart:core', 'int') {
@@ -42,17 +44,14 @@
});
}
- Procedure _intPlus;
- Procedure get intPlus =>
- _intPlus ??= hierarchy.getInterfaceMember(_intClass, Name('+'));
+ late final Procedure intPlus =
+ hierarchy.getInterfaceMember(_intClass, Name('+')) as Procedure;
- Procedure _intLess;
- Procedure get intLess =>
- _intLess ??= hierarchy.getInterfaceMember(_intClass, Name('<'));
+ late final Procedure intLess =
+ hierarchy.getInterfaceMember(_intClass, Name('<')) as Procedure;
- Procedure _jsArrayIndexSet;
- Procedure get jsArrayIndexSet => _jsArrayIndexSet ??=
- hierarchy.getInterfaceMember(_jsArrayClass, Name('[]='));
+ late final Procedure jsArrayIndexSet =
+ hierarchy.getInterfaceMember(_jsArrayClass, Name('[]=')) as Procedure;
/// Replace calls to `List.generate(length, (i) => e)` with an expansion
///
@@ -74,7 +73,7 @@
assert(args.positional.length == 2);
final length = args.positional[0];
final generator = args.positional[1];
- final bool growable =
+ final bool? growable =
_getConstantNamedOptionalArgument(args, 'growable', true);
if (growable == null) return node;
@@ -90,18 +89,18 @@
// If the length is a constant, use the constant directly so that the
// inferrer can see the constant length.
- int /*?*/ lengthConstant = _getLengthArgument(args);
- VariableDeclaration lengthVariable;
+ int? lengthConstant = _getLengthArgument(args);
+ VariableDeclaration? lengthVariable;
Expression getLength() {
if (lengthConstant != null) return IntLiteral(lengthConstant);
lengthVariable ??= VariableDeclaration('_length',
initializer: length, isFinal: true, type: intType)
..fileOffset = node.fileOffset;
- return VariableGet(lengthVariable)..fileOffset = node.fileOffset;
+ return VariableGet(lengthVariable!)..fileOffset = node.fileOffset;
}
- TreeNode allocation = StaticInvocation(
+ Expression allocation = StaticInvocation(
growable ? _arrayAllocateGrowableFactory : _arrayAllocateFixedFactory,
Arguments(
[getLength()],
@@ -122,11 +121,8 @@
initializer: IntLiteral(0),
type: intType,
)..fileOffset = node.fileOffset;
- indexVariable.fileOffset = (generator as FunctionExpression)
- .function
- .positionalParameters
- .first
- .fileOffset;
+ indexVariable.fileOffset =
+ generator.function.positionalParameters.first.fileOffset;
final loop = ForStatement(
// initializers: _i = 0
@@ -138,7 +134,7 @@
Name('<'),
Arguments([getLength()]),
interfaceTarget: intLess,
- functionType: intLess.getterType,
+ functionType: intLess.getterType as FunctionType,
),
// updates: _i++
[
@@ -164,7 +160,7 @@
return BlockExpression(
Block([
- if (lengthVariable != null) lengthVariable,
+ if (lengthVariable != null) lengthVariable!,
listVariable,
loop,
]),
@@ -185,7 +181,7 @@
/// Returns constant value of the first argument in [args], or null if it is
/// not a constant.
- int /*?*/ _getLengthArgument(Arguments args) {
+ int? _getLengthArgument(Arguments args) {
if (args.positional.length < 1) return null;
final value = args.positional.first;
if (value is IntLiteral) {
@@ -202,7 +198,7 @@
/// Returns constant value of the only named optional argument in [args], or
/// null if it is not a bool constant. Returns [defaultValue] if optional
/// argument is not passed. Argument is asserted to have the given [name].
- bool /*?*/ _getConstantNamedOptionalArgument(
+ bool? _getConstantNamedOptionalArgument(
Arguments args, String name, bool defaultValue) {
if (args.named.isEmpty) {
return defaultValue;
@@ -224,15 +220,15 @@
/// Choose a name for the `_list` temporary. If the `List.generate` expression
/// is an initializer for a variable, use that name so that dart2js can try to
/// use one JavaScript variable with the source name for 'both' variables.
- String _listNameFromContext(Expression node) {
- TreeNode parent = node.parent;
+ String? _listNameFromContext(Expression node) {
+ TreeNode? parent = node.parent;
if (parent is VariableDeclaration) return parent.name;
return '_list';
}
String _indexNameFromContext(FunctionExpression generator) {
final function = generator.function;
- String /*?*/ candidate = function.positionalParameters.first.name;
+ String? candidate = function.positionalParameters.first.name;
if (candidate == null || candidate == '' || candidate == '_') return '_i';
return candidate;
}
@@ -246,8 +242,8 @@
final int constructorFileOffset;
final VariableDeclaration listVariable;
final FunctionNode function;
- VariableDeclaration argument;
- VariableDeclaration parameter;
+ late final VariableDeclaration argument;
+ late final VariableDeclaration parameter;
int functionNestingLevel = 0;
ListGenerateLoopBodyInliner(this.listFactorySpecializer,
@@ -298,7 +294,7 @@
}
Statement run() {
- final body = cloneInContext(function.body);
+ Statement body = cloneInContext(function.body!);
return Block([parameter, body]);
}
@@ -335,9 +331,11 @@
value,
]),
interfaceTarget: listFactorySpecializer.jsArrayIndexSet,
- functionType: Substitution.fromInterfaceType(listVariable.type)
- .substituteType(
- listFactorySpecializer.jsArrayIndexSet.getterType))
+ functionType:
+ Substitution.fromInterfaceType(listVariable.type as InterfaceType)
+ .substituteType(
+ listFactorySpecializer.jsArrayIndexSet.getterType)
+ as FunctionType)
..isInvariant = true
..isBoundsSafe = true
..fileOffset = constructorFileOffset,
@@ -355,7 +353,7 @@
@override
VariableDeclaration getVariableClone(VariableDeclaration variable) {
- VariableDeclaration clone = super.getVariableClone(variable);
+ VariableDeclaration? clone = super.getVariableClone(variable);
return clone ?? variable;
}
}
diff --git a/pkg/compiler/lib/src/kernel/transformations/lowering.dart b/pkg/compiler/lib/src/kernel/transformations/lowering.dart
index e9cad5b..e04314b 100644
--- a/pkg/compiler/lib/src/kernel/transformations/lowering.dart
+++ b/pkg/compiler/lib/src/kernel/transformations/lowering.dart
@@ -2,6 +2,8 @@
// 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.
+// @dart=2.12
+
import 'package:kernel/ast.dart';
import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
import 'package:kernel/core_types.dart' show CoreTypes;
@@ -16,7 +18,7 @@
/// Each transformation is applied locally to AST nodes of certain types after
/// transforming children nodes.
void transformLibraries(List<Library> libraries, CoreTypes coreTypes,
- ClassHierarchy hierarchy, CompilerOptions options) {
+ ClassHierarchy hierarchy, CompilerOptions? options) {
final transformer = _Lowering(coreTypes, hierarchy, options);
libraries.forEach(transformer.visitLibrary);
@@ -31,10 +33,10 @@
final FactorySpecializer factorySpecializer;
final LateLowering _lateLowering;
- Member _currentMember;
+ Member? _currentMember;
_Lowering(
- CoreTypes coreTypes, ClassHierarchy hierarchy, CompilerOptions _options)
+ CoreTypes coreTypes, ClassHierarchy hierarchy, CompilerOptions? _options)
: factorySpecializer = FactorySpecializer(coreTypes, hierarchy),
_lateLowering = LateLowering(coreTypes, _options);
@@ -51,7 +53,7 @@
@override
TreeNode visitStaticInvocation(StaticInvocation node) {
node.transformChildren(this);
- return factorySpecializer.transformStaticInvocation(node, _currentMember);
+ return factorySpecializer.transformStaticInvocation(node, _currentMember!);
}
@override
@@ -71,37 +73,37 @@
@override
TreeNode visitVariableGet(VariableGet node) {
node.transformChildren(this);
- return _lateLowering.transformVariableGet(node, _currentMember);
+ return _lateLowering.transformVariableGet(node, _currentMember!);
}
@override
TreeNode visitVariableSet(VariableSet node) {
node.transformChildren(this);
- return _lateLowering.transformVariableSet(node, _currentMember);
+ return _lateLowering.transformVariableSet(node, _currentMember!);
}
@override
TreeNode visitField(Field node) {
_currentMember = node;
node.transformChildren(this);
- return _lateLowering.transformField(node, _currentMember);
+ return _lateLowering.transformField(node, _currentMember!);
}
@override
TreeNode visitFieldInitializer(FieldInitializer node) {
node.transformChildren(this);
- return _lateLowering.transformFieldInitializer(node, _currentMember);
+ return _lateLowering.transformFieldInitializer(node, _currentMember!);
}
@override
TreeNode visitStaticGet(StaticGet node) {
node.transformChildren(this);
- return _lateLowering.transformStaticGet(node, _currentMember);
+ return _lateLowering.transformStaticGet(node, _currentMember!);
}
@override
TreeNode visitStaticSet(StaticSet node) {
node.transformChildren(this);
- return _lateLowering.transformStaticSet(node, _currentMember);
+ return _lateLowering.transformStaticSet(node, _currentMember!);
}
}
diff --git a/pkg/compiler/lib/src/options.dart b/pkg/compiler/lib/src/options.dart
index c5288eb..3598ad3 100644
--- a/pkg/compiler/lib/src/options.dart
+++ b/pkg/compiler/lib/src/options.dart
@@ -2,6 +2,8 @@
// 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.
+// @dart=2.12
+
library dart2js.src.options;
import 'package:front_end/src/api_unstable/dart2js.dart' as fe;
@@ -32,8 +34,8 @@
class FeatureOption {
final String flag;
final bool isNegativeFlag;
- bool _state;
- bool get isEnabled => _state;
+ bool? _state;
+ bool get isEnabled => _state!;
bool get isDisabled => !isEnabled;
void set state(bool value) {
assert(_state == null);
@@ -67,10 +69,10 @@
FeatureOption newHolders = FeatureOption('new-holders');
/// [FeatureOption]s which default to enabled.
- List<FeatureOption> shipping;
+ late final List<FeatureOption> shipping = [legacyJavaScript];
/// [FeatureOption]s which default to disabled.
- List<FeatureOption> canary;
+ late final List<FeatureOption> canary = [newHolders];
/// Forces canary feature on. This must run after [Option].parse.
void forceCanary() {
@@ -79,12 +81,21 @@
}
}
- // Initialize feature lists.
- FeatureOptions() {
- shipping = [legacyJavaScript];
- canary = [newHolders];
+ /// Returns a list of enabled features as a comma separated string.
+ String flavorString() {
+ bool _shouldPrint(FeatureOption feature) {
+ return feature.isNegativeFlag ? feature.isDisabled : feature.isEnabled;
+ }
+ String _toString(FeatureOption feature) {
+ return feature.isNegativeFlag ? 'no-${feature.flag}' : feature.flag;
+ }
+ Iterable<String> _listToString(List<FeatureOption> options) {
+ return options.where(_shouldPrint).map(_toString);
+ }
+ return _listToString(shipping).followedBy(_listToString(canary)).join(', ');
}
+ /// Parses a [List<String>] and enables / disables features as necessary.
void parse(List<String> options) {
_extractFeatures(options, shipping, FeatureStatus.shipping);
_extractFeatures(options, canary, FeatureStatus.canary);
@@ -122,12 +133,12 @@
/// as few as possible.
class CompilerOptions implements DiagnosticOptions {
/// The entry point of the application that is being compiled.
- Uri entryPoint;
+ Uri? entryPoint;
/// Location of the package configuration file.
///
/// If not null then [packageRoot] should be null.
- Uri packageConfig;
+ Uri? packageConfig;
/// List of kernel files to load.
///
@@ -140,18 +151,18 @@
/// At this time, this list points to full kernel files. In the future, we may
/// use a list of outline files for modular compiles, and only use full kernel
/// files for linking.
- List<Uri> dillDependencies;
+ List<Uri>? dillDependencies;
/// Location from which serialized inference data is read.
///
/// If this is set, the [entryPoint] is expected to be a .dill file and the
/// frontend work is skipped.
- Uri readDataUri;
+ Uri? readDataUri;
/// Location to which inference data is serialized.
///
/// If this is set, the compilation stops after type inference.
- Uri writeDataUri;
+ Uri? writeDataUri;
/// Serialize data without the closed world.
/// TODO(joshualitt) make this the default right after landing in Google3 and
@@ -162,22 +173,22 @@
///
/// If this is set, the [entryPoint] is expected to be a .dill file and the
/// frontend work is skipped.
- Uri readClosedWorldUri;
+ Uri? readClosedWorldUri;
/// Location to which inference data is serialized.
///
/// If this is set, the compilation stops after computing the closed world.
- Uri writeClosedWorldUri;
+ Uri? writeClosedWorldUri;
/// Location from which codegen data is read.
///
/// If this is set, the compilation starts at codegen enqueueing.
- Uri readCodegenUri;
+ Uri? readCodegenUri;
/// Location to which codegen data is serialized.
///
/// If this is set, the compilation stops after code generation.
- Uri writeCodegenUri;
+ Uri? writeCodegenUri;
/// Whether to run only the CFE and emit the generated kernel file in
/// [outputUri].
@@ -205,7 +216,7 @@
explicitExperimentalFlags: explicitExperimentalFlags);
/// A possibly null state object for kernel compilation.
- fe.InitializedCompilerState kernelInitializedCompilerState;
+ fe.InitializedCompilerState? kernelInitializedCompilerState;
/// Whether we allow mocking compilation of libraries such as dart:io and
/// dart:html for unit testing purposes.
@@ -230,11 +241,11 @@
/// Location where to generate a map containing details of how deferred
/// libraries are subdivided.
- Uri deferredMapUri;
+ Uri? deferredMapUri;
/// Location where to generate an internal format representing the deferred
/// graph.
- Uri deferredGraphUri;
+ Uri? deferredGraphUri;
/// The maximum number of deferred fragments to generate. If the number of
/// fragments exceeds this amount, then they may be merged.
@@ -242,8 +253,8 @@
/// will not merge fragments with unrelated dependencies and thus we may
/// generate more fragments than the 'mergeFragmentsThreshold' under some
/// situations.
- int mergeFragmentsThreshold = null; // default value, no max.
- int _mergeFragmentsThreshold;
+ int? mergeFragmentsThreshold = null; // default value, no max.
+ int? _mergeFragmentsThreshold;
/// Whether to disable inlining during the backend optimizations.
// TODO(sigmund): negate, so all flags are positive
@@ -276,7 +287,7 @@
/// Diagnostic option: List of packages for which warnings and hints are
/// reported. If `null`, no package warnings or hints are reported. If
/// empty, all warnings and hints are reported.
- List<String> shownPackageWarnings; // &&&&&
+ List<String>? shownPackageWarnings;
/// Whether to disable global type inference.
bool disableTypeInference = false;
@@ -304,7 +315,7 @@
/// If set, SSA intermediate form is dumped for methods with names matching
/// this RegExp pattern.
- String dumpSsaPattern = null;
+ String? dumpSsaPattern = null;
/// Whether we allow passing an extra argument to `assert`, containing a
/// reason for why an assertion fails. (experimental)
@@ -354,19 +365,19 @@
bool generateSourceMap = true;
/// URI of the main output of the compiler.
- Uri outputUri;
+ Uri? outputUri;
/// Location of the libraries specification file.
- Uri librariesSpecificationUri;
+ Uri? librariesSpecificationUri;
/// Location of the kernel platform `.dill` files.
- Uri platformBinaries;
+ Uri? platformBinaries;
/// Whether to print legacy types as T* rather than T.
bool printLegacyStars = false;
/// URI where the compiler should generate the output source map file.
- Uri sourceMapUri;
+ Uri? sourceMapUri;
/// The compiler is run from the build bot.
bool testMode = false;
@@ -387,29 +398,29 @@
/// What should the compiler do with parameter type assertions.
///
/// This is an internal configuration option derived from other flags.
- CheckPolicy defaultParameterCheckPolicy;
+ late CheckPolicy defaultParameterCheckPolicy;
/// What should the compiler do with implicit downcasts.
///
/// This is an internal configuration option derived from other flags.
- CheckPolicy defaultImplicitDowncastCheckPolicy;
+ late CheckPolicy defaultImplicitDowncastCheckPolicy;
/// What the compiler should do with a boolean value in a condition context
/// when the language specification says it is a runtime error for it to be
/// null.
///
/// This is an internal configuration option derived from other flags.
- CheckPolicy defaultConditionCheckPolicy;
+ late CheckPolicy defaultConditionCheckPolicy;
/// What should the compiler do with explicit casts.
///
/// This is an internal configuration option derived from other flags.
- CheckPolicy defaultExplicitCastCheckPolicy;
+ late CheckPolicy defaultExplicitCastCheckPolicy;
/// What should the compiler do with List index bounds checks.
///
/// This is an internal configuration option derived from other flags.
- CheckPolicy defaultIndexBoundsCheckPolicy;
+ late CheckPolicy defaultIndexBoundsCheckPolicy;
/// Whether to generate code compliant with content security policy (CSP).
bool useContentSecurityPolicy = false;
@@ -492,14 +503,14 @@
}
/// If specified, a bundle of optimizations to enable (or disable).
- int optimizationLevel = null;
+ int? optimizationLevel = null;
/// The shard to serialize when using [writeCodegenUri].
- int codegenShard;
+ int? codegenShard;
/// The number of shards to serialize when using [writeCodegenUri] or to
/// deserialize when using [readCodegenUri].
- int codegenShards;
+ int? codegenShards;
/// Arguments passed to the front end about how it is invoked.
///
@@ -515,7 +526,7 @@
/// Verbosity level used for filtering messages during compilation.
fe.Verbosity verbosity = fe.Verbosity.all;
- FeatureOptions features;
+ late FeatureOptions features;
// -------------------------------------------------
// Options for deprecated features
@@ -523,11 +534,11 @@
/// Create an options object by parsing flags from [options].
static CompilerOptions parse(List<String> options,
- {FeatureOptions featureOptions,
- Uri librariesSpecificationUri,
- Uri platformBinaries,
- void Function(String) onError,
- void Function(String) onWarning}) {
+ {FeatureOptions? featureOptions,
+ Uri? librariesSpecificationUri,
+ Uri? platformBinaries,
+ void Function(String)? onError,
+ void Function(String)? onWarning}) {
if (featureOptions == null) featureOptions = FeatureOptions();
featureOptions.parse(options);
Map<fe.ExperimentalFlag, bool> explicitExperimentalFlags =
@@ -545,7 +556,7 @@
..benchmarkingExperiment =
_hasOption(options, Flags.benchmarkingExperiment)
..buildId =
- _extractStringOption(options, '--build-id=', _UNDETERMINED_BUILD_ID)
+ _extractStringOption(options, '--build-id=', _UNDETERMINED_BUILD_ID)!
..compileForServer = _hasOption(options, Flags.serverMode)
..deferredMapUri = _extractUriOption(options, '--deferred-map=')
..deferredGraphUri =
@@ -638,11 +649,11 @@
.._mergeFragmentsThreshold =
_extractIntOption(options, '${Flags.mergeFragmentsThreshold}=')
..cfeInvocationModes = fe.InvocationMode.parseArguments(
- _extractStringOption(options, '${Flags.cfeInvocationModes}=', ''),
+ _extractStringOption(options, '${Flags.cfeInvocationModes}=', '')!,
onError: onError)
..verbosity = fe.Verbosity.parseArgument(
_extractStringOption(
- options, '${Flags.verbosity}=', fe.Verbosity.defaultValue),
+ options, '${Flags.verbosity}=', fe.Verbosity.defaultValue)!,
onError: onError)
..features = featureOptions;
}
@@ -654,7 +665,7 @@
if (librariesSpecificationUri == null) {
throw new ArgumentError("[librariesSpecificationUri] is null.");
}
- if (librariesSpecificationUri.path.endsWith('/')) {
+ if (librariesSpecificationUri!.path.endsWith('/')) {
throw new ArgumentError(
"[librariesSpecificationUri] should be a file: $librariesSpecificationUri");
}
@@ -697,12 +708,12 @@
disableTypeInference = true;
disableRtiOptimization = true;
}
- if (optimizationLevel >= 2) {
+ if (optimizationLevel! >= 2) {
enableMinification = true;
laxRuntimeTypeToString = true;
omitLateNames = true;
}
- if (optimizationLevel >= 3) {
+ if (optimizationLevel! >= 3) {
omitImplicitChecks = true;
}
if (optimizationLevel == 4) {
@@ -752,7 +763,7 @@
/// Returns `true` if warnings and hints are shown for all packages.
@override
bool get showAllPackageWarnings {
- return shownPackageWarnings != null && shownPackageWarnings.isEmpty;
+ return shownPackageWarnings != null && shownPackageWarnings!.isEmpty;
}
/// Returns `true` if warnings and hints are hidden for all packages.
@@ -767,7 +778,7 @@
}
if (shownPackageWarnings != null) {
return uri.scheme == 'package' &&
- shownPackageWarnings.contains(uri.pathSegments.first);
+ shownPackageWarnings!.contains(uri.pathSegments.first);
}
return false;
}
@@ -794,8 +805,8 @@
'isEmitted=$isEmitted)';
}
-String _extractStringOption(
- List<String> options, String prefix, String defaultValue) {
+String? _extractStringOption(
+ List<String> options, String prefix, String? defaultValue) {
for (String option in options) {
if (option.startsWith(prefix)) {
return option.substring(prefix.length);
@@ -804,13 +815,13 @@
return defaultValue;
}
-Uri _extractUriOption(List<String> options, String prefix) {
- String option = _extractStringOption(options, prefix, null);
+Uri? _extractUriOption(List<String> options, String prefix) {
+ String? option = _extractStringOption(options, prefix, null);
return (option == null) ? null : Uri.parse(option);
}
-int _extractIntOption(List<String> options, String prefix) {
- String option = _extractStringOption(options, prefix, null);
+int? _extractIntOption(List<String> options, String prefix) {
+ String? option = _extractStringOption(options, prefix, null);
return (option == null) ? null : int.parse(option);
}
@@ -821,7 +832,7 @@
/// Extract list of comma separated values provided for [flag]. Returns an
/// empty list if [option] contain [flag] without arguments. Returns `null` if
/// [option] doesn't contain [flag] with or without arguments.
-List<String> _extractOptionalCsvOption(List<String> options, String flag) {
+List<String>? _extractOptionalCsvOption(List<String> options, String flag) {
String prefix = '$flag=';
for (String option in options) {
if (option == flag) {
@@ -837,15 +848,15 @@
/// Extract list of comma separated Uris provided for [flag]. Returns an
/// empty list if [option] contain [flag] without arguments. Returns `null` if
/// [option] doesn't contain [flag] with or without arguments.
-List<Uri> _extractUriListOption(List<String> options, String flag) {
- List<String> stringUris = _extractOptionalCsvOption(options, flag);
+List<Uri>? _extractUriListOption(List<String> options, String flag) {
+ List<String>? stringUris = _extractOptionalCsvOption(options, flag);
if (stringUris == null) return null;
return stringUris.map(Uri.parse).toList();
}
Map<fe.ExperimentalFlag, bool> _extractExperiments(List<String> options,
- {void Function(String) onError, void Function(String) onWarning}) {
- List<String> experiments =
+ {void Function(String)? onError, void Function(String)? onWarning}) {
+ List<String>? experiments =
_extractOptionalCsvOption(options, Flags.enableLanguageExperiments);
onError ??= (String error) => throw new ArgumentError(error);
onWarning ??= (String warning) => print(warning);
diff --git a/pkg/compiler/lib/src/serialization/abstract_sink.dart b/pkg/compiler/lib/src/serialization/abstract_sink.dart
index 1bd824c..d4a4746 100644
--- a/pkg/compiler/lib/src/serialization/abstract_sink.dart
+++ b/pkg/compiler/lib/src/serialization/abstract_sink.dart
@@ -506,7 +506,6 @@
writeDartType(constant.type);
writeConstant(constant.keyList);
writeConstants(constant.values);
- writeConstantOrNull(constant.protoValue);
writeBool(constant.onlyStringKeys);
break;
case ConstantValueKind.CONSTRUCTED:
diff --git a/pkg/compiler/lib/src/serialization/abstract_source.dart b/pkg/compiler/lib/src/serialization/abstract_source.dart
index a06007f..ed14321 100644
--- a/pkg/compiler/lib/src/serialization/abstract_source.dart
+++ b/pkg/compiler/lib/src/serialization/abstract_source.dart
@@ -519,10 +519,9 @@
DartType type = readDartType();
ListConstantValue keyList = readConstant();
List<ConstantValue> values = readConstants();
- ConstantValue protoValue = readConstantOrNull();
bool onlyStringKeys = readBool();
return new constant_system.JavaScriptMapConstant(
- type, keyList, values, protoValue, onlyStringKeys);
+ type, keyList, values, onlyStringKeys);
case ConstantValueKind.CONSTRUCTED:
InterfaceType type = readDartType();
Map<FieldEntity, ConstantValue> fields =
diff --git a/pkg/compiler/lib/src/serialization/node_indexer.dart b/pkg/compiler/lib/src/serialization/node_indexer.dart
index e0c56a2..1e52a8f 100644
--- a/pkg/compiler/lib/src/serialization/node_indexer.dart
+++ b/pkg/compiler/lib/src/serialization/node_indexer.dart
@@ -106,12 +106,6 @@
}
@override
- void visitPropertyGet(ir.PropertyGet node) {
- registerNode(node);
- super.visitPropertyGet(node);
- }
-
- @override
void visitInstanceGet(ir.InstanceGet node) {
registerNode(node);
super.visitInstanceGet(node);
@@ -136,12 +130,6 @@
}
@override
- void visitPropertySet(ir.PropertySet node) {
- registerNode(node);
- super.visitPropertySet(node);
- }
-
- @override
void visitInstanceSet(ir.InstanceSet node) {
registerNode(node);
super.visitInstanceSet(node);
@@ -154,12 +142,6 @@
}
@override
- void visitMethodInvocation(ir.MethodInvocation node) {
- registerNode(node);
- super.visitMethodInvocation(node);
- }
-
- @override
void visitInstanceInvocation(ir.InstanceInvocation node) {
registerNode(node);
super.visitInstanceInvocation(node);
@@ -313,6 +295,10 @@
void visitConstructorTearOffConstant(ir.ConstructorTearOffConstant node) {}
@override
+ void visitRedirectingFactoryTearOffConstant(
+ ir.RedirectingFactoryTearOffConstant node) {}
+
+ @override
void visitInstantiationConstant(ir.InstantiationConstant node) {
node.tearOffConstant.accept(this);
}
diff --git a/pkg/compiler/lib/src/serialization/serialization.dart b/pkg/compiler/lib/src/serialization/serialization.dart
index e684b95..590efec 100644
--- a/pkg/compiler/lib/src/serialization/serialization.dart
+++ b/pkg/compiler/lib/src/serialization/serialization.dart
@@ -9,7 +9,7 @@
import '../closure.dart';
import '../constants/constant_system.dart' as constant_system;
import '../constants/values.dart';
-import '../deferred_load.dart';
+import '../deferred_load/deferred_load.dart';
import '../diagnostics/source_span.dart';
import '../elements/entities.dart';
import '../elements/indexed.dart';
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index 765039b..9afc681 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -12,7 +12,7 @@
import '../common_elements.dart';
import '../constants/constant_system.dart' as constant_system;
import '../constants/values.dart';
-import '../deferred_load.dart';
+import '../deferred_load/deferred_load.dart';
import '../dump_info.dart';
import '../elements/entities.dart';
import '../elements/jumps.dart';
@@ -3467,11 +3467,6 @@
}
@override
- void visitPropertyGet(ir.PropertyGet node) {
- _handlePropertyGet(node, node.receiver, node.name);
- }
-
- @override
void visitVariableGet(ir.VariableGet node) {
ir.VariableDeclaration variable = node.variable;
HInstruction letBinding = _letBindings[variable];
@@ -3516,11 +3511,6 @@
}
@override
- void visitPropertySet(ir.PropertySet node) {
- _handlePropertySet(node, node.receiver, node.name, node.value);
- }
-
- @override
void visitSuperPropertySet(ir.SuperPropertySet node) {
SourceInformation sourceInformation =
_sourceInformationBuilder.buildAssignment(node);
@@ -4491,8 +4481,8 @@
} else if (closure is ir.ConstantExpression &&
closure.constant is ir.StaticTearOffConstant) {
ir.StaticTearOffConstant tearOff = closure.constant;
- ir.Member member = tearOff.procedure;
- if (member is ir.Procedure && handleTarget(member)) {
+ ir.Procedure member = tearOff.target;
+ if (handleTarget(member)) {
return;
}
}
@@ -5032,10 +5022,7 @@
isIntercepted: isIntercepted);
}
invoke.instructionContext = _currentFrame.member;
- if (node is ir.MethodInvocation) {
- invoke.isInvariant = node.isInvariant;
- invoke.isBoundsSafe = node.isBoundsSafe;
- } else if (node is ir.InstanceInvocation) {
+ if (node is ir.InstanceInvocation) {
invoke.isInvariant = node.isInvariant;
invoke.isBoundsSafe = node.isBoundsSafe;
}
@@ -5274,11 +5261,6 @@
_sourceInformationBuilder.buildCall(node, node));
}
- @override
- void visitMethodInvocation(ir.MethodInvocation node) {
- _handleMethodInvocation(node, node.receiver, node.arguments);
- }
-
void _handleEquals(ir.Expression node, ir.Expression left,
HInstruction leftInstruction, HInstruction rightInstruction) {
_pushDynamicInvocation(
@@ -7229,15 +7211,6 @@
}
@override
- visitPropertyGet(ir.PropertyGet node) {
- registerCall();
- registerRegularNode();
- registerReductiveNode();
- skipReductiveNodes(() => visit(node.name));
- visit(node.receiver);
- }
-
- @override
visitInstanceGet(ir.InstanceGet node) {
registerCall();
registerRegularNode();
@@ -7265,16 +7238,6 @@
}
@override
- visitPropertySet(ir.PropertySet node) {
- registerCall();
- registerRegularNode();
- registerReductiveNode();
- skipReductiveNodes(() => visit(node.name));
- visit(node.receiver);
- visit(node.value);
- }
-
- @override
visitInstanceSet(ir.InstanceSet node) {
registerCall();
registerRegularNode();
@@ -7343,16 +7306,6 @@
}
@override
- visitMethodInvocation(ir.MethodInvocation node) {
- registerRegularNode();
- registerReductiveNode();
- registerCall();
- visit(node.receiver);
- skipReductiveNodes(() => visit(node.name));
- _processArguments(node.arguments, null);
- }
-
- @override
visitInstanceInvocation(ir.InstanceInvocation node) {
registerRegularNode();
registerReductiveNode();
diff --git a/pkg/compiler/lib/src/tracer.dart b/pkg/compiler/lib/src/tracer.dart
index a02c499..c2c5c5f 100644
--- a/pkg/compiler/lib/src/tracer.dart
+++ b/pkg/compiler/lib/src/tracer.dart
@@ -4,11 +4,12 @@
library tracer;
+import 'package:kernel/text/indentation.dart' show Indentation;
+
import '../compiler_new.dart' as api;
import 'options.dart' show CompilerOptions;
import 'ssa/nodes.dart' as ssa show HGraph;
import 'ssa/ssa_tracer.dart' show HTracer;
-import 'util/util.dart' show Indentation;
import 'world.dart' show JClosedWorld;
String TRACE_FILTER_PATTERN_FOR_TEST;
diff --git a/pkg/compiler/lib/src/util/util.dart b/pkg/compiler/lib/src/util/util.dart
index 3a9949d..6a7894f 100644
--- a/pkg/compiler/lib/src/util/util.dart
+++ b/pkg/compiler/lib/src/util/util.dart
@@ -2,16 +2,16 @@
// 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.
+// @dart=2.12
+
library dart2js.util;
import 'package:front_end/src/api_unstable/dart2js.dart'
- show $BACKSLASH, $CR, $DEL, $DQ, $LF, $LS, $PS, $TAB, Link;
+ show $BACKSLASH, $CR, $DEL, $DQ, $LF, $LS, $PS, $TAB;
export 'maplet.dart';
export 'setlet.dart';
-part 'indentation.dart';
-
/// Helper functions for creating hash codes.
class Hashing {
/// If an integer is masked by this constant, the result is guaranteed to be
@@ -45,13 +45,13 @@
}
/// Mix the bits of `object.hashCode` with [existing].
- static int objectHash(Object object, [int existing = 0]) {
+ static int objectHash(Object? object, [int existing = 0]) {
return mixHashCodeBits(existing, object.hashCode);
}
/// Mix the bits of `.hashCode` all non-null objects.
- static int objectsHash(Object obj1,
- [Object obj2, Object obj3, Object obj4, Object obj5]) {
+ static int objectsHash(Object? obj1,
+ [Object? obj2, Object? obj3, Object? obj4, Object? obj5]) {
int hash = 0;
if (obj5 != null) hash = objectHash(obj5, hash);
if (obj4 != null) hash = objectHash(obj4, hash);
@@ -61,7 +61,7 @@
}
/// Mix the bits of the element hash codes of [list] with [existing].
- static int listHash(List list, [int existing = 0]) {
+ static int listHash(List? list, [int existing = 0]) {
int h = existing;
if (list != null) {
int length = list.length;
@@ -73,7 +73,7 @@
}
/// Mix the bits of the element hash codes of [iterable] with [existing].
- static int setHash<E>(Iterable<E> iterable, [int existing = 0]) {
+ static int setHash<E>(Iterable<E>? iterable, [int existing = 0]) {
int h = existing;
if (iterable != null) {
for (E e in iterable) {
@@ -111,7 +111,7 @@
}
}
-bool identicalElements<E>(List<E> a, List<E> b) {
+bool identicalElements<E>(List<E>? a, List<E>? b) {
if (identical(a, b)) return true;
if (a == null || b == null) return false;
if (a.length != b.length) return false;
@@ -123,7 +123,7 @@
return true;
}
-bool equalElements<E>(List<E> a, List<E> b) {
+bool equalElements<E>(List<E>? a, List<E>? b) {
if (identical(a, b)) return true;
if (a == null || b == null) return false;
if (a.length != b.length) return false;
@@ -135,13 +135,13 @@
return true;
}
-bool equalSets<E>(Set<E> a, Set<E> b) {
+bool equalSets<E>(Set<E>? a, Set<E>? b) {
if (identical(a, b)) return true;
if (a == null || b == null) return false;
return a.length == b.length && a.containsAll(b) && b.containsAll(a);
}
-bool equalMaps<K, V>(Map<K, V> a, Map<K, V> b) {
+bool equalMaps<K, V>(Map<K, V>? a, Map<K, V>? b) {
if (identical(a, b)) return true;
if (a == null || b == null) return false;
if (a.length != b.length) return false;
@@ -153,7 +153,7 @@
/// File name prefix used to shorten the file name in stack traces printed by
/// [trace].
-String stackTraceFilePrefix = null;
+String? stackTraceFilePrefix = null;
/// Writes the characters of [string] on [buffer]. The characters
/// are escaped as suitable for JavaScript and JSON. [buffer] is
diff --git a/pkg/compiler/lib/src/world.dart b/pkg/compiler/lib/src/world.dart
index e1f8a31..a17fc60 100644
--- a/pkg/compiler/lib/src/world.dart
+++ b/pkg/compiler/lib/src/world.dart
@@ -12,7 +12,7 @@
JElementEnvironment,
KCommonElements,
KElementEnvironment;
-import 'deferred_load.dart';
+import 'deferred_load/deferred_load.dart';
import 'diagnostics/diagnostic_listener.dart';
import 'elements/entities.dart';
import 'elements/names.dart';
diff --git a/pkg/compiler/test/analyses/dart2js_allowed.json b/pkg/compiler/test/analyses/dart2js_allowed.json
index 807fcb7..9048e82 100644
--- a/pkg/compiler/test/analyses/dart2js_allowed.json
+++ b/pkg/compiler/test/analyses/dart2js_allowed.json
@@ -43,7 +43,7 @@
"Dynamic invocation of 'toSet'.": 1,
"Dynamic invocation of 'toList'.": 1
},
- "pkg/compiler/lib/src/deferred_load.dart": {
+ "pkg/compiler/lib/src/deferred_load/deferred_load.dart": {
"Dynamic access of 'memberContext'.": 1,
"Dynamic access of 'name'.": 1
},
diff --git a/pkg/compiler/test/codegen/data_2/unused_empty_map.dart b/pkg/compiler/test/codegen/data_2/unused_empty_map.dart
index d9e0363..0ac9666 100644
--- a/pkg/compiler/test/codegen/data_2/unused_empty_map.dart
+++ b/pkg/compiler/test/codegen/data_2/unused_empty_map.dart
@@ -2,6 +2,8 @@
// 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.
+// ignore_for_file: unused_local_variable
+
@pragma('dart2js:noInline')
// No code to construct unused map.
/*member: foo1:function() {
diff --git a/pkg/compiler/test/deferred/constant_emission_test_helper.dart b/pkg/compiler/test/deferred/constant_emission_test_helper.dart
index d8fc00a..0f05dc3 100644
--- a/pkg/compiler/test/deferred/constant_emission_test_helper.dart
+++ b/pkg/compiler/test/deferred/constant_emission_test_helper.dart
@@ -9,7 +9,7 @@
import 'package:compiler/src/compiler.dart';
import 'package:compiler/src/constants/values.dart';
-import 'package:compiler/src/deferred_load.dart';
+import 'package:compiler/src/deferred_load/deferred_load.dart';
import 'package:compiler/src/elements/entities.dart';
import 'package:compiler/src/elements/types.dart';
import 'package:compiler/src/js_emitter/model.dart';
diff --git a/pkg/compiler/test/deferred/load_graph_segmentation_test.dart b/pkg/compiler/test/deferred/load_graph_segmentation_test.dart
index 823899f..64ec62d 100644
--- a/pkg/compiler/test/deferred/load_graph_segmentation_test.dart
+++ b/pkg/compiler/test/deferred/load_graph_segmentation_test.dart
@@ -10,7 +10,7 @@
import 'package:async_helper/async_helper.dart';
import 'package:compiler/src/compiler.dart';
-import 'package:compiler/src/deferred_load.dart';
+import 'package:compiler/src/deferred_load/deferred_load.dart';
import 'package:compiler/src/js_emitter/startup_emitter/fragment_merger.dart';
import 'package:expect/expect.dart';
import '../helpers/memory_compiler.dart';
@@ -42,6 +42,7 @@
var mainOutputUnit = closedWorld.outputUnitData.mainOutputUnit;
var backendStrategy = compiler.backendStrategy;
+ // ignore: deprecated_member_use_from_same_package
var classes = backendStrategy.emitterTask.neededClasses;
var inputElement = classes.where((e) => e.name == 'InputElement').single;
dynamic lib1 = lookupLibrary("memory:lib1.dart");
diff --git a/pkg/compiler/test/deferred_loading/data/shadowed_types/lib_shared.dart b/pkg/compiler/test/deferred_loading/data/shadowed_types/lib_shared.dart
index 5b20db1..09e4bf0 100644
--- a/pkg/compiler/test/deferred_loading/data/shadowed_types/lib_shared.dart
+++ b/pkg/compiler/test/deferred_loading/data/shadowed_types/lib_shared.dart
@@ -4,7 +4,7 @@
/*class: A:
class_unit=1{libb},
- type_unit=2{libb, liba}
+ type_unit=2{liba, libb}
*/
/*member: A.:member_unit=1{libb}*/
class A {}
@@ -25,7 +25,7 @@
/*class: D:
class_unit=1{libb},
- type_unit=2{libb, liba}
+ type_unit=2{liba, libb}
*/
/*member: D.:member_unit=1{libb}*/
class D {}
diff --git a/pkg/compiler/test/deferred_loading/data/shadowed_types/main.dart b/pkg/compiler/test/deferred_loading/data/shadowed_types/main.dart
index d32f920..9c29878 100644
--- a/pkg/compiler/test/deferred_loading/data/shadowed_types/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/shadowed_types/main.dart
@@ -6,7 +6,7 @@
a_pre_fragments=[
p1: {units: [3{liba}], usedBy: [], needs: []},
p2: {units: [1{libb}], usedBy: [], needs: []},
- p3: {units: [2{libb, liba}], usedBy: [], needs: []}],
+ p3: {units: [2{liba, libb}], usedBy: [], needs: []}],
b_finalized_fragments=[
f1: [3{liba}],
f2: [1{libb}]],
@@ -19,7 +19,7 @@
a_pre_fragments=[
p1: {units: [3{liba}], usedBy: [p3], needs: []},
p2: {units: [1{libb}], usedBy: [p3], needs: []},
- p3: {units: [2{libb, liba}], usedBy: [], needs: [p1, p2]}],
+ p3: {units: [2{liba, libb}], usedBy: [], needs: [p1, p2]}],
b_finalized_fragments=[
f1: [3{liba}],
f2: [1{libb}]],
diff --git a/pkg/compiler/test/deferred_loading/deferred_loading_test.dart b/pkg/compiler/test/deferred_loading/deferred_loading_test.dart
index 621ba83..aecbf54 100644
--- a/pkg/compiler/test/deferred_loading/deferred_loading_test.dart
+++ b/pkg/compiler/test/deferred_loading/deferred_loading_test.dart
@@ -5,24 +5,10 @@
// @dart = 2.7
import 'dart:io' hide Link;
-import 'package:_fe_analyzer_shared/src/testing/features.dart';
import 'package:async_helper/async_helper.dart';
-import 'package:compiler/src/closure.dart';
-import 'package:compiler/src/common.dart';
-import 'package:compiler/src/compiler.dart';
-import 'package:compiler/src/deferred_load.dart';
-import 'package:compiler/src/elements/entities.dart';
-import 'package:compiler/src/ir/util.dart';
-import 'package:compiler/src/js_model/element_map.dart';
-import 'package:compiler/src/js_model/js_world.dart';
-import 'package:compiler/src/js_emitter/startup_emitter/fragment_merger.dart';
-import 'package:compiler/src/kernel/kernel_strategy.dart';
-import 'package:expect/expect.dart';
-import '../equivalence/id_equivalence.dart';
+import 'package:compiler/src/deferred_load/deferred_load.dart';
import '../equivalence/id_equivalence_helper.dart';
-import 'package:compiler/src/constants/values.dart';
-
-import 'package:kernel/ast.dart' as ir;
+import 'deferred_loading_test_helper.dart';
/// Add in options to pass to the compiler like
/// `Flags.disableTypeInference` or `Flags.disableInlining`
@@ -44,342 +30,3 @@
[twoDeferredFragmentConfig, threeDeferredFragmentConfig]);
});
}
-
-// For ease of testing and making our tests easier to read, we impose an
-// artificial constraint of requiring every deferred import use a different
-// named prefix per test. We enforce this constraint here by checking that no
-// prefix name responds to two different libraries.
-Map<String, Uri> importPrefixes = {};
-
-String importPrefixString(OutputUnit unit) {
- StringBuffer sb = StringBuffer();
- bool first = true;
- for (ImportEntity import in unit.imports) {
- if (!first) sb.write(', ');
- sb.write('${import.name}');
- first = false;
- Expect.isTrue(import.isDeferred);
-
- if (importPrefixes.containsKey(import.name)) {
- var existing = importPrefixes[import.name];
- var current = import.enclosingLibraryUri;
- Expect.equals(
- existing,
- current,
- '\n Duplicate prefix \'${import.name}\' used in both:\n'
- ' - $existing and\n'
- ' - $current.\n'
- ' We require using unique prefixes on these tests to make '
- 'the expectations more readable.');
- }
- importPrefixes[import.name] = import.enclosingLibraryUri;
- }
- return sb.toString();
-}
-
-/// Create a consistent string representation of [OutputUnit]s for both
-/// KImportEntities and ImportElements.
-String outputUnitString(OutputUnit unit) {
- if (unit == null) return 'none';
- String sb = importPrefixString(unit);
- return '${unit.name}{$sb}';
-}
-
-Map<String, List<PreFragment>> buildPreFragmentMap(
- Map<String, List<FinalizedFragment>> fragmentsToLoad,
- List<PreFragment> preDeferredFragments) {
- Map<FinalizedFragment, PreFragment> fragmentMap = {};
- for (var preFragment in preDeferredFragments) {
- fragmentMap[preFragment.finalizedFragment] = preFragment;
- }
- Map<String, List<PreFragment>> preFragmentMap = {};
- fragmentsToLoad.forEach((loadId, fragments) {
- List<PreFragment> preFragments = [];
- for (var fragment in fragments) {
- preFragments.add(fragmentMap[fragment]);
- }
- preFragmentMap[loadId] = preFragments.toList();
- });
- return preFragmentMap;
-}
-
-class Tags {
- static const String cls = 'class_unit';
- static const String member = 'member_unit';
- static const String closure = 'closure_unit';
- static const String constants = 'constants';
- static const String type = 'type_unit';
- // The below tags appear in a single block comment in the main file.
- // To keep them appearing in sequential order we prefix characters.
- static const String preFragments = 'a_pre_fragments';
- static const String finalizedFragments = 'b_finalized_fragments';
- static const String steps = 'c_steps';
-}
-
-class OutputUnitDataComputer extends DataComputer<Features> {
- const OutputUnitDataComputer();
-
- /// OutputData for [member] as a kernel based element.
- ///
- /// At this point the compiler has already been run, so it is holding the
- /// relevant OutputUnits, we just need to extract that information from it. We
- /// fill [actualMap] with the data computed about what the resulting OutputUnit
- /// is.
- @override
- void computeMemberData(Compiler compiler, MemberEntity member,
- Map<Id, ActualData<Features>> actualMap,
- {bool verbose: false}) {
- JsClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
- JsToElementMap elementMap = closedWorld.elementMap;
- MemberDefinition definition = elementMap.getMemberDefinition(member);
- OutputUnitIrComputer(compiler.reporter, actualMap, elementMap,
- closedWorld.outputUnitData, closedWorld.closureDataLookup)
- .run(definition.node);
- }
-
- @override
- void computeClassData(Compiler compiler, ClassEntity cls,
- Map<Id, ActualData<Features>> actualMap,
- {bool verbose: false}) {
- JsClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
- JsToElementMap elementMap = closedWorld.elementMap;
- ClassDefinition definition = elementMap.getClassDefinition(cls);
- OutputUnitIrComputer(compiler.reporter, actualMap, elementMap,
- closedWorld.outputUnitData, closedWorld.closureDataLookup)
- .computeForClass(definition.node);
- }
-
- @override
- void computeLibraryData(Compiler compiler, LibraryEntity library,
- Map<Id, ActualData<Features>> actualMap,
- {bool verbose}) {
- KernelFrontendStrategy frontendStrategy = compiler.frontendStrategy;
- ir.Library node = frontendStrategy.elementMap.getLibraryNode(library);
- List<PreFragment> preDeferredFragments = compiler
- .backendStrategy.emitterTask.emitter.preDeferredFragmentsForTesting;
- Map<String, List<FinalizedFragment>> fragmentsToLoad =
- compiler.backendStrategy.emitterTask.emitter.finalizedFragmentsToLoad;
- Set<OutputUnit> omittedOutputUnits =
- compiler.backendStrategy.emitterTask.emitter.omittedOutputUnits;
- PreFragmentsIrComputer(compiler.reporter, actualMap, preDeferredFragments,
- fragmentsToLoad, omittedOutputUnits)
- .computeForLibrary(node);
- }
-
- @override
- DataInterpreter<Features> get dataValidator =>
- const FeaturesDataInterpreter();
-}
-
-class PreFragmentsIrComputer extends IrDataExtractor<Features> {
- final List<PreFragment> _preDeferredFragments;
- final Map<String, List<FinalizedFragment>> _fragmentsToLoad;
- final Set<OutputUnit> _omittedOutputUnits;
-
- PreFragmentsIrComputer(
- DiagnosticReporter reporter,
- Map<Id, ActualData<Features>> actualMap,
- this._preDeferredFragments,
- this._fragmentsToLoad,
- this._omittedOutputUnits)
- : super(reporter, actualMap);
-
- @override
- Features computeLibraryValue(Id id, ir.Library library) {
- var name = '${library.importUri.pathSegments.last}';
- Features features = new Features();
- if (!name.startsWith('main')) return features;
-
- // First build a list of pre fragments and their dependencies.
- int index = 1;
- Map<FinalizedFragment, int> finalizedFragmentIndices = {};
- Map<PreFragment, int> preFragmentIndices = {};
- Map<int, PreFragment> reversePreFragmentIndices = {};
- Map<int, FinalizedFragment> reverseFinalizedFragmentIndices = {};
- for (var preFragment in _preDeferredFragments) {
- if (!preFragmentIndices.containsKey(preFragment)) {
- var finalizedFragment = preFragment.finalizedFragment;
- preFragmentIndices[preFragment] = index;
- finalizedFragmentIndices[finalizedFragment] = index;
- reversePreFragmentIndices[index] = preFragment;
- reverseFinalizedFragmentIndices[index] = finalizedFragment;
- index++;
- }
- }
-
- for (int i = 1; i < index; i++) {
- var preFragment = reversePreFragmentIndices[i];
- List<String> needs = [];
- List<OutputUnit> supplied = [];
- List<String> usedBy = [];
- for (var dependent in preFragment.successors) {
- if (preFragmentIndices.containsKey(dependent)) {
- usedBy.add('p${preFragmentIndices[dependent]}');
- }
- }
-
- for (var dependency in preFragment.predecessors) {
- if (preFragmentIndices.containsKey(dependency)) {
- needs.add('p${preFragmentIndices[dependency]}');
- }
- }
-
- for (var emittedOutputUnit in preFragment.emittedOutputUnits) {
- supplied.add(emittedOutputUnit.outputUnit);
- }
-
- var suppliedString = '[${supplied.map(outputUnitString).join(', ')}]';
- features.addElement(Tags.preFragments,
- 'p$i: {units: $suppliedString, usedBy: $usedBy, needs: $needs}');
- }
-
- // Now dump finalized fragments and load ids.
- for (int i = 1; i < index; i++) {
- var finalizedFragment = reverseFinalizedFragmentIndices[i];
- List<String> supplied = [];
-
- for (var codeFragment in finalizedFragment.codeFragments) {
- List<String> outputUnitStrings = [];
- for (var outputUnit in codeFragment.outputUnits) {
- if (!_omittedOutputUnits.contains(outputUnit)) {
- outputUnitStrings.add(outputUnitString(outputUnit));
- }
- }
- if (outputUnitStrings.isNotEmpty) {
- supplied.add(outputUnitStrings.join('+'));
- }
- }
-
- if (supplied.isNotEmpty) {
- var suppliedString = '[${supplied.join(', ')}]';
- features.addElement(Tags.finalizedFragments, 'f$i: $suppliedString');
- }
- }
-
- _fragmentsToLoad.forEach((loadId, finalizedFragments) {
- List<String> finalizedFragmentNeeds = [];
- for (var finalizedFragment in finalizedFragments) {
- assert(finalizedFragmentIndices.containsKey(finalizedFragment));
- finalizedFragmentNeeds
- .add('f${finalizedFragmentIndices[finalizedFragment]}');
- }
- features.addElement(
- Tags.steps, '$loadId=(${finalizedFragmentNeeds.join(', ')})');
- });
-
- return features;
- }
-}
-
-class OutputUnitIrComputer extends IrDataExtractor<Features> {
- final JsToElementMap _elementMap;
- final OutputUnitData _data;
- final ClosureData _closureDataLookup;
-
- Set<String> _constants = {};
-
- OutputUnitIrComputer(
- DiagnosticReporter reporter,
- Map<Id, ActualData<Features>> actualMap,
- this._elementMap,
- this._data,
- this._closureDataLookup)
- : super(reporter, actualMap);
-
- Features getMemberValue(
- String tag, MemberEntity member, Set<String> constants) {
- Features features = Features();
- features.add(tag,
- value: outputUnitString(_data.outputUnitForMemberForTesting(member)));
- for (var constant in constants) {
- features.addElement(Tags.constants, constant);
- }
- return features;
- }
-
- @override
- Features computeClassValue(Id id, ir.Class node) {
- var cls = _elementMap.getClass(node);
- Features features = Features();
- features.add(Tags.cls,
- value: outputUnitString(_data.outputUnitForClassForTesting(cls)));
- features.add(Tags.type,
- value: outputUnitString(_data.outputUnitForClassTypeForTesting(cls)));
- return features;
- }
-
- @override
- Features computeMemberValue(Id id, ir.Member node) {
- if (node is ir.Field && node.isConst) {
- ir.Expression initializer = node.initializer;
- ConstantValue constant = _elementMap.getConstantValue(node, initializer);
- if (!constant.isPrimitive) {
- SourceSpan span = computeSourceSpanFromTreeNode(initializer);
- if (initializer is ir.ConstructorInvocation) {
- // Adjust the source-span to match the AST-based location. The kernel FE
- // skips the "const" keyword for the expression offset and any prefix in
- // front of the constructor. The "-6" is an approximation assuming that
- // there is just a single space after "const" and no prefix.
- // TODO(sigmund): offsets should be fixed in the FE instead.
- span = SourceSpan(span.uri, span.begin - 6, span.end - 6);
- }
- _registerValue(
- NodeId(span.begin, IdKind.node),
- Features.fromMap({
- Tags.member: outputUnitString(
- _data.outputUnitForConstantForTesting(constant))
- }),
- node,
- span,
- actualMap,
- reporter);
- }
- }
-
- Features features =
- getMemberValue(Tags.member, _elementMap.getMember(node), _constants);
- _constants = {};
- return features;
- }
-
- @override
- visitConstantExpression(ir.ConstantExpression node) {
- ConstantValue constant = _elementMap.getConstantValue(null, node);
- if (!constant.isPrimitive) {
- _constants.add('${constant.toStructuredText(_elementMap.types)}='
- '${outputUnitString(_data.outputUnitForConstant(constant))}');
- }
- return super.visitConstantExpression(node);
- }
-
- @override
- Features computeNodeValue(Id id, ir.TreeNode node) {
- if (node is ir.FunctionExpression || node is ir.FunctionDeclaration) {
- ClosureRepresentationInfo info = _closureDataLookup.getClosureInfo(node);
- return getMemberValue(Tags.closure, info.callMethod, const {});
- }
- return null;
- }
-}
-
-/// Set [actualMap] to hold a key of [id] with the computed data [value]
-/// corresponding to [object] at location [sourceSpan]. We also perform error
-/// checking to ensure that the same [id] isn't added twice.
-void _registerValue<T>(Id id, T value, Object object, SourceSpan sourceSpan,
- Map<Id, ActualData<T>> actualMap, CompilerDiagnosticReporter reporter) {
- if (actualMap.containsKey(id)) {
- ActualData<T> existingData = actualMap[id];
- reportHere(reporter, sourceSpan,
- "Duplicate id ${id}, value=$value, object=$object");
- reportHere(
- reporter,
- sourceSpan,
- "Duplicate id ${id}, value=${existingData.value}, "
- "object=${existingData.object}");
- Expect.fail("Duplicate id $id.");
- }
- if (value != null) {
- actualMap[id] =
- ActualData<T>(id, value, sourceSpan.uri, sourceSpan.begin, object);
- }
-}
diff --git a/pkg/compiler/test/deferred_loading/deferred_loading_test_helper.dart b/pkg/compiler/test/deferred_loading/deferred_loading_test_helper.dart
new file mode 100644
index 0000000..73271f9
--- /dev/null
+++ b/pkg/compiler/test/deferred_loading/deferred_loading_test_helper.dart
@@ -0,0 +1,360 @@
+// 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.
+
+// @dart = 2.7
+
+import 'package:_fe_analyzer_shared/src/testing/features.dart';
+import 'package:compiler/src/closure.dart';
+import 'package:compiler/src/common.dart';
+import 'package:compiler/src/compiler.dart';
+import 'package:compiler/src/deferred_load/deferred_load.dart';
+import 'package:compiler/src/elements/entities.dart';
+import 'package:compiler/src/ir/util.dart';
+import 'package:compiler/src/js_model/element_map.dart';
+import 'package:compiler/src/js_model/js_world.dart';
+import 'package:compiler/src/js_emitter/startup_emitter/fragment_merger.dart';
+import 'package:compiler/src/kernel/kernel_strategy.dart';
+import 'package:expect/expect.dart';
+import '../equivalence/id_equivalence.dart';
+import '../equivalence/id_equivalence_helper.dart';
+import 'package:compiler/src/constants/values.dart';
+
+import 'package:kernel/ast.dart' as ir;
+
+// For ease of testing and making our tests easier to read, we impose an
+// artificial constraint of requiring every deferred import use a different
+// named prefix per test. We enforce this constraint here by checking that no
+// prefix name responds to two different libraries.
+Map<String, Uri> importPrefixes = {};
+
+String importPrefixString(OutputUnit unit) {
+ List<String> importNames = [];
+ for (ImportEntity import in unit.imports) {
+ importNames.add(import.name);
+ Expect.isTrue(import.isDeferred);
+
+ if (importPrefixes.containsKey(import.name)) {
+ var existing = importPrefixes[import.name];
+ var current = import.enclosingLibraryUri;
+ Expect.equals(
+ existing,
+ current,
+ '\n Duplicate prefix \'${import.name}\' used in both:\n'
+ ' - $existing and\n'
+ ' - $current.\n'
+ ' We require using unique prefixes on these tests to make '
+ 'the expectations more readable.');
+ }
+ importPrefixes[import.name] = import.enclosingLibraryUri;
+ }
+ importNames.sort();
+ return importNames.join(', ');
+}
+
+/// Create a consistent string representation of [OutputUnit]s for both
+/// KImportEntities and ImportElements.
+String outputUnitString(OutputUnit unit) {
+ if (unit == null) return 'none';
+ String sb = importPrefixString(unit);
+ return '${unit.name}{$sb}';
+}
+
+Map<String, List<PreFragment>> buildPreFragmentMap(
+ Map<String, List<FinalizedFragment>> fragmentsToLoad,
+ List<PreFragment> preDeferredFragments) {
+ Map<FinalizedFragment, PreFragment> fragmentMap = {};
+ for (var preFragment in preDeferredFragments) {
+ fragmentMap[preFragment.finalizedFragment] = preFragment;
+ }
+ Map<String, List<PreFragment>> preFragmentMap = {};
+ fragmentsToLoad.forEach((loadId, fragments) {
+ List<PreFragment> preFragments = [];
+ for (var fragment in fragments) {
+ preFragments.add(fragmentMap[fragment]);
+ }
+ preFragmentMap[loadId] = preFragments.toList();
+ });
+ return preFragmentMap;
+}
+
+class Tags {
+ static const String cls = 'class_unit';
+ static const String member = 'member_unit';
+ static const String closure = 'closure_unit';
+ static const String constants = 'constants';
+ static const String type = 'type_unit';
+ // The below tags appear in a single block comment in the main file.
+ // To keep them appearing in sequential order we prefix characters.
+ static const String preFragments = 'a_pre_fragments';
+ static const String finalizedFragments = 'b_finalized_fragments';
+ static const String steps = 'c_steps';
+}
+
+class OutputUnitDataComputer extends DataComputer<Features> {
+ const OutputUnitDataComputer();
+
+ /// OutputData for [member] as a kernel based element.
+ ///
+ /// At this point the compiler has already been run, so it is holding the
+ /// relevant OutputUnits, we just need to extract that information from it. We
+ /// fill [actualMap] with the data computed about what the resulting OutputUnit
+ /// is.
+ @override
+ void computeMemberData(Compiler compiler, MemberEntity member,
+ Map<Id, ActualData<Features>> actualMap,
+ {bool verbose: false}) {
+ JsClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
+ JsToElementMap elementMap = closedWorld.elementMap;
+ MemberDefinition definition = elementMap.getMemberDefinition(member);
+ OutputUnitIrComputer(compiler.reporter, actualMap, elementMap,
+ closedWorld.outputUnitData, closedWorld.closureDataLookup)
+ .run(definition.node);
+ }
+
+ @override
+ void computeClassData(Compiler compiler, ClassEntity cls,
+ Map<Id, ActualData<Features>> actualMap,
+ {bool verbose: false}) {
+ JsClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
+ JsToElementMap elementMap = closedWorld.elementMap;
+ ClassDefinition definition = elementMap.getClassDefinition(cls);
+ OutputUnitIrComputer(compiler.reporter, actualMap, elementMap,
+ closedWorld.outputUnitData, closedWorld.closureDataLookup)
+ .computeForClass(definition.node);
+ }
+
+ @override
+ void computeLibraryData(Compiler compiler, LibraryEntity library,
+ Map<Id, ActualData<Features>> actualMap,
+ {bool verbose}) {
+ KernelFrontendStrategy frontendStrategy = compiler.frontendStrategy;
+ ir.Library node = frontendStrategy.elementMap.getLibraryNode(library);
+ List<PreFragment> preDeferredFragments = compiler
+ .backendStrategy.emitterTask.emitter.preDeferredFragmentsForTesting;
+ Map<String, List<FinalizedFragment>> fragmentsToLoad =
+ compiler.backendStrategy.emitterTask.emitter.finalizedFragmentsToLoad;
+ Set<OutputUnit> omittedOutputUnits =
+ compiler.backendStrategy.emitterTask.emitter.omittedOutputUnits;
+ PreFragmentsIrComputer(compiler.reporter, actualMap, preDeferredFragments,
+ fragmentsToLoad, omittedOutputUnits)
+ .computeForLibrary(node);
+ }
+
+ @override
+ DataInterpreter<Features> get dataValidator =>
+ const FeaturesDataInterpreter();
+}
+
+class PreFragmentsIrComputer extends IrDataExtractor<Features> {
+ final List<PreFragment> _preDeferredFragments;
+ final Map<String, List<FinalizedFragment>> _fragmentsToLoad;
+ final Set<OutputUnit> _omittedOutputUnits;
+
+ PreFragmentsIrComputer(
+ DiagnosticReporter reporter,
+ Map<Id, ActualData<Features>> actualMap,
+ this._preDeferredFragments,
+ this._fragmentsToLoad,
+ this._omittedOutputUnits)
+ : super(reporter, actualMap);
+
+ @override
+ Features computeLibraryValue(Id id, ir.Library library) {
+ var name = '${library.importUri.pathSegments.last}';
+ Features features = new Features();
+ if (!name.startsWith('main')) return features;
+
+ // First build a list of pre fragments and their dependencies.
+ int index = 1;
+ Map<FinalizedFragment, int> finalizedFragmentIndices = {};
+ Map<PreFragment, int> preFragmentIndices = {};
+ Map<int, PreFragment> reversePreFragmentIndices = {};
+ Map<int, FinalizedFragment> reverseFinalizedFragmentIndices = {};
+ for (var preFragment in _preDeferredFragments) {
+ if (!preFragmentIndices.containsKey(preFragment)) {
+ var finalizedFragment = preFragment.finalizedFragment;
+ preFragmentIndices[preFragment] = index;
+ finalizedFragmentIndices[finalizedFragment] = index;
+ reversePreFragmentIndices[index] = preFragment;
+ reverseFinalizedFragmentIndices[index] = finalizedFragment;
+ index++;
+ }
+ }
+
+ for (int i = 1; i < index; i++) {
+ var preFragment = reversePreFragmentIndices[i];
+ List<String> needs = [];
+ List<OutputUnit> supplied = [];
+ List<String> usedBy = [];
+ for (var dependent in preFragment.successors) {
+ if (preFragmentIndices.containsKey(dependent)) {
+ usedBy.add('p${preFragmentIndices[dependent]}');
+ }
+ }
+
+ for (var dependency in preFragment.predecessors) {
+ if (preFragmentIndices.containsKey(dependency)) {
+ needs.add('p${preFragmentIndices[dependency]}');
+ }
+ }
+
+ for (var emittedOutputUnit in preFragment.emittedOutputUnits) {
+ supplied.add(emittedOutputUnit.outputUnit);
+ }
+
+ var suppliedString = '[${supplied.map(outputUnitString).join(', ')}]';
+ features.addElement(Tags.preFragments,
+ 'p$i: {units: $suppliedString, usedBy: $usedBy, needs: $needs}');
+ }
+
+ // Now dump finalized fragments and load ids.
+ for (int i = 1; i < index; i++) {
+ var finalizedFragment = reverseFinalizedFragmentIndices[i];
+ List<String> supplied = [];
+
+ for (var codeFragment in finalizedFragment.codeFragments) {
+ List<String> outputUnitStrings = [];
+ for (var outputUnit in codeFragment.outputUnits) {
+ if (!_omittedOutputUnits.contains(outputUnit)) {
+ outputUnitStrings.add(outputUnitString(outputUnit));
+ }
+ }
+ if (outputUnitStrings.isNotEmpty) {
+ supplied.add(outputUnitStrings.join('+'));
+ }
+ }
+
+ if (supplied.isNotEmpty) {
+ var suppliedString = '[${supplied.join(', ')}]';
+ features.addElement(Tags.finalizedFragments, 'f$i: $suppliedString');
+ }
+ }
+
+ _fragmentsToLoad.forEach((loadId, finalizedFragments) {
+ List<String> finalizedFragmentNeeds = [];
+ for (var finalizedFragment in finalizedFragments) {
+ assert(finalizedFragmentIndices.containsKey(finalizedFragment));
+ finalizedFragmentNeeds
+ .add('f${finalizedFragmentIndices[finalizedFragment]}');
+ }
+ features.addElement(
+ Tags.steps, '$loadId=(${finalizedFragmentNeeds.join(', ')})');
+ });
+
+ return features;
+ }
+}
+
+class OutputUnitIrComputer extends IrDataExtractor<Features> {
+ final JsToElementMap _elementMap;
+ final OutputUnitData _data;
+ final ClosureData _closureDataLookup;
+
+ Set<String> _constants = {};
+
+ OutputUnitIrComputer(
+ DiagnosticReporter reporter,
+ Map<Id, ActualData<Features>> actualMap,
+ this._elementMap,
+ this._data,
+ this._closureDataLookup)
+ : super(reporter, actualMap);
+
+ Features getMemberValue(
+ String tag, MemberEntity member, Set<String> constants) {
+ Features features = Features();
+ features.add(tag,
+ value: outputUnitString(_data.outputUnitForMemberForTesting(member)));
+ for (var constant in constants) {
+ features.addElement(Tags.constants, constant);
+ }
+ return features;
+ }
+
+ @override
+ Features computeClassValue(Id id, ir.Class node) {
+ var cls = _elementMap.getClass(node);
+ Features features = Features();
+ features.add(Tags.cls,
+ value: outputUnitString(_data.outputUnitForClassForTesting(cls)));
+ features.add(Tags.type,
+ value: outputUnitString(_data.outputUnitForClassTypeForTesting(cls)));
+ return features;
+ }
+
+ @override
+ Features computeMemberValue(Id id, ir.Member node) {
+ if (node is ir.Field && node.isConst) {
+ ir.Expression initializer = node.initializer;
+ ConstantValue constant = _elementMap.getConstantValue(node, initializer);
+ if (!constant.isPrimitive) {
+ SourceSpan span = computeSourceSpanFromTreeNode(initializer);
+ if (initializer is ir.ConstructorInvocation) {
+ // Adjust the source-span to match the AST-based location. The kernel FE
+ // skips the "const" keyword for the expression offset and any prefix in
+ // front of the constructor. The "-6" is an approximation assuming that
+ // there is just a single space after "const" and no prefix.
+ // TODO(sigmund): offsets should be fixed in the FE instead.
+ span = SourceSpan(span.uri, span.begin - 6, span.end - 6);
+ }
+ _registerValue(
+ NodeId(span.begin, IdKind.node),
+ Features.fromMap({
+ Tags.member: outputUnitString(
+ _data.outputUnitForConstantForTesting(constant))
+ }),
+ node,
+ span,
+ actualMap,
+ reporter);
+ }
+ }
+
+ Features features =
+ getMemberValue(Tags.member, _elementMap.getMember(node), _constants);
+ _constants = {};
+ return features;
+ }
+
+ @override
+ visitConstantExpression(ir.ConstantExpression node) {
+ ConstantValue constant = _elementMap.getConstantValue(null, node);
+ if (!constant.isPrimitive) {
+ _constants.add('${constant.toStructuredText(_elementMap.types)}='
+ '${outputUnitString(_data.outputUnitForConstant(constant))}');
+ }
+ return super.visitConstantExpression(node);
+ }
+
+ @override
+ Features computeNodeValue(Id id, ir.TreeNode node) {
+ if (node is ir.FunctionExpression || node is ir.FunctionDeclaration) {
+ ClosureRepresentationInfo info = _closureDataLookup.getClosureInfo(node);
+ return getMemberValue(Tags.closure, info.callMethod, const {});
+ }
+ return null;
+ }
+}
+
+/// Set [actualMap] to hold a key of [id] with the computed data [value]
+/// corresponding to [object] at location [sourceSpan]. We also perform error
+/// checking to ensure that the same [id] isn't added twice.
+void _registerValue<T>(Id id, T value, Object object, SourceSpan sourceSpan,
+ Map<Id, ActualData<T>> actualMap, CompilerDiagnosticReporter reporter) {
+ if (actualMap.containsKey(id)) {
+ ActualData<T> existingData = actualMap[id];
+ reportHere(reporter, sourceSpan,
+ "Duplicate id ${id}, value=$value, object=$object");
+ reportHere(
+ reporter,
+ sourceSpan,
+ "Duplicate id ${id}, value=${existingData.value}, "
+ "object=${existingData.object}");
+ Expect.fail("Duplicate id $id.");
+ }
+ if (value != null) {
+ actualMap[id] =
+ ActualData<T>(id, value, sourceSpan.uri, sourceSpan.begin, object);
+ }
+}
diff --git a/pkg/compiler/test/end_to_end/diagnostic_reporter_helper.dart b/pkg/compiler/test/end_to_end/diagnostic_reporter_helper.dart
index 0058660..ba061e2 100644
--- a/pkg/compiler/test/end_to_end/diagnostic_reporter_helper.dart
+++ b/pkg/compiler/test/end_to_end/diagnostic_reporter_helper.dart
@@ -56,6 +56,7 @@
@override
void reportInfoMessage(Spannable node, MessageKind errorCode,
[Map<String, String> arguments = const {}]) {
+ // ignore: deprecated_member_use_from_same_package
reporter.reportInfoMessage(node, errorCode, arguments);
}
diff --git a/pkg/compiler/test/end_to_end/feature_options_test.dart b/pkg/compiler/test/end_to_end/feature_options_test.dart
index 3481941..d4f3908 100644
--- a/pkg/compiler/test/end_to_end/feature_options_test.dart
+++ b/pkg/compiler/test/end_to_end/feature_options_test.dart
@@ -128,7 +128,26 @@
Expect.throwsArgumentError(() => test(['--cf1', '--no-cf1']));
}
+void flavorStringTest(List<String> options, String expectedFlavorString) {
+ var tfo = test(options);
+ Expect.equals(expectedFlavorString, tfo.flavorString());
+}
+
+void flavorStringTests() {
+ flavorStringTest([], 'sf1, sf2, no-sf3, no-sf4');
+ flavorStringTest(['--no-sf1', '--no-sf2', '--sf3', '--sf4'], '');
+ flavorStringTest(['--no-sf1', '--no-sf2', '--sf3'], 'no-sf4');
+ flavorStringTest(['--no-sf1', '--sf3', '--sf4'], 'sf2');
+ flavorStringTest(['--no-sf1', '--no-sf2', '--sf3', '--sf4', '--cf1'], 'cf1');
+ flavorStringTest(['--cf1'], 'sf1, sf2, no-sf3, no-sf4, cf1');
+ flavorStringTest(['--no-sf1', '--no-sf2', '--sf3', '--sf4', '--no-cf3'], 'no-cf3');
+ flavorStringTest(['--no-cf3'], 'sf1, sf2, no-sf3, no-sf4, no-cf3');
+ flavorStringTest(['--no-sf1', '--no-sf2', '--sf3', '--sf4', '--cf1',
+ '--no-cf3'], 'cf1, no-cf3');
+}
+
void main() {
+ // Test feature options functionality.
testShipping();
testNoShipping();
testCanary();
@@ -138,4 +157,7 @@
testNoCanaryEnabled();
testNoShippingEnabled();
testFlagCollision();
+
+ // Supplemental tests.
+ flavorStringTests();
}
diff --git a/pkg/compiler/test/end_to_end/library_env_test.dart b/pkg/compiler/test/end_to_end/library_env_test.dart
index ac96c89..f194f37 100644
--- a/pkg/compiler/test/end_to_end/library_env_test.dart
+++ b/pkg/compiler/test/end_to_end/library_env_test.dart
@@ -85,48 +85,57 @@
}
runTest() async {
- var compiler = new CustomCompiler([], {});
+ {
+ final compiler = new CustomCompiler([], {});
- await compiler.setupSdk();
+ await compiler.setupSdk();
+ final lookup = compiler.environment.valueOf;
- // Core libraries are always present.
- Expect.equals("true", compiler.fromEnvironment("dart.library.collection"));
- // Non-existing entries in the environment return 'null'.
- Expect.isNull(compiler.fromEnvironment("not in env"));
- // Check for client libraries (default if there are no flags to the compiler).
- Expect.equals("true", compiler.fromEnvironment("dart.library.mock.client"));
- Expect.equals("true", compiler.fromEnvironment("dart.library.html"));
- // Check for shared libraries..
- Expect.equals("true", compiler.fromEnvironment("dart.library.mock.shared"));
- // Check server libraries are not present.
- Expect.equals(null, compiler.fromEnvironment("dart.library.mock.server"));
- Expect.equals(null, compiler.fromEnvironment("dart.library.io"));
+ // Core libraries are always present.
+ Expect.equals("true", lookup("dart.library.collection"));
+ // Non-existing entries in the environment return 'null'.
+ Expect.isNull(lookup("not in env"));
+ // Check for client libraries (default if there are no flags to the compiler).
+ Expect.equals("true", lookup("dart.library.mock.client"));
+ Expect.equals("true", lookup("dart.library.html"));
+ // Check for shared libraries..
+ Expect.equals("true", lookup("dart.library.mock.shared"));
+ // Check server libraries are not present.
+ Expect.equals(null, lookup("dart.library.mock.server"));
+ Expect.equals(null, lookup("dart.library.io"));
+ }
+ {
+ final compiler = new CustomCompiler([Flags.serverMode], {});
- compiler = new CustomCompiler([Flags.serverMode], {});
+ await compiler.setupSdk();
+ final lookup = compiler.environment.valueOf;
- await compiler.setupSdk();
+ // Core libraries are always present.
+ Expect.equals("true", lookup("dart.library.collection"));
+ // Non-existing entries in the environment return 'null'.
+ Expect.isNull(lookup("not in env"));
+ // Check client libraries are not present.
+ Expect.equals(null, lookup("dart.library.mock.client"));
+ Expect.equals(null, lookup("dart.library.html"));
+ // Check for shared libraries..
+ Expect.equals("true", lookup("dart.library.mock.shared"));
+ // Check for server libraries.
+ Expect.equals("true", lookup("dart.library.mock.server"));
+ Expect.equals("true", lookup("dart.library.io"));
+ }
+ {
+ // Check that user-defined env-variables win.
+ final compiler = new CustomCompiler([], {
+ 'dart.library.collection': "false",
+ 'dart.library.mock.client': "foo"
+ });
- // Core libraries are always present.
- Expect.equals("true", compiler.fromEnvironment("dart.library.collection"));
- // Non-existing entries in the environment return 'null'.
- Expect.isNull(compiler.fromEnvironment("not in env"));
- // Check client libraries are not present.
- Expect.equals(null, compiler.fromEnvironment("dart.library.mock.client"));
- Expect.equals(null, compiler.fromEnvironment("dart.library.html"));
- // Check for shared libraries..
- Expect.equals("true", compiler.fromEnvironment("dart.library.mock.shared"));
- // Check for server libraries.
- Expect.equals("true", compiler.fromEnvironment("dart.library.mock.server"));
- Expect.equals("true", compiler.fromEnvironment("dart.library.io"));
+ await compiler.setupSdk();
+ final lookup = compiler.environment.valueOf;
- // Check that user-defined env-variables win.
- compiler = new CustomCompiler([],
- {'dart.library.collection': "false", 'dart.library.mock.client': "foo"});
-
- await compiler.setupSdk();
-
- Expect.equals("false", compiler.fromEnvironment("dart.library.collection"));
- Expect.equals("foo", compiler.fromEnvironment("dart.library.mock.client"));
+ Expect.equals("false", lookup("dart.library.collection"));
+ Expect.equals("foo", lookup("dart.library.mock.client"));
+ }
}
main() {
diff --git a/pkg/compiler/test/equivalence/id_equivalence.dart b/pkg/compiler/test/equivalence/id_equivalence.dart
index 31ece9d..879d6b9 100644
--- a/pkg/compiler/test/equivalence/id_equivalence.dart
+++ b/pkg/compiler/test/equivalence/id_equivalence.dart
@@ -17,7 +17,7 @@
SourceSpan computeSourceSpanFromUriOffset(Uri uri, int offset) {
if (uri != null) {
- if (offset != null) {
+ if (offset != null && offset != -1) {
return new SourceSpan(uri, offset, offset + 1);
} else {
return new SourceSpan(uri, 0, 0);
diff --git a/pkg/compiler/test/helpers/program_lookup.dart b/pkg/compiler/test/helpers/program_lookup.dart
index 1c98822..c6f3393 100644
--- a/pkg/compiler/test/helpers/program_lookup.dart
+++ b/pkg/compiler/test/helpers/program_lookup.dart
@@ -6,7 +6,7 @@
import 'package:expect/expect.dart';
import 'package:compiler/src/common_elements.dart';
-import 'package:compiler/src/deferred_load.dart';
+import 'package:compiler/src/deferred_load/deferred_load.dart';
import 'package:compiler/src/elements/entities.dart';
import 'package:compiler/src/js_backend/namer.dart';
import 'package:compiler/src/js_emitter/model.dart';
diff --git a/pkg/compiler/test/impact/data/constants/main.dart b/pkg/compiler/test/impact/data/constants/main.dart
index a29bd63..be9a623 100644
--- a/pkg/compiler/test/impact/data/constants/main.dart
+++ b/pkg/compiler/test/impact/data/constants/main.dart
@@ -108,13 +108,27 @@
inst:List<bool*>]*/
listLiteral() => const [true, false];
-/*member: mapLiteral:type=[inst:ConstantMap<dynamic,dynamic>,inst:ConstantProtoMap<dynamic,dynamic>,inst:ConstantStringMap<dynamic,dynamic>,inst:GeneralConstantMap<dynamic,dynamic>,inst:JSBool]*/
+/*member: mapLiteral:type=[
+ inst:ConstantMap<dynamic,dynamic>,
+ inst:ConstantStringMap<dynamic,dynamic>,
+ inst:GeneralConstantMap<dynamic,dynamic>,
+ inst:JSBool]*/
mapLiteral() => const {true: false};
-/*member: stringMapLiteral:type=[inst:ConstantMap<dynamic,dynamic>,inst:ConstantProtoMap<dynamic,dynamic>,inst:ConstantStringMap<dynamic,dynamic>,inst:GeneralConstantMap<dynamic,dynamic>,inst:JSBool,inst:JSString]*/
+/*member: stringMapLiteral:type=[
+ inst:ConstantMap<dynamic,dynamic>,
+ inst:ConstantStringMap<dynamic,dynamic>,
+ inst:GeneralConstantMap<dynamic,dynamic>,
+ inst:JSBool,
+ inst:JSString]*/
stringMapLiteral() => const {'foo': false};
-/*member: setLiteral:type=[inst:ConstantMap<dynamic,dynamic>,inst:ConstantProtoMap<dynamic,dynamic>,inst:ConstantStringMap<dynamic,dynamic>,inst:GeneralConstantMap<dynamic,dynamic>,inst:JSBool,inst:_UnmodifiableSet<dynamic>]*/
+/*member: setLiteral:type=[
+ inst:ConstantMap<dynamic,dynamic>,
+ inst:ConstantStringMap<dynamic,dynamic>,
+ inst:GeneralConstantMap<dynamic,dynamic>,
+ inst:JSBool,
+ inst:_UnmodifiableSet<dynamic>]*/
setLiteral() => const {true, false};
/*member: instanceConstant:
@@ -190,13 +204,27 @@
inst:List<bool*>]*/
listLiteralRef() => listLiteralField;
-/*member: mapLiteralRef:type=[inst:ConstantMap<dynamic,dynamic>,inst:ConstantProtoMap<dynamic,dynamic>,inst:ConstantStringMap<dynamic,dynamic>,inst:GeneralConstantMap<dynamic,dynamic>,inst:JSBool]*/
+/*member: mapLiteralRef:type=[
+ inst:ConstantMap<dynamic,dynamic>,
+ inst:ConstantStringMap<dynamic,dynamic>,
+ inst:GeneralConstantMap<dynamic,dynamic>,
+ inst:JSBool]*/
mapLiteralRef() => mapLiteralField;
-/*member: stringMapLiteralRef:type=[inst:ConstantMap<dynamic,dynamic>,inst:ConstantProtoMap<dynamic,dynamic>,inst:ConstantStringMap<dynamic,dynamic>,inst:GeneralConstantMap<dynamic,dynamic>,inst:JSBool,inst:JSString]*/
+/*member: stringMapLiteralRef:type=[
+ inst:ConstantMap<dynamic,dynamic>,
+ inst:ConstantStringMap<dynamic,dynamic>,
+ inst:GeneralConstantMap<dynamic,dynamic>,
+ inst:JSBool,
+ inst:JSString]*/
stringMapLiteralRef() => stringMapLiteralField;
-/*member: setLiteralRef:type=[inst:ConstantMap<dynamic,dynamic>,inst:ConstantProtoMap<dynamic,dynamic>,inst:ConstantStringMap<dynamic,dynamic>,inst:GeneralConstantMap<dynamic,dynamic>,inst:JSBool,inst:_UnmodifiableSet<dynamic>]*/
+/*member: setLiteralRef:type=[
+ inst:ConstantMap<dynamic,dynamic>,
+ inst:ConstantStringMap<dynamic,dynamic>,
+ inst:GeneralConstantMap<dynamic,dynamic>,
+ inst:JSBool,
+ inst:_UnmodifiableSet<dynamic>]*/
setLiteralRef() => setLiteralField;
/*member: instanceConstantRef:
@@ -263,15 +291,29 @@
listLiteralDeferred() => defer.listLiteralField;
// TODO(johnniwinther): Should we record that this is deferred?
-/*member: mapLiteralDeferred:type=[inst:ConstantMap<dynamic,dynamic>,inst:ConstantProtoMap<dynamic,dynamic>,inst:ConstantStringMap<dynamic,dynamic>,inst:GeneralConstantMap<dynamic,dynamic>,inst:JSBool]*/
+/*member: mapLiteralDeferred:type=[
+ inst:ConstantMap<dynamic,dynamic>,
+ inst:ConstantStringMap<dynamic,dynamic>,
+ inst:GeneralConstantMap<dynamic,dynamic>,
+ inst:JSBool]*/
mapLiteralDeferred() => defer.mapLiteralField;
// TODO(johnniwinther): Should we record that this is deferred?
-/*member: stringMapLiteralDeferred:type=[inst:ConstantMap<dynamic,dynamic>,inst:ConstantProtoMap<dynamic,dynamic>,inst:ConstantStringMap<dynamic,dynamic>,inst:GeneralConstantMap<dynamic,dynamic>,inst:JSBool,inst:JSString]*/
+/*member: stringMapLiteralDeferred:type=[
+ inst:ConstantMap<dynamic,dynamic>,
+ inst:ConstantStringMap<dynamic,dynamic>,
+ inst:GeneralConstantMap<dynamic,dynamic>,
+ inst:JSBool,
+ inst:JSString]*/
stringMapLiteralDeferred() => defer.stringMapLiteralField;
// TODO(johnniwinther): Should we record that this is deferred?
-/*member: setLiteralDeferred:type=[inst:ConstantMap<dynamic,dynamic>,inst:ConstantProtoMap<dynamic,dynamic>,inst:ConstantStringMap<dynamic,dynamic>,inst:GeneralConstantMap<dynamic,dynamic>,inst:JSBool,inst:_UnmodifiableSet<dynamic>]*/
+/*member: setLiteralDeferred:type=[
+ inst:ConstantMap<dynamic,dynamic>,
+ inst:ConstantStringMap<dynamic,dynamic>,
+ inst:GeneralConstantMap<dynamic,dynamic>,
+ inst:JSBool,
+ inst:_UnmodifiableSet<dynamic>]*/
setLiteralDeferred() => defer.setLiteralField;
/*member: instanceConstantDeferred:
diff --git a/pkg/compiler/test/impact/data/literals.dart b/pkg/compiler/test/impact/data/literals.dart
index 05b7c0c..e0e3ba5 100644
--- a/pkg/compiler/test/impact/data/literals.dart
+++ b/pkg/compiler/test/impact/data/literals.dart
@@ -179,7 +179,6 @@
/*member: testEmptyMapLiteralConstant:
type=[
inst:ConstantMap<dynamic,dynamic>,
- inst:ConstantProtoMap<dynamic,dynamic>,
inst:ConstantStringMap<dynamic,dynamic>,
inst:GeneralConstantMap<dynamic,dynamic>]
*/
diff --git a/pkg/compiler/test/inference/inference_test_helper.dart b/pkg/compiler/test/inference/inference_test_helper.dart
index 33565b7..231a108 100644
--- a/pkg/compiler/test/inference/inference_test_helper.dart
+++ b/pkg/compiler/test/inference/inference_test_helper.dart
@@ -146,7 +146,7 @@
node is ir.FunctionDeclaration) {
ClosureRepresentationInfo info = _closureDataLookup.getClosureInfo(node);
return getMemberValue(info.callMethod);
- } else if (node is ir.MethodInvocation ||
+ } else if (
node is ir.InstanceInvocation ||
node is ir.InstanceGetterInvocation ||
node is ir.DynamicInvocation ||
@@ -154,13 +154,13 @@
node is ir.EqualsNull ||
node is ir.EqualsCall) {
return getTypeMaskValue(result.typeOfReceiver(node));
- } else if (node is ir.PropertyGet ||
+ } else if (
node is ir.InstanceGet ||
node is ir.DynamicGet ||
node is ir.InstanceTearOff ||
node is ir.FunctionTearOff) {
return getTypeMaskValue(result.typeOfReceiver(node));
- } else if (node is ir.PropertySet ||
+ } else if (
node is ir.InstanceSet ||
node is ir.DynamicSet) {
return getTypeMaskValue(result.typeOfReceiver(node));
diff --git a/pkg/compiler/test/rti/rti_need_test_helper.dart b/pkg/compiler/test/rti/rti_need_test_helper.dart
index 4206006..5b15bb6 100644
--- a/pkg/compiler/test/rti/rti_need_test_helper.dart
+++ b/pkg/compiler/test/rti/rti_need_test_helper.dart
@@ -187,14 +187,16 @@
}
/// Visitor that determines whether a type refers to [entity].
-class FindTypeVisitor extends BaseDartTypeVisitor<bool, Null> {
+class FindTypeVisitor extends DartTypeVisitor<bool, Null> {
final Entity entity;
FindTypeVisitor(this.entity);
- bool visitTypes(List<DartType> types) {
+ bool check(DartType type) => visit(type, null);
+
+ bool checkList(List<DartType> types) {
for (DartType type in types) {
- if (type.accept(this, null)) {
+ if (check(type)) {
return true;
}
}
@@ -202,39 +204,47 @@
}
@override
- bool visitType(DartType type, _) => false;
-
- @override
bool visitLegacyType(LegacyType type, _) => visit(type.baseType, _);
@override
bool visitNullableType(NullableType type, _) => visit(type.baseType, _);
@override
- bool visitInterfaceType(InterfaceType type, _) {
- if (type.element == entity) return true;
- return visitTypes(type.typeArguments);
- }
+ bool visitNeverType(NeverType type, _) => false;
@override
- bool visitFunctionType(FunctionType type, _) {
- if (type.returnType.accept(this, null)) return true;
- if (visitTypes(type.typeVariables)) return true;
- if (visitTypes(type.parameterTypes)) return true;
- if (visitTypes(type.optionalParameterTypes)) return true;
- if (visitTypes(type.namedParameterTypes)) return true;
- return false;
- }
+ bool visitVoidType(VoidType type, _) => false;
@override
- bool visitTypeVariableType(TypeVariableType type, _) {
- return type.element.typeDeclaration == entity;
- }
+ bool visitTypeVariableType(TypeVariableType type, _) =>
+ type.element.typeDeclaration == entity;
@override
- bool visitFutureOrType(FutureOrType type, _) {
- return type.typeArgument.accept(this, null);
- }
+ bool visitFunctionTypeVariable(FunctionTypeVariable type, _) => false;
+
+ @override
+ bool visitFunctionType(FunctionType type, _) =>
+ type.returnType.accept(this, null) ||
+ checkList(type.typeVariables) ||
+ checkList(type.parameterTypes) ||
+ checkList(type.optionalParameterTypes) ||
+ checkList(type.namedParameterTypes);
+
+ @override
+ bool visitInterfaceType(InterfaceType type, _) =>
+ type.element == entity || checkList(type.typeArguments);
+
+ @override
+ bool visitDynamicType(DynamicType type, _) => false;
+
+ @override
+ bool visitErasedType(ErasedType type, _) => false;
+
+ @override
+ bool visitAnyType(AnyType type, _) => false;
+
+ @override
+ bool visitFutureOrType(FutureOrType type, _) => check(type.typeArgument);
}
class RtiNeedDataComputer extends DataComputer<String> {
diff --git a/pkg/compiler/test/static_type/static_type_test.dart b/pkg/compiler/test/static_type/static_type_test.dart
index 15cf87d..0123144 100644
--- a/pkg/compiler/test/static_type/static_type_test.dart
+++ b/pkg/compiler/test/static_type/static_type_test.dart
@@ -86,9 +86,6 @@
String computeNodeValue(Id id, ir.TreeNode node) {
if (node is ir.VariableGet) {
return typeToText(node.accept(staticTypeCache));
- } else if (node is ir.MethodInvocation) {
- return '[${typeToText(node.receiver.accept(staticTypeCache))}]->'
- '${typeToText(node.accept(staticTypeCache))}';
} else if (node is ir.InstanceInvocation) {
return '[${typeToText(node.receiver.accept(staticTypeCache))}]->'
'${typeToText(node.accept(staticTypeCache))}';
diff --git a/pkg/dartdev/lib/src/analysis_server.dart b/pkg/dartdev/lib/src/analysis_server.dart
index 0e0f59c..a17a169 100644
--- a/pkg/dartdev/lib/src/analysis_server.dart
+++ b/pkg/dartdev/lib/src/analysis_server.dart
@@ -9,6 +9,7 @@
import 'package:analysis_server/src/server/driver.dart' show Driver;
import 'package:analysis_server_client/protocol.dart'
show EditBulkFixesResult, ResponseDecoder;
+import 'package:args/args.dart';
import 'package:meta/meta.dart';
import 'package:path/path.dart' as path;
@@ -16,17 +17,23 @@
import 'sdk.dart';
import 'utils.dart';
+/// When set, this function is executed just before the Analysis Server starts.
+void Function(String cmdName, List<FileSystemEntity> analysisRoots,
+ ArgResults argResults) preAnalysisServerStart;
+
/// A class to provide an API wrapper around an analysis server process.
class AnalysisServer {
AnalysisServer(
this.sdkPath,
this.analysisRoots, {
@required this.commandName,
+ @required this.argResults,
});
final Directory sdkPath;
final List<FileSystemEntity> analysisRoots;
final String commandName;
+ final ArgResults argResults;
Process _process;
@@ -69,6 +76,7 @@
final Map<String, Completer<Map<String, dynamic>>> _requestCompleters = {};
Future<void> start() async {
+ preAnalysisServerStart?.call(commandName, analysisRoots, argResults);
final List<String> command = <String>[
sdk.analysisServerSnapshot,
'--${Driver.SUPPRESS_ANALYTICS_FLAG}',
@@ -285,12 +293,14 @@
return messages.map((message) => DiagnosticMessage(message)).toList();
}
- // TODO(jwren) add some tests to verify that the results are what we are
- // expecting, 'other' is not always on the RHS of the subtraction in the
- // implementation.
@override
int compareTo(AnalysisError other) {
- // Sort in order of file path, error location, severity, and message.
+ // Sort in order of severity, file path, error location, and message.
+ final int diff = _severityLevel.index - other._severityLevel.index;
+ if (diff != 0) {
+ return diff;
+ }
+
if (file != other.file) {
return file.compareTo(other.file);
}
@@ -299,11 +309,6 @@
return offset - other.offset;
}
- final int diff = other._severityLevel.index - _severityLevel.index;
- if (diff != 0) {
- return diff;
- }
-
return message.compareTo(other.message);
}
diff --git a/pkg/dartdev/lib/src/commands/analyze.dart b/pkg/dartdev/lib/src/commands/analyze.dart
index a4c02be..27fbf53 100644
--- a/pkg/dartdev/lib/src/commands/analyze.dart
+++ b/pkg/dartdev/lib/src/commands/analyze.dart
@@ -100,6 +100,7 @@
io.Directory(sdk.sdkPath),
targets,
commandName: 'analyze',
+ argResults: argResults,
);
server.onErrors.listen((FileAnalysisErrors fileErrors) {
@@ -126,8 +127,6 @@
progress?.finish(showTiming: true);
- errors.sort();
-
if (errors.isEmpty) {
if (!machineFormat) {
log.stdout('No issues found!');
@@ -135,6 +134,8 @@
return 0;
}
+ errors.sort();
+
if (machineFormat) {
emitMachineFormat(log, errors);
} else if (jsonFormat) {
diff --git a/pkg/dartdev/lib/src/commands/fix.dart b/pkg/dartdev/lib/src/commands/fix.dart
index 60d2e46..08d4d36 100644
--- a/pkg/dartdev/lib/src/commands/fix.dart
+++ b/pkg/dartdev/lib/src/commands/fix.dart
@@ -93,6 +93,7 @@
io.Directory(sdk.sdkPath),
[dir],
commandName: 'fix',
+ argResults: argResults,
);
await server.start();
diff --git a/pkg/dartdev/lib/src/core.dart b/pkg/dartdev/lib/src/core.dart
index 2da96fc..b84cd86 100644
--- a/pkg/dartdev/lib/src/core.dart
+++ b/pkg/dartdev/lib/src/core.dart
@@ -18,6 +18,10 @@
Logger log;
bool isDiagnostics = false;
+/// When set, this function is executed from the [DartdevCommand] constructor to
+/// contribute additional flags.
+void Function(ArgParser argParser, String cmdName) flagContributor;
+
abstract class DartdevCommand extends Command<int> {
final String _name;
final String _description;
@@ -29,7 +33,9 @@
final bool hidden;
DartdevCommand(this._name, this._description, this._verbose,
- {this.hidden = false});
+ {this.hidden = false}) {
+ flagContributor?.call(argParser, _name);
+ }
@override
String get name => _name;
diff --git a/pkg/dartdev/test/analysis_server_test.dart b/pkg/dartdev/test/analysis_server_test.dart
index dba2ccc..05f7597 100644
--- a/pkg/dartdev/test/analysis_server_test.dart
+++ b/pkg/dartdev/test/analysis_server_test.dart
@@ -25,14 +25,14 @@
test('can start', () async {
AnalysisServer server = AnalysisServer(io.Directory(sdk.sdkPath), [p.dir],
- commandName: 'testing');
+ commandName: 'testing', argResults: null);
await server.start();
await server.shutdown();
});
test('can send message', () async {
AnalysisServer server = AnalysisServer(io.Directory(sdk.sdkPath), [p.dir],
- commandName: 'testing');
+ commandName: 'testing', argResults: null);
await server.start();
final response = await server.getVersion();
diff --git a/pkg/dartdev/test/commands/analyze_test.dart b/pkg/dartdev/test/commands/analyze_test.dart
index 293c139..d2a43e3 100644
--- a/pkg/dartdev/test/commands/analyze_test.dart
+++ b/pkg/dartdev/test/commands/analyze_test.dart
@@ -56,6 +56,119 @@
expect(error.contextMessages, hasLength(2));
});
});
+
+ group('sorting', () {
+ test('severity', () {
+ var errors = <AnalysisError>[
+ AnalysisError({
+ 'severity': 'INFO',
+ 'location': {
+ 'file': 'a.dart',
+ }
+ }),
+ AnalysisError({
+ 'severity': 'WARNING',
+ 'location': {
+ 'file': 'a.dart',
+ }
+ }),
+ AnalysisError({
+ 'severity': 'ERROR',
+ 'location': {
+ 'file': 'a.dart',
+ }
+ })
+ ];
+
+ errors.sort();
+
+ expect(errors, hasLength(3));
+ expect(errors[0].isError, isTrue);
+ expect(errors[1].isWarning, isTrue);
+ expect(errors[2].isInfo, isTrue);
+ });
+
+ test('file', () {
+ var errors = <AnalysisError>[
+ AnalysisError({
+ 'severity': 'INFO',
+ 'location': {
+ 'file': 'c.dart',
+ }
+ }),
+ AnalysisError({
+ 'severity': 'INFO',
+ 'location': {
+ 'file': 'b.dart',
+ }
+ }),
+ AnalysisError({
+ 'severity': 'INFO',
+ 'location': {
+ 'file': 'a.dart',
+ }
+ })
+ ];
+
+ errors.sort();
+
+ expect(errors, hasLength(3));
+ expect(errors[0].file, equals('a.dart'));
+ expect(errors[1].file, equals('b.dart'));
+ expect(errors[2].file, equals('c.dart'));
+ });
+
+ test('offset', () {
+ var errors = <AnalysisError>[
+ AnalysisError({
+ 'severity': 'INFO',
+ 'location': {'file': 'a.dart', 'offset': 8}
+ }),
+ AnalysisError({
+ 'severity': 'INFO',
+ 'location': {'file': 'a.dart', 'offset': 6}
+ }),
+ AnalysisError({
+ 'severity': 'INFO',
+ 'location': {'file': 'a.dart', 'offset': 4}
+ })
+ ];
+
+ errors.sort();
+
+ expect(errors, hasLength(3));
+ expect(errors[0].offset, equals(4));
+ expect(errors[1].offset, equals(6));
+ expect(errors[2].offset, equals(8));
+ });
+
+ test('message', () {
+ var errors = <AnalysisError>[
+ AnalysisError({
+ 'severity': 'INFO',
+ 'location': {'file': 'a.dart', 'offset': 8},
+ 'message': 'C'
+ }),
+ AnalysisError({
+ 'severity': 'INFO',
+ 'location': {'file': 'a.dart', 'offset': 6},
+ 'message': 'B'
+ }),
+ AnalysisError({
+ 'severity': 'INFO',
+ 'location': {'file': 'a.dart', 'offset': 4},
+ 'message': 'A'
+ })
+ ];
+
+ errors.sort();
+
+ expect(errors, hasLength(3));
+ expect(errors[0].message, equals('A'));
+ expect(errors[1].message, equals('B'));
+ expect(errors[2].message, equals('C'));
+ });
+ });
}
void defineAnalyze() {
diff --git a/pkg/dartdev/test/commands/format_test.dart b/pkg/dartdev/test/commands/format_test.dart
index 82e68d2..568f3ce 100644
--- a/pkg/dartdev/test/commands/format_test.dart
+++ b/pkg/dartdev/test/commands/format_test.dart
@@ -2,6 +2,7 @@
// 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.
+import 'dart:convert';
import 'dart:io';
import 'package:test/test.dart';
@@ -98,4 +99,16 @@
startsWith('No file or directory found at "$unknownFilePath".'));
expect(result.stdout, startsWith('Formatted no files in '));
});
+
+ test('formats from stdin and exits', () async {
+ p = project(mainSrc: 'int get foo => 1;\n');
+ var process = await p.start(['format']);
+ process.stdin.writeln('main( ) { }');
+
+ var result = process.stdout.reduce((a, b) => a + b);
+
+ await process.stdin.close();
+ expect(await process.exitCode, 0);
+ expect(utf8.decode(await result), 'main() {}\n');
+ });
}
diff --git a/pkg/dartdev/test/commands/test_test.dart b/pkg/dartdev/test/commands/test_test.dart
index b493403..bda022bb 100644
--- a/pkg/dartdev/test/commands/test_test.dart
+++ b/pkg/dartdev/test/commands/test_test.dart
@@ -30,7 +30,7 @@
expect(result.stdout, startsWith('''
Runs tests in this package.
-Usage: pub run test [files or directories...]
+Usage: dart test [files or directories...]
'''));
expect(result.stderr, isEmpty);
});
diff --git a/pkg/dds/CHANGELOG.md b/pkg/dds/CHANGELOG.md
index 84e2e6a..9859145 100644
--- a/pkg/dds/CHANGELOG.md
+++ b/pkg/dds/CHANGELOG.md
@@ -1,3 +1,7 @@
+# 2.0.2
+- Fix possibility of `LateInitializationError` being thrown when trying to
+ cleanup after an error during initialization.
+
# 2.0.1
- Update `package:vm_service` to ^7.0.0.
diff --git a/pkg/dds/analysis_options.yaml b/pkg/dds/analysis_options.yaml
index 413f412..1f83658 100644
--- a/pkg/dds/analysis_options.yaml
+++ b/pkg/dds/analysis_options.yaml
@@ -2,5 +2,6 @@
linter:
rules:
+ - depend_on_referenced_packages
- directives_ordering
- prefer_generic_function_type_aliases
diff --git a/pkg/dds/lib/src/dap/adapters/dart.dart b/pkg/dds/lib/src/dap/adapters/dart.dart
index d7811e0..64b66be 100644
--- a/pkg/dds/lib/src/dap/adapters/dart.dart
+++ b/pkg/dds/lib/src/dap/adapters/dart.dart
@@ -139,6 +139,9 @@
/// processed its initial paused state).
Future<void> get debuggerInitialized => _debuggerInitializedCompleter.future;
+ bool get evaluateToStringInDebugViews =>
+ args.evaluateToStringInDebugViews ?? false;
+
/// [attachRequest] is called by the client when it wants us to to attach to
/// an existing app. This will only be called once (and only one of this or
/// launchRequest will be called).
@@ -318,6 +321,15 @@
sendResponse(protocols?.toJson());
break;
+ /// Used to toggle debug settings such as whether SDK/Packages are
+ /// debuggable while the session is in progress.
+ case 'updateDebugOptions':
+ if (args != null) {
+ await _updateDebugOptions(args.args);
+ }
+ sendResponse(null);
+ break;
+
default:
await super.customRequest(request, args, sendResponse);
}
@@ -421,7 +433,7 @@
final resultString = await _converter.convertVmInstanceRefToDisplayString(
thread,
result,
- allowCallingToString: true,
+ allowCallingToString: evaluateToStringInDebugViews,
);
// TODO(dantup): We may need to store `expression` with this data
// to allow building nested evaluateNames.
@@ -845,7 +857,8 @@
thread,
variable.value,
name: variable.name,
- allowCallingToString: index <= maxToStringsPerEvaluation,
+ allowCallingToString: evaluateToStringInDebugViews &&
+ index <= maxToStringsPerEvaluation,
);
}
@@ -871,6 +884,7 @@
variables.addAll(await _converter.convertVmInstanceToVariablesList(
thread,
object,
+ allowCallingToString: evaluateToStringInDebugViews,
startItem: childStart,
numItems: childCount,
));
@@ -972,8 +986,15 @@
if (ref == null || ref.kind == vm.InstanceKind.kNull) {
return null;
}
- // TODO(dantup): This should handle truncation and complex types.
- return ref.valueAsString;
+ return _converter.convertVmInstanceRefToDisplayString(
+ thread,
+ ref,
+ // Always allow calling toString() here as the user expects the full
+ // string they logged regardless of the evaluateToStringInDebugViews
+ // setting.
+ allowCallingToString: true,
+ includeQuotesAroundString: false,
+ );
}
var loggerName = await asString(record.loggerName);
@@ -987,13 +1008,13 @@
final prefix = '[$loggerName] ';
if (message != null) {
- sendPrefixedOutput('stdout', prefix, '$message\n');
+ sendPrefixedOutput('console', prefix, '$message\n');
}
if (error != null) {
- sendPrefixedOutput('stderr', prefix, '$error\n');
+ sendPrefixedOutput('console', prefix, '$error\n');
}
if (stack != null) {
- sendPrefixedOutput('stderr', prefix, '$stack\n');
+ sendPrefixedOutput('console', prefix, '$stack\n');
}
}
@@ -1009,7 +1030,29 @@
// Notify IsolateManager if we'll be debugging so it knows whether to set
// up breakpoints etc. when isolates are registered.
final debug = !(args.noDebug ?? false);
- _isolateManager.setDebugEnabled(debug);
+ _isolateManager.debug = debug;
+ _isolateManager.debugSdkLibraries = args.debugSdkLibraries ?? true;
+ _isolateManager.debugExternalPackageLibraries =
+ args.debugExternalPackageLibraries ?? true;
+ }
+
+ /// Updates the current debug options for the session.
+ ///
+ /// Clients may not know about all debug options, so anything not included
+ /// in the map will not be updated by this method.
+ Future<void> _updateDebugOptions(Map<String, Object?> args) async {
+ // TODO(dantup): Document this - it's a public API we expect to be used
+ // by editors that can support it (although it will require custom
+ // code as it's there's no DAP standard for this, or the settings it
+ // toggles).
+ if (args.containsKey('debugSdkLibraries')) {
+ _isolateManager.debugSdkLibraries = args['debugSdkLibraries'] as bool;
+ }
+ if (args.containsKey('debugExternalPackageLibraries')) {
+ _isolateManager.debugExternalPackageLibraries =
+ args['debugExternalPackageLibraries'] as bool;
+ }
+ await _isolateManager.applyDebugOptions();
}
/// A wrapper around the same name function from package:vm_service that
diff --git a/pkg/dds/lib/src/dap/adapters/dart_cli.dart b/pkg/dds/lib/src/dap/adapters/dart_cli.dart
index b0fd701..c01214d 100644
--- a/pkg/dds/lib/src/dap/adapters/dart_cli.dart
+++ b/pkg/dds/lib/src/dap/adapters/dart_cli.dart
@@ -53,7 +53,9 @@
enableDds: enableDds,
enableAuthCodes: enableAuthCodes,
logger: logger,
- );
+ ) {
+ channel.closed.then((_) => shutdown());
+ }
Future<void> debuggerConnected(vm.VM vmInfo) async {
if (!isAttach) {
diff --git a/pkg/dds/lib/src/dap/base_debug_adapter.dart b/pkg/dds/lib/src/dap/base_debug_adapter.dart
index cd2b99a..a74f1f3 100644
--- a/pkg/dds/lib/src/dap/base_debug_adapter.dart
+++ b/pkg/dds/lib/src/dap/base_debug_adapter.dart
@@ -65,14 +65,7 @@
RawRequestArguments? args,
void Function(Object?) sendResponse,
) async {
- final response = Response(
- success: false,
- requestSeq: request.seq,
- seq: _sequence++,
- command: request.command,
- message: 'Unknown command: ${request.command}',
- );
- sendResponse(response);
+ throw DebugAdapterException('Unknown command ${request.command}');
}
Future<void> disconnectRequest(
@@ -251,7 +244,7 @@
} else if (message is Response) {
_handleIncomingResponse(message);
} else {
- throw Exception('Unknown Protocol message ${message.type}');
+ throw DebugAdapterException('Unknown Protocol message ${message.type}');
}
}
diff --git a/pkg/dds/lib/src/dap/isolate_manager.dart b/pkg/dds/lib/src/dap/isolate_manager.dart
index 99ee743..9c16536 100644
--- a/pkg/dds/lib/src/dap/isolate_manager.dart
+++ b/pkg/dds/lib/src/dap/isolate_manager.dart
@@ -23,15 +23,33 @@
final Map<int, ThreadInfo> _threadsByThreadId = {};
int _nextThreadNumber = 1;
- /// Whether debugging is enabled.
+ /// Whether debugging is enabled for this session.
///
/// This must be set before any isolates are spawned and controls whether
/// breakpoints or exception pause modes are sent to the VM.
///
+ /// If false, requests to send breakpoints or exception pause mode will be
+ /// dropped. Other functionality (handling pause events, resuming, etc.) will
+ /// all still function.
+ ///
/// This is used to support debug sessions that have VM Service connections
/// but were run with noDebug: true (for example we may need a VM Service
/// connection for a noDebug flutter app in order to support hot reload).
- bool _debug = false;
+ bool debug = false;
+
+ /// Whether SDK libraries should be marked as debuggable.
+ ///
+ /// Calling [sendLibraryDebuggables] is required after changing this value to
+ /// apply changes. This allows applying both [debugSdkLibraries] and
+ /// [debugExternalPackageLibraries] in one step.
+ bool debugSdkLibraries = true;
+
+ /// Whether external package libraries should be marked as debuggable.
+ ///
+ /// Calling [sendLibraryDebuggables] is required after changing this value to
+ /// apply changes. This allows applying both [debugSdkLibraries] and
+ /// [debugExternalPackageLibraries] in one step.
+ bool debugExternalPackageLibraries = true;
/// Tracks breakpoints last provided by the client so they can be sent to new
/// isolates that appear after initial breakpoints were sent.
@@ -72,6 +90,18 @@
/// not exited between accessing this list and trying to use the results.
List<ThreadInfo> get threads => _threadsByIsolateId.values.toList();
+ /// Re-applies debug options to all isolates/libraries.
+ ///
+ /// This is required if options like debugSdkLibraries are modified, but is a
+ /// separate step to batch together changes to multiple options.
+ Future<void> applyDebugOptions() async {
+ await Future.wait(_threadsByThreadId.values.map(
+ // debuggable libraries is the only thing currently affected by these
+ // changable options.
+ (isolate) => _sendLibraryDebuggables(isolate.isolate),
+ ));
+ }
+
Future<T> getObject<T extends vm.Response>(
vm.IsolateRef isolate, vm.ObjRef object) async {
final res = await _adapter.vmService?.getObject(isolate.id!, object.id!);
@@ -219,19 +249,6 @@
.map((isolate) => _sendBreakpoints(isolate.isolate, uri: uri)));
}
- /// Sets whether debugging is enabled for this session.
- ///
- /// If not, requests to send breakpoints or exception pause mode will be
- /// dropped. Other functionality (handling pause events, resuming, etc.) will
- /// all still function.
- ///
- /// This is used to support debug sessions that have VM Service connections
- /// but were run with noDebug: true (for example we may need a VM Service
- /// connection for a noDebug flutter app in order to support hot reload).
- void setDebugEnabled(bool debug) {
- _debug = debug;
- }
-
/// Records exception pause mode as one of 'None', 'Unhandled' or 'All'. All
/// existing isolates will be updated to reflect the new setting.
Future<void> setExceptionPauseMode(String mode) async {
@@ -371,13 +388,13 @@
/// Checks whether a library should be considered debuggable.
///
- /// This usesthe settings from the launch arguments (debugSdkLibraries
- /// and debugExternalPackageLibraries) against the type of library given.
+ /// Initial values are provided in the launch arguments, but may be updated
+ /// by the `updateDebugOptions` custom request.
bool _libaryIsDebuggable(vm.LibraryRef library) {
if (_isSdkLibrary(library)) {
- return _adapter.args.debugSdkLibraries ?? false;
+ return debugSdkLibraries;
} else if (_isExternalPackageLibrary(library)) {
- return _adapter.args.debugExternalPackageLibraries ?? false;
+ return debugExternalPackageLibraries;
} else {
return true;
}
@@ -391,7 +408,7 @@
/// newly-created isolates).
Future<void> _sendBreakpoints(vm.IsolateRef isolate, {String? uri}) async {
final service = _adapter.vmService;
- if (!_debug || service == null) {
+ if (!debug || service == null) {
return;
}
@@ -425,7 +442,7 @@
/// Sets the exception pause mode for an individual isolate.
Future<void> _sendExceptionPauseMode(vm.IsolateRef isolate) async {
final service = _adapter.vmService;
- if (!_debug || service == null) {
+ if (!debug || service == null) {
return;
}
@@ -436,7 +453,7 @@
/// on the debug settings.
Future<void> _sendLibraryDebuggables(vm.IsolateRef isolateRef) async {
final service = _adapter.vmService;
- if (!_debug || service == null) {
+ if (!debug || service == null) {
return;
}
diff --git a/pkg/dds/lib/src/dap/protocol_converter.dart b/pkg/dds/lib/src/dap/protocol_converter.dart
index 85ef5f8..6285121 100644
--- a/pkg/dds/lib/src/dap/protocol_converter.dart
+++ b/pkg/dds/lib/src/dap/protocol_converter.dart
@@ -57,21 +57,32 @@
required bool allowCallingToString,
bool includeQuotesAroundString = true,
}) async {
- final canCallToString = allowCallingToString &&
- (_adapter.args.evaluateToStringInDebugViews ?? false);
+ final isTruncated = ref.valueAsStringIsTruncated ?? false;
+ if (ref.kind == vm.InstanceKind.kString && isTruncated) {
+ // Call toString() if allowed, otherwise (or if it returns null) fall back
+ // to the truncated value with "…" suffix.
+ var stringValue = allowCallingToString
+ ? await _callToString(
+ thread,
+ ref,
+ includeQuotesAroundString: includeQuotesAroundString,
+ )
+ : null;
+ stringValue ??= '${ref.valueAsString}…';
- if (ref.kind == 'String' || ref.valueAsString != null) {
- var stringValue = ref.valueAsString.toString();
- if (ref.valueAsStringIsTruncated ?? false) {
- stringValue = '$stringValue…';
- }
- if (ref.kind == 'String' && includeQuotesAroundString) {
- stringValue = '"$stringValue"';
- }
- return stringValue;
+ return includeQuotesAroundString ? '"$stringValue"' : stringValue;
+ } else if (ref.kind == vm.InstanceKind.kString) {
+ // Untruncated strings.
+ return includeQuotesAroundString
+ ? '"${ref.valueAsString}"'
+ : ref.valueAsString.toString();
+ } else if (ref.valueAsString != null) {
+ return isTruncated
+ ? '${ref.valueAsString}…'
+ : ref.valueAsString.toString();
} else if (ref.kind == 'PlainInstance') {
var stringValue = ref.classRef?.name ?? '<unknown instance>';
- if (canCallToString) {
+ if (allowCallingToString) {
final toStringValue = await _callToString(
thread,
ref,
@@ -99,6 +110,7 @@
Future<List<dap.Variable>> convertVmInstanceToVariablesList(
ThreadInfo thread,
vm.Instance instance, {
+ required bool allowCallingToString,
int? startItem = 0,
int? numItems,
}) async {
@@ -112,7 +124,7 @@
await convertVmResponseToVariable(
thread,
instance,
- allowCallingToString: true,
+ allowCallingToString: allowCallingToString,
)
];
} else if (elements != null) {
@@ -121,10 +133,15 @@
return Future.wait(elements
.cast<vm.Response>()
.sublist(start, numItems != null ? start + numItems : null)
- .mapIndexed((index, response) async => convertVmResponseToVariable(
- thread, response,
+ .mapIndexed(
+ (index, response) => convertVmResponseToVariable(
+ thread,
+ response,
name: '${start + index}',
- allowCallingToString: index <= maxToStringsPerEvaluation)));
+ allowCallingToString:
+ allowCallingToString && index <= maxToStringsPerEvaluation,
+ ),
+ ));
} else if (associations != null) {
// For maps, create a variable for each entry (in the requested subset).
// Use the keys and values to create a display string in the form
@@ -135,13 +152,14 @@
return Future.wait(associations
.sublist(start, numItems != null ? start + numItems : null)
.mapIndexed((index, mapEntry) async {
- final allowCallingToString = index <= maxToStringsPerEvaluation;
+ final callToString =
+ allowCallingToString && index <= maxToStringsPerEvaluation;
final keyDisplay = await convertVmResponseToDisplayString(
thread, mapEntry.key,
- allowCallingToString: allowCallingToString);
+ allowCallingToString: callToString);
final valueDisplay = await convertVmResponseToDisplayString(
thread, mapEntry.value,
- allowCallingToString: allowCallingToString);
+ allowCallingToString: callToString);
return dap.Variable(
name: '${start + index}',
value: '$keyDisplay -> $valueDisplay',
@@ -154,7 +172,8 @@
(index, field) async => convertVmResponseToVariable(
thread, field.value,
name: field.decl?.name ?? '<unnamed field>',
- allowCallingToString: index <= maxToStringsPerEvaluation)));
+ allowCallingToString:
+ allowCallingToString && index <= maxToStringsPerEvaluation)));
// Also evaluate the getters if evaluateGettersInDebugViews=true enabled.
final service = _adapter.vmService;
@@ -177,7 +196,8 @@
thread,
response,
name: getterName,
- allowCallingToString: index <= maxToStringsPerEvaluation,
+ allowCallingToString:
+ allowCallingToString && index <= maxToStringsPerEvaluation,
);
}
@@ -397,7 +417,7 @@
if (service == null) {
return null;
}
- final result = await service.invoke(
+ var result = await service.invoke(
thread.isolate.id!,
ref.id!,
'toString',
@@ -405,10 +425,18 @@
disableBreakpoints: true,
);
+ // If the response is a string and is truncated, use getObject() to get the
+ // full value.
+ if (result is vm.InstanceRef &&
+ result.kind == 'String' &&
+ (result.valueAsStringIsTruncated ?? false)) {
+ result = await service.getObject(thread.isolate.id!, result.id!);
+ }
+
return convertVmResponseToDisplayString(
thread,
result,
- allowCallingToString: false,
+ allowCallingToString: false, // Don't allow recursing.
includeQuotesAroundString: includeQuotesAroundString,
);
}
diff --git a/pkg/dds/lib/src/dap/protocol_stream_transformers.dart b/pkg/dds/lib/src/dap/protocol_stream_transformers.dart
index 6bd6caa..424fa84 100644
--- a/pkg/dds/lib/src/dap/protocol_stream_transformers.dart
+++ b/pkg/dds/lib/src/dap/protocol_stream_transformers.dart
@@ -4,7 +4,6 @@
import 'dart:async';
import 'dart:convert';
-import 'dart:typed_data';
class InvalidEncodingError {
final String headers;
@@ -107,28 +106,3 @@
final String? encoding;
ProtocolHeaders(this.rawHeaders, this.contentLength, this.encoding);
}
-
-/// Transforms a stream of [Uint8List]s to [List<int>]s. Used because
-/// [ServerSocket] and [Socket] use [Uint8List] but stdin and stdout use
-/// [List<int>] and the LSP server needs to operate against both.
-class Uint8ListTransformer extends StreamTransformerBase<Uint8List, List<int>> {
- // TODO(dantup): Is there a built-in (or better) way to do this?
- @override
- Stream<List<int>> bind(Stream<Uint8List> stream) {
- late StreamSubscription<Uint8List> input;
- late StreamController<List<int>> _output;
- _output = StreamController<List<int>>(
- onListen: () {
- input = stream.listen(
- (uints) => _output.add(uints),
- onError: _output.addError,
- onDone: _output.close,
- );
- },
- onPause: () => input.pause(),
- onResume: () => input.resume(),
- onCancel: () => input.cancel(),
- );
- return _output.stream;
- }
-}
diff --git a/pkg/dds/lib/src/dap/server.dart b/pkg/dds/lib/src/dap/server.dart
index f2530a3..8a38138 100644
--- a/pkg/dds/lib/src/dap/server.dart
+++ b/pkg/dds/lib/src/dap/server.dart
@@ -3,92 +3,45 @@
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
-import 'dart:io';
import 'package:dds/src/dap/adapters/dart.dart';
-import 'package:pedantic/pedantic.dart';
import 'adapters/dart_cli.dart';
import 'logging.dart';
import 'protocol_stream.dart';
-import 'protocol_stream_transformers.dart';
-/// A DAP server that binds to a port and runs in multi-session mode.
+/// A DAP server that communicates over a [ByteStreamServerChannel], usually
+/// constructed from the processes stdin/stdout streams.
+///
+/// The server runs in single-user mode and services only a single client. For
+/// multiple debug sessions, there would be multiple servers (and the editor
+/// would have a client for each of them).
class DapServer {
- final ServerSocket _socket;
+ final ByteStreamServerChannel channel;
+ late final DartDebugAdapter adapter;
final bool ipv6;
final bool enableDds;
final bool enableAuthCodes;
final Logger? logger;
- final _channels = <ByteStreamServerChannel>{};
- final _adapters = <DartDebugAdapter>{};
- DapServer._(
- this._socket, {
+ DapServer(
+ Stream<List<int>> _input,
+ StreamSink<List<int>> _output, {
this.ipv6 = false,
this.enableDds = true,
this.enableAuthCodes = true,
this.logger,
- }) {
- _socket.listen(_acceptConnection);
- }
-
- String get host => _socket.address.host;
- int get port => _socket.port;
-
- Future<void> stop() async {
- _channels.forEach((client) => client.close());
- await _socket.close();
- }
-
- void _acceptConnection(Socket client) {
- final address = client.remoteAddress;
- logger?.call('Accepted connection from $address');
- client.done.then((_) {
- logger?.call('Connection from $address closed');
- });
- _createAdapter(client.transform(Uint8ListTransformer()), client);
- }
-
- void _createAdapter(Stream<List<int>> _input, StreamSink<List<int>> _output) {
- // TODO(dantup): This is hard-coded to DartCliDebugAdapter but will
- // ultimately need to support having a factory passed in to support
- // tests and/or being used in flutter_tools.
- final channel = ByteStreamServerChannel(_input, _output, logger);
- final adapter = DartCliDebugAdapter(
+ }) : channel = ByteStreamServerChannel(_input, _output, logger) {
+ adapter = DartCliDebugAdapter(
channel,
ipv6: ipv6,
enableDds: enableDds,
enableAuthCodes: enableAuthCodes,
logger: logger,
);
- _channels.add(channel);
- _adapters.add(adapter);
- unawaited(channel.closed.then((_) {
- _channels.remove(channel);
- _adapters.remove(adapter);
- adapter.shutdown();
- }));
}
- /// Starts a DAP Server listening on [host]:[port].
- static Future<DapServer> create({
- String? host,
- int port = 0,
- bool ipv6 = false,
- bool enableDdds = true,
- bool enableAuthCodes = true,
- Logger? logger,
- }) async {
- final hostFallback =
- ipv6 ? InternetAddress.loopbackIPv6 : InternetAddress.loopbackIPv4;
- final _socket = await ServerSocket.bind(host ?? hostFallback, port);
- return DapServer._(
- _socket,
- ipv6: ipv6,
- enableDds: enableDdds,
- enableAuthCodes: enableAuthCodes,
- logger: logger,
- );
+ void stop() {
+ channel.close();
}
}
diff --git a/pkg/dds/lib/src/dds_impl.dart b/pkg/dds/lib/src/dds_impl.dart
index c65ba5d..4360bcc 100644
--- a/pkg/dds/lib/src/dds_impl.dart
+++ b/pkg/dds/lib/src/dds_impl.dart
@@ -67,7 +67,7 @@
Future<void> startService() async {
bool started = false;
- final completer = Completer<void>();
+ DartDevelopmentServiceException? error;
// TODO(bkonyi): throw if we've already shutdown.
// Establish the connection to the VM service.
_vmServiceSocket = webSocketBuilder(remoteVmServiceWsUri);
@@ -76,18 +76,25 @@
unawaited(
vmServiceClient.listen().then(
(_) {
- shutdown();
- if (!started && !completer.isCompleted) {
- completer
- .completeError(DartDevelopmentServiceException.failedToStart());
+ if (started) {
+ shutdown();
+ } else {
+ // If we fail to connect to the service or the connection is
+ // terminated while we're starting up, we'll need to cleanup later
+ // once DDS has finished initializing to make sure all ports are
+ // closed before throwing the exception.
+ error = DartDevelopmentServiceException.failedToStart();
}
},
onError: (e, st) {
- shutdown();
- if (!completer.isCompleted) {
- completer.completeError(
- DartDevelopmentServiceException.connectionIssue(e.toString()),
- st,
+ if (started) {
+ shutdown();
+ } else {
+ // If we encounter an error while we're starting up, we'll need to
+ // cleanup later once DDS has finished initializing to make sure
+ // all ports are closed before throwing the exception.
+ error = DartDevelopmentServiceException.connectionIssue(
+ e.toString(),
);
}
},
@@ -104,13 +111,15 @@
// Once we have a connection to the VM service, we're ready to spawn the intermediary.
await _startDDSServer();
started = true;
- completer.complete();
} on StateError {
/* Ignore json-rpc state errors */
- } catch (e, st) {
- completer.completeError(e, st);
}
- return completer.future;
+
+ // Check if we encountered any errors during startup, cleanup, and throw.
+ if (error != null) {
+ await shutdown();
+ throw error!;
+ }
}
Future<void> _startDDSServer() async {
diff --git a/pkg/dds/pubspec.yaml b/pkg/dds/pubspec.yaml
index 2bf3136..012f3e3 100644
--- a/pkg/dds/pubspec.yaml
+++ b/pkg/dds/pubspec.yaml
@@ -3,7 +3,7 @@
A library used to spawn the Dart Developer Service, used to communicate with
a Dart VM Service instance.
-version: 2.0.1
+version: 2.0.2
homepage: https://github.com/dart-lang/sdk/tree/master/pkg/dds
diff --git a/pkg/dds/test/common/fakes.dart b/pkg/dds/test/common/fakes.dart
index 7e11f9d..9ef5cf9 100644
--- a/pkg/dds/test/common/fakes.dart
+++ b/pkg/dds/test/common/fakes.dart
@@ -7,6 +7,7 @@
import 'package:json_rpc_2/json_rpc_2.dart' as json_rpc;
import 'package:test/fake.dart';
import 'package:vm_service/vm_service.dart';
+import 'package:web_socket_channel/web_socket_channel.dart';
/// [FakePeer] implements the bare minimum of the [Peer] interface needed for
/// [DartDevelopmentService] to establish a connection with a VM service.
@@ -62,3 +63,18 @@
int _idCount = 0;
}
+
+class FakeWebSocketSink extends Fake implements WebSocketSink {
+ @override
+ Future close([int? closeCode, String? closeReason]) {
+ // Do nothing.
+ return Future.value();
+ }
+}
+
+/// [FakeWebSocketChannel] implements the bare minimum of the [WebSocket]
+/// interface required to finish DDS initialization.
+class FakeWebSocketChannel extends Fake implements WebSocketChannel {
+ @override
+ WebSocketSink get sink => FakeWebSocketSink();
+}
diff --git a/pkg/dds/test/dap/integration/debug_breakpoints_test.dart b/pkg/dds/test/dap/integration/debug_breakpoints_test.dart
index 9a50b03..62cacbf 100644
--- a/pkg/dds/test/dap/integration/debug_breakpoints_test.dart
+++ b/pkg/dds/test/dap/integration/debug_breakpoints_test.dart
@@ -9,56 +9,61 @@
import 'test_support.dart';
main() {
- testDap((dap) async {
- group('debug mode breakpoints', () {
- test('stops at a line breakpoint', () async {
- final client = dap.client;
- final testFile = dap.createTestFile(simpleBreakpointProgram);
- final breakpointLine = lineWith(testFile, '// BREAKPOINT');
+ late DapTestSession dap;
+ setUp(() async {
+ dap = await DapTestSession.setUp();
+ });
+ tearDown(() => dap.tearDown());
- await client.hitBreakpoint(testFile, breakpointLine);
- });
+ group('debug mode breakpoints', () {
+ test('stops at a line breakpoint', () async {
+ final client = dap.client;
+ final testFile = dap.createTestFile(simpleBreakpointProgram);
+ final breakpointLine = lineWith(testFile, '// BREAKPOINT');
- test('stops at a line breakpoint and can be resumed', () async {
- final client = dap.client;
- final testFile = dap.createTestFile(simpleBreakpointProgram);
- final breakpointLine = lineWith(testFile, '// BREAKPOINT');
+ await client.hitBreakpoint(testFile, breakpointLine);
+ });
- // Hit the initial breakpoint.
- final stop = await client.hitBreakpoint(testFile, breakpointLine);
+ test('stops at a line breakpoint and can be resumed', () async {
+ final client = dap.client;
+ final testFile = dap.createTestFile(simpleBreakpointProgram);
+ final breakpointLine = lineWith(testFile, '// BREAKPOINT');
- // Resume and expect termination (as the script will get to the end).
- await Future.wait([
- client.event('terminated'),
- client.continue_(stop.threadId!),
- ], eagerError: true);
- });
+ // Hit the initial breakpoint.
+ final stop = await client.hitBreakpoint(testFile, breakpointLine);
- test('stops at a line breakpoint and can step over (next)', () async {
- final testFile = dap.createTestFile(r'''
+ // Resume and expect termination (as the script will get to the end).
+ await Future.wait([
+ client.event('terminated'),
+ client.continue_(stop.threadId!),
+ ], eagerError: true);
+ });
+
+ test('stops at a line breakpoint and can step over (next)', () async {
+ final testFile = dap.createTestFile(r'''
void main(List<String> args) async {
print('Hello!'); // BREAKPOINT
print('Hello!'); // STEP
}
''');
- final breakpointLine = lineWith(testFile, '// BREAKPOINT');
- final stepLine = lineWith(testFile, '// STEP');
+ final breakpointLine = lineWith(testFile, '// BREAKPOINT');
+ final stepLine = lineWith(testFile, '// STEP');
- // Hit the initial breakpoint.
- final stop = await dap.client.hitBreakpoint(testFile, breakpointLine);
+ // Hit the initial breakpoint.
+ final stop = await dap.client.hitBreakpoint(testFile, breakpointLine);
- // Step and expect stopping on the next line with a 'step' stop type.
- await Future.wait([
- dap.client.expectStop('step', file: testFile, line: stepLine),
- dap.client.next(stop.threadId!),
- ], eagerError: true);
- });
+ // Step and expect stopping on the next line with a 'step' stop type.
+ await Future.wait([
+ dap.client.expectStop('step', file: testFile, line: stepLine),
+ dap.client.next(stop.threadId!),
+ ], eagerError: true);
+ });
- test(
- 'stops at a line breakpoint and can step over (next) an async boundary',
- () async {
- final client = dap.client;
- final testFile = dap.createTestFile(r'''
+ test(
+ 'stops at a line breakpoint and can step over (next) an async boundary',
+ () async {
+ final client = dap.client;
+ final testFile = dap.createTestFile(r'''
Future<void> main(List<String> args) async {
await asyncPrint('Hello!'); // BREAKPOINT
await asyncPrint('Hello!'); // STEP
@@ -68,30 +73,30 @@
await Future.delayed(const Duration(milliseconds: 1));
}
''');
- final breakpointLine = lineWith(testFile, '// BREAKPOINT');
- final stepLine = lineWith(testFile, '// STEP');
+ final breakpointLine = lineWith(testFile, '// BREAKPOINT');
+ final stepLine = lineWith(testFile, '// STEP');
- // Hit the initial breakpoint.
- final stop = await dap.client.hitBreakpoint(testFile, breakpointLine);
+ // Hit the initial breakpoint.
+ final stop = await dap.client.hitBreakpoint(testFile, breakpointLine);
- // The first step will move from `asyncPrint` to the `await`.
- await Future.wait([
- client.expectStop('step', file: testFile, line: breakpointLine),
- client.next(stop.threadId!),
- ], eagerError: true);
+ // The first step will move from `asyncPrint` to the `await`.
+ await Future.wait([
+ client.expectStop('step', file: testFile, line: breakpointLine),
+ client.next(stop.threadId!),
+ ], eagerError: true);
- // The next step should go over the async boundary and to stepLine (if
- // we did not correctly send kOverAsyncSuspension we would end up in
- // the asyncPrint method).
- await Future.wait([
- client.expectStop('step', file: testFile, line: stepLine),
- client.next(stop.threadId!),
- ], eagerError: true);
- });
+ // The next step should go over the async boundary and to stepLine (if
+ // we did not correctly send kOverAsyncSuspension we would end up in
+ // the asyncPrint method).
+ await Future.wait([
+ client.expectStop('step', file: testFile, line: stepLine),
+ client.next(stop.threadId!),
+ ], eagerError: true);
+ });
- test('stops at a line breakpoint and can step in', () async {
- final client = dap.client;
- final testFile = dap.createTestFile(r'''
+ test('stops at a line breakpoint and can step in', () async {
+ final client = dap.client;
+ final testFile = dap.createTestFile(r'''
void main(List<String> args) async {
log('Hello!'); // BREAKPOINT
}
@@ -100,22 +105,22 @@
print(message);
}
''');
- final breakpointLine = lineWith(testFile, '// BREAKPOINT');
- final stepLine = lineWith(testFile, '// STEP');
+ final breakpointLine = lineWith(testFile, '// BREAKPOINT');
+ final stepLine = lineWith(testFile, '// STEP');
- // Hit the initial breakpoint.
- final stop = await client.hitBreakpoint(testFile, breakpointLine);
+ // Hit the initial breakpoint.
+ final stop = await client.hitBreakpoint(testFile, breakpointLine);
- // Step and expect stopping in the inner function with a 'step' stop type.
- await Future.wait([
- client.expectStop('step', file: testFile, line: stepLine),
- client.stepIn(stop.threadId!),
- ], eagerError: true);
- });
+ // Step and expect stopping in the inner function with a 'step' stop type.
+ await Future.wait([
+ client.expectStop('step', file: testFile, line: stepLine),
+ client.stepIn(stop.threadId!),
+ ], eagerError: true);
+ });
- test('stops at a line breakpoint and can step out', () async {
- final client = dap.client;
- final testFile = dap.createTestFile(r'''
+ test('stops at a line breakpoint and can step out', () async {
+ final client = dap.client;
+ final testFile = dap.createTestFile(r'''
void main(List<String> args) async {
log('Hello!');
log('Hello!'); // STEP
@@ -125,87 +130,119 @@
print(message); // BREAKPOINT
}
''');
- final breakpointLine = lineWith(testFile, '// BREAKPOINT');
- final stepLine = lineWith(testFile, '// STEP');
+ final breakpointLine = lineWith(testFile, '// BREAKPOINT');
+ final stepLine = lineWith(testFile, '// STEP');
- // Hit the initial breakpoint.
- final stop = await client.hitBreakpoint(testFile, breakpointLine);
+ // Hit the initial breakpoint.
+ final stop = await client.hitBreakpoint(testFile, breakpointLine);
- // Step and expect stopping in the inner function with a 'step' stop type.
- await Future.wait([
- client.expectStop('step', file: testFile, line: stepLine),
- client.stepOut(stop.threadId!),
- ], eagerError: true);
- });
+ // Step and expect stopping in the inner function with a 'step' stop type.
+ await Future.wait([
+ client.expectStop('step', file: testFile, line: stepLine),
+ client.stepOut(stop.threadId!),
+ ], eagerError: true);
+ });
- test('does not step into SDK code with debugSdkLibraries=false',
- () async {
- final client = dap.client;
- final testFile = dap.createTestFile(r'''
+ test('does not step into SDK code with debugSdkLibraries=false', () async {
+ final client = dap.client;
+ final testFile = dap.createTestFile(r'''
void main(List<String> args) async {
print('Hello!'); // BREAKPOINT
print('Hello!'); // STEP
}
''');
- final breakpointLine = lineWith(testFile, '// BREAKPOINT');
- final stepLine = lineWith(testFile, '// STEP');
+ final breakpointLine = lineWith(testFile, '// BREAKPOINT');
+ final stepLine = lineWith(testFile, '// STEP');
- // Hit the initial breakpoint.
- final stop = await client.hitBreakpoint(testFile, breakpointLine);
+ // Hit the initial breakpoint.
+ final stop = await client.hitBreakpoint(
+ testFile,
+ breakpointLine,
+ launch: () => client.launch(
+ testFile.path,
+ debugSdkLibraries: false,
+ ),
+ );
- // Step in and expect stopping on the next line (don't go into print).
- await Future.wait([
- client.expectStop('step', file: testFile, line: stepLine),
- client.stepIn(stop.threadId!),
- ], eagerError: true);
- });
+ // Step in and expect stopping on the next line (don't go into print).
+ await Future.wait([
+ client.expectStop('step', file: testFile, line: stepLine),
+ client.stepIn(stop.threadId!),
+ ], eagerError: true);
+ });
- test('steps into SDK code with debugSdkLibraries=true', () async {
- final client = dap.client;
- final testFile = dap.createTestFile(r'''
+ test('steps into SDK code with debugSdkLibraries=true', () async {
+ final client = dap.client;
+ final testFile = dap.createTestFile(r'''
void main(List<String> args) async {
print('Hello!'); // BREAKPOINT
print('Hello!');
}
''');
- final breakpointLine = lineWith(testFile, '// BREAKPOINT');
+ final breakpointLine = lineWith(testFile, '// BREAKPOINT');
- // Hit the initial breakpoint.
- final stop = await dap.client.hitBreakpoint(
- testFile,
- breakpointLine,
- launch: () => client.launch(
- testFile.path,
- debugSdkLibraries: true,
- ),
- );
+ // Hit the initial breakpoint.
+ final stop = await dap.client.hitBreakpoint(
+ testFile,
+ breakpointLine,
+ launch: () => client.launch(
+ testFile.path,
+ debugSdkLibraries: true,
+ ),
+ );
- // Step in and expect to go into print.
- await Future.wait([
- client.expectStop('step', sourceName: 'dart:core/print.dart'),
- client.stepIn(stop.threadId!),
- ], eagerError: true);
+ // Step in and expect to go into print.
+ await Future.wait([
+ client.expectStop('step', sourceName: 'dart:core/print.dart'),
+ client.stepIn(stop.threadId!),
+ ], eagerError: true);
+ });
+
+ test(
+ 'does not step into external package code with debugExternalPackageLibraries=false',
+ () {
+ // TODO(dantup): Support for debugExternalPackageLibraries
+ }, skip: true);
+
+ test(
+ 'steps into external package code with debugExternalPackageLibraries=true',
+ () {
+ // TODO(dantup): Support for debugExternalPackageLibraries
+ }, skip: true);
+
+ test('allows changing debug settings during session', () async {
+ final client = dap.client;
+ final testFile = dap.createTestFile(r'''
+void main(List<String> args) async {
+ print('Hello!'); // BREAKPOINT
+ print('Hello!'); // STEP
+}
+ ''');
+ final breakpointLine = lineWith(testFile, '// BREAKPOINT');
+ final stepLine = lineWith(testFile, '// STEP');
+
+ // Start with debugSdkLibraryes _enabled_ and hit the breakpoint.
+ final stop = await client.hitBreakpoint(
+ testFile,
+ breakpointLine,
+ launch: () => client.launch(
+ testFile.path,
+ debugSdkLibraries: true,
+ ),
+ );
+
+ // Turn off debugSdkLibraries.
+ await client.custom('updateDebugOptions', {
+ 'debugSdkLibraries': false,
});
- test(
- 'does not step into external package code with debugExternalPackageLibraries=false',
- () {
- // TODO(dantup): Support for debugExternalPackageLibraries
- }, skip: true);
-
- test(
- 'steps into external package code with debugExternalPackageLibraries=true',
- () {
- // TODO(dantup): Support for debugExternalPackageLibraries
- }, skip: true);
-
- test('allows changing debug settings during session', () {
- // TODO(dantup): !
- // Dart-Code's DAP has a custom method that allows an editor to change
- // the debug settings (debugSdkLibraries/debugExternalPackageLibraries)
- // during a debug session.
- }, skip: true);
- // These tests can be slow due to starting up the external server process.
- }, timeout: Timeout.none);
- });
+ // Step in and expect stopping on the next line (don't go into print
+ // because we turned off SDK debugging).
+ await Future.wait([
+ client.expectStop('step', file: testFile, line: stepLine),
+ client.stepIn(stop.threadId!),
+ ], eagerError: true);
+ });
+ // These tests can be slow due to starting up the external server process.
+ }, timeout: Timeout.none);
}
diff --git a/pkg/dds/test/dap/integration/debug_eval_test.dart b/pkg/dds/test/dap/integration/debug_eval_test.dart
index 9b59310..ab24f0c 100644
--- a/pkg/dds/test/dap/integration/debug_eval_test.dart
+++ b/pkg/dds/test/dap/integration/debug_eval_test.dart
@@ -10,126 +10,131 @@
import 'test_support.dart';
main() {
- testDap((dap) async {
- group('debug mode evaluation', () {
- test('evaluates expressions with simple results', () async {
- final client = dap.client;
- final testFile = await dap.createTestFile(r'''
+ late DapTestSession dap;
+ setUp(() async {
+ dap = await DapTestSession.setUp();
+ });
+ tearDown(() => dap.tearDown());
+
+ group('debug mode evaluation', () {
+ test('evaluates expressions with simple results', () async {
+ final client = dap.client;
+ final testFile = await dap.createTestFile(r'''
void main(List<String> args) {
var a = 1;
var b = 2;
var c = 'test';
print('Hello!'); // BREAKPOINT
}''');
- final breakpointLine = lineWith(testFile, '// BREAKPOINT');
+ final breakpointLine = lineWith(testFile, '// BREAKPOINT');
- final stop = await client.hitBreakpoint(testFile, breakpointLine);
- await client.expectTopFrameEvalResult(stop.threadId!, 'a', '1');
- await client.expectTopFrameEvalResult(stop.threadId!, 'a * b', '2');
- await client.expectTopFrameEvalResult(stop.threadId!, 'c', '"test"');
- });
+ final stop = await client.hitBreakpoint(testFile, breakpointLine);
+ await client.expectTopFrameEvalResult(stop.threadId!, 'a', '1');
+ await client.expectTopFrameEvalResult(stop.threadId!, 'a * b', '2');
+ await client.expectTopFrameEvalResult(stop.threadId!, 'c', '"test"');
+ });
- test('evaluates expressions with complex results', () async {
- final client = dap.client;
- final testFile = await dap.createTestFile(simpleBreakpointProgram);
- final breakpointLine = lineWith(testFile, '// BREAKPOINT');
+ test('evaluates expressions with complex results', () async {
+ final client = dap.client;
+ final testFile = await dap.createTestFile(simpleBreakpointProgram);
+ final breakpointLine = lineWith(testFile, '// BREAKPOINT');
- final stop = await client.hitBreakpoint(testFile, breakpointLine);
- final result = await client.expectTopFrameEvalResult(
- stop.threadId!,
- 'DateTime(2000, 1, 1)',
- 'DateTime',
- );
+ final stop = await client.hitBreakpoint(testFile, breakpointLine);
+ final result = await client.expectTopFrameEvalResult(
+ stop.threadId!,
+ 'DateTime(2000, 1, 1)',
+ 'DateTime',
+ );
- // Check we got a variablesReference that maps on to the fields.
- expect(result.variablesReference, greaterThan(0));
- await client.expectVariables(
- result.variablesReference,
- '''
+ // Check we got a variablesReference that maps on to the fields.
+ expect(result.variablesReference, greaterThan(0));
+ await client.expectVariables(
+ result.variablesReference,
+ '''
isUtc: false
''',
- );
- });
+ );
+ });
- test(
- 'evaluates complex expressions expressions with evaluateToStringInDebugViews=true',
- () async {
- final client = dap.client;
- final testFile = await dap.createTestFile(simpleBreakpointProgram);
- final breakpointLine = lineWith(testFile, '// BREAKPOINT');
+ test(
+ 'evaluates complex expressions expressions with evaluateToStringInDebugViews=true',
+ () async {
+ final client = dap.client;
+ final testFile = await dap.createTestFile(simpleBreakpointProgram);
+ final breakpointLine = lineWith(testFile, '// BREAKPOINT');
- final stop = await client.hitBreakpoint(
- testFile,
- breakpointLine,
- launch: () =>
- client.launch(testFile.path, evaluateToStringInDebugViews: true),
- );
+ final stop = await client.hitBreakpoint(
+ testFile,
+ breakpointLine,
+ launch: () =>
+ client.launch(testFile.path, evaluateToStringInDebugViews: true),
+ );
- await client.expectTopFrameEvalResult(
- stop.threadId!,
- 'DateTime(2000, 1, 1)',
- 'DateTime (2000-01-01 00:00:00.000)',
- );
- });
+ await client.expectTopFrameEvalResult(
+ stop.threadId!,
+ 'DateTime(2000, 1, 1)',
+ 'DateTime (2000-01-01 00:00:00.000)',
+ );
+ });
- test(
- 'evaluates $threadExceptionExpression to the threads exception (simple type)',
- () async {
- final client = dap.client;
- final testFile = await dap.createTestFile(r'''
+ test(
+ 'evaluates $threadExceptionExpression to the threads exception (simple type)',
+ () async {
+ final client = dap.client;
+ final testFile = await dap.createTestFile(r'''
void main(List<String> args) {
throw 'my error';
}''');
- final stop = await client.hitException(testFile);
+ final stop = await client.hitException(testFile);
- final result = await client.expectTopFrameEvalResult(
- stop.threadId!,
- threadExceptionExpression,
- '"my error"',
- );
- expect(result.variablesReference, equals(0));
- });
+ final result = await client.expectTopFrameEvalResult(
+ stop.threadId!,
+ threadExceptionExpression,
+ '"my error"',
+ );
+ expect(result.variablesReference, equals(0));
+ });
- test(
- 'evaluates $threadExceptionExpression to the threads exception (complex type)',
- () async {
- final client = dap.client;
- final testFile = await dap.createTestFile(r'''
+ test(
+ 'evaluates $threadExceptionExpression to the threads exception (complex type)',
+ () async {
+ final client = dap.client;
+ final testFile = await dap.createTestFile(r'''
void main(List<String> args) {
throw Exception('my error');
}''');
- final stop = await client.hitException(testFile);
- final result = await client.expectTopFrameEvalResult(
- stop.threadId!,
- threadExceptionExpression,
- '_Exception',
- );
- expect(result.variablesReference, greaterThan(0));
- });
+ final stop = await client.hitException(testFile);
+ final result = await client.expectTopFrameEvalResult(
+ stop.threadId!,
+ threadExceptionExpression,
+ '_Exception',
+ );
+ expect(result.variablesReference, greaterThan(0));
+ });
- test(
- 'evaluates $threadExceptionExpression.x.y to x.y on the threads exception',
- () async {
- final client = dap.client;
- final testFile = await dap.createTestFile(r'''
+ test(
+ 'evaluates $threadExceptionExpression.x.y to x.y on the threads exception',
+ () async {
+ final client = dap.client;
+ final testFile = await dap.createTestFile(r'''
void main(List<String> args) {
throw Exception('12345');
}
''');
- final stop = await client.hitException(testFile);
- await client.expectTopFrameEvalResult(
- stop.threadId!,
- '$threadExceptionExpression.message.length',
- '5',
- );
- });
+ final stop = await client.hitException(testFile);
+ await client.expectTopFrameEvalResult(
+ stop.threadId!,
+ '$threadExceptionExpression.message.length',
+ '5',
+ );
+ });
- test('can evaluate expressions in non-top frames', () async {
- final client = dap.client;
- final testFile = await dap.createTestFile(r'''
+ test('can evaluate expressions in non-top frames', () async {
+ final client = dap.client;
+ final testFile = await dap.createTestFile(r'''
void main(List<String> args) {
var a = 999;
foo();
@@ -138,17 +143,16 @@
void foo() {
var a = 111; // BREAKPOINT
}''');
- final breakpointLine = lineWith(testFile, '// BREAKPOINT');
+ final breakpointLine = lineWith(testFile, '// BREAKPOINT');
- final stop = await client.hitBreakpoint(testFile, breakpointLine);
- final stack = await client.getValidStack(stop.threadId!,
- startFrame: 0, numFrames: 2);
- final secondFrameId = stack.stackFrames[1].id;
+ final stop = await client.hitBreakpoint(testFile, breakpointLine);
+ final stack = await client.getValidStack(stop.threadId!,
+ startFrame: 0, numFrames: 2);
+ final secondFrameId = stack.stackFrames[1].id;
- await client.expectEvalResult(secondFrameId, 'a', '999');
- });
+ await client.expectEvalResult(secondFrameId, 'a', '999');
+ });
- // These tests can be slow due to starting up the external server process.
- }, timeout: Timeout.none);
- });
+ // These tests can be slow due to starting up the external server process.
+ }, timeout: Timeout.none);
}
diff --git a/pkg/dds/test/dap/integration/debug_logging_test.dart b/pkg/dds/test/dap/integration/debug_logging_test.dart
index 1df090c..27578f5 100644
--- a/pkg/dds/test/dap/integration/debug_logging_test.dart
+++ b/pkg/dds/test/dap/integration/debug_logging_test.dart
@@ -4,13 +4,19 @@
import 'package:test/test.dart';
+import 'test_client.dart';
import 'test_support.dart';
main() {
- testDap((dap) async {
- group('debug mode', () {
- test('prints messages from dart:developer log()', () async {
- final testFile = dap.createTestFile(r'''
+ late DapTestSession dap;
+ setUp(() async {
+ dap = await DapTestSession.setUp();
+ });
+ tearDown(() => dap.tearDown());
+
+ group('debug mode', () {
+ test('prints messages from dart:developer log()', () async {
+ final testFile = dap.createTestFile(r'''
import 'dart:developer';
void main(List<String> args) async {
@@ -19,19 +25,45 @@
}
''');
- var outputEvents = await dap.client.collectOutput(file: testFile);
+ var outputEvents = await dap.client.collectOutput(file: testFile);
- // Skip the first line because it's the VM Service connection info.
- final output = outputEvents.skip(1).map((e) => e.output).join();
- expectLines(output, [
- '[log] this is a test',
- ' across two lines',
- '[foo] this is a test',
- '',
- 'Exited.',
- ]);
- });
- // These tests can be slow due to starting up the external server process.
- }, timeout: Timeout.none);
- });
+ // Skip the first line because it's the VM Service connection info.
+ final output = outputEvents.skip(1).map((e) => e.output).join();
+ expectLines(output, [
+ '[log] this is a test',
+ ' across two lines',
+ '[foo] this is a test',
+ '',
+ 'Exited.',
+ ]);
+ });
+
+ test('prints long messages from dart:developer log()', () async {
+ // Make a long message that's more than 255 chars (where the VM truncates
+ // log strings by default).
+ final longMessage = 'this is a test' * 20;
+ final testFile = dap.createTestFile('''
+import 'dart:developer';
+
+void main(List<String> args) async {
+ log('$longMessage');
+ // Prevent us exiting before the async log messages may have completed.
+ // The test will terminate the script early once the expectations are met.
+ await Future.delayed(const Duration(seconds: 30));
+}
+ ''');
+ final expectedLogMessage = '[log] $longMessage\n';
+
+ final consoleOutputs = dap.client.outputEvents
+ .where((event) => event.category == 'console')
+ .map((event) => event.output);
+
+ await Future.wait([
+ expectLater(consoleOutputs, emitsThrough(expectedLogMessage)),
+ dap.client.start(file: testFile),
+ ]);
+ await dap.client.terminate();
+ });
+ // These tests can be slow due to starting up the external server process.
+ }, timeout: Timeout.none);
}
diff --git a/pkg/dds/test/dap/integration/debug_test.dart b/pkg/dds/test/dap/integration/debug_test.dart
index 7b80af0..41863f9 100644
--- a/pkg/dds/test/dap/integration/debug_test.dart
+++ b/pkg/dds/test/dap/integration/debug_test.dart
@@ -10,10 +10,15 @@
import 'test_support.dart';
main() {
- testDap((dap) async {
- group('debug mode', () {
- test('runs a simple script', () async {
- final testFile = dap.createTestFile(r'''
+ group('debug mode', () {
+ late DapTestSession dap;
+ setUp(() async {
+ dap = await DapTestSession.setUp();
+ });
+ tearDown(() => dap.tearDown());
+
+ test('runs a simple script', () async {
+ final testFile = dap.createTestFile(r'''
void main(List<String> args) async {
print('Hello!');
print('World!');
@@ -21,100 +26,99 @@
}
''');
- final outputEvents = await dap.client.collectOutput(
- launch: () => dap.client.launch(
- testFile.path,
- args: ['one', 'two'],
- ),
- );
+ final outputEvents = await dap.client.collectOutput(
+ launch: () => dap.client.launch(
+ testFile.path,
+ args: ['one', 'two'],
+ ),
+ );
- // Expect a "console" output event that prints the URI of the VM Service
- // the debugger connects to.
- final vmConnection = outputEvents.first;
- expect(vmConnection.output,
- startsWith('Connecting to VM Service at ws://127.0.0.1:'));
- expect(vmConnection.category, equals('console'));
+ // Expect a "console" output event that prints the URI of the VM Service
+ // the debugger connects to.
+ final vmConnection = outputEvents.first;
+ expect(vmConnection.output,
+ startsWith('Connecting to VM Service at ws://127.0.0.1:'));
+ expect(vmConnection.category, equals('console'));
- // Expect the normal applications output.
- final output = outputEvents.skip(1).map((e) => e.output).join();
- expectLines(output, [
- 'Hello!',
- 'World!',
- 'args: [one, two]',
- '',
- 'Exited.',
- ]);
- });
+ // Expect the normal applications output.
+ final output = outputEvents.skip(1).map((e) => e.output).join();
+ expectLines(output, [
+ 'Hello!',
+ 'World!',
+ 'args: [one, two]',
+ '',
+ 'Exited.',
+ ]);
+ });
- test('provides a list of threads', () async {
- final client = dap.client;
- final testFile = dap.createTestFile(simpleBreakpointProgram);
- final breakpointLine = lineWith(testFile, '// BREAKPOINT');
+ test('provides a list of threads', () async {
+ final client = dap.client;
+ final testFile = dap.createTestFile(simpleBreakpointProgram);
+ final breakpointLine = lineWith(testFile, '// BREAKPOINT');
- await client.hitBreakpoint(testFile, breakpointLine);
- final response = await client.getValidThreads();
+ await client.hitBreakpoint(testFile, breakpointLine);
+ final response = await client.getValidThreads();
- expect(response.threads, hasLength(1));
- expect(response.threads.first.name, equals('main'));
- });
+ expect(response.threads, hasLength(1));
+ expect(response.threads.first.name, equals('main'));
+ });
- test('runs with DDS', () async {
- final client = dap.client;
- final testFile = dap.createTestFile(simpleBreakpointProgram);
- final breakpointLine = lineWith(testFile, '// BREAKPOINT');
+ test('runs with DDS by default', () async {
+ final client = dap.client;
+ final testFile = dap.createTestFile(simpleBreakpointProgram);
+ final breakpointLine = lineWith(testFile, '// BREAKPOINT');
- await client.hitBreakpoint(testFile, breakpointLine);
- expect(await client.ddsAvailable, isTrue);
- });
- // These tests can be slow due to starting up the external server process.
- }, timeout: Timeout.none);
+ await client.hitBreakpoint(testFile, breakpointLine);
+ expect(await client.ddsAvailable, isTrue);
+ });
- test('runs with auth codes enabled', () async {
+ test('runs with auth codes enabled by default', () async {
final testFile = dap.createTestFile(emptyProgram);
final outputEvents = await dap.client.collectOutput(file: testFile);
- expect(_hasAuthCode(outputEvents.first), isTrue);
+ final vmServiceUri = _extractVmServiceUri(outputEvents.first);
+ expect(vmServiceUri.path, matches(vmServiceAuthCodePathPattern));
});
- });
+ // These tests can be slow due to starting up the external server process.
+ }, timeout: Timeout.none);
- testDap((dap) async {
- group('debug mode', () {
- test('runs without DDS', () async {
- final client = dap.client;
- final testFile = dap.createTestFile(simpleBreakpointProgram);
- final breakpointLine = lineWith(testFile, '// BREAKPOINT');
+ group('debug mode', () {
+ test('can run without DDS', () async {
+ final dap = await DapTestSession.setUp(additionalArgs: ['--no-dds']);
+ addTearDown(dap.tearDown);
- await client.hitBreakpoint(testFile, breakpointLine);
+ final client = dap.client;
+ final testFile = dap.createTestFile(simpleBreakpointProgram);
+ final breakpointLine = lineWith(testFile, '// BREAKPOINT');
- expect(await client.ddsAvailable, isFalse);
- });
+ await client.hitBreakpoint(testFile, breakpointLine);
- test('runs with auth tokens disabled', () async {
- final testFile = dap.createTestFile(emptyProgram);
+ expect(await client.ddsAvailable, isFalse);
+ });
- final outputEvents = await dap.client.collectOutput(file: testFile);
- expect(_hasAuthCode(outputEvents.first), isFalse);
- });
- // These tests can be slow due to starting up the external server process.
- }, timeout: Timeout.none);
- }, additionalArgs: ['--no-dds', '--no-auth-codes']);
+ test('can run without auth codes', () async {
+ final dap =
+ await DapTestSession.setUp(additionalArgs: ['--no-auth-codes']);
+ addTearDown(dap.tearDown);
- testDap((dap) async {
- group('debug mode', () {
- test('can run with ipv6', () async {
- final testFile = dap.createTestFile(emptyProgram);
+ final testFile = dap.createTestFile(emptyProgram);
+ final outputEvents = await dap.client.collectOutput(file: testFile);
+ final vmServiceUri = _extractVmServiceUri(outputEvents.first);
+ expect(vmServiceUri.path, isNot(matches(vmServiceAuthCodePathPattern)));
+ });
- final outputEvents = await dap.client.collectOutput(file: testFile);
- final vmServiceUri = _extractVmServiceUri(outputEvents.first);
+ test('can run with ipv6', () async {
+ final dap = await DapTestSession.setUp(additionalArgs: ['--ipv6']);
+ addTearDown(dap.tearDown);
- // Check DAP server host.
- expect(dap.server.host, equals('::1'));
- // Check VM Service/DDS host.
- expect(vmServiceUri.host, equals('::1'));
- });
- // These tests can be slow due to starting up the external server process.
- }, timeout: Timeout.none);
- }, additionalArgs: ['--ipv6']);
+ final testFile = dap.createTestFile(emptyProgram);
+ final outputEvents = await dap.client.collectOutput(file: testFile);
+ final vmServiceUri = _extractVmServiceUri(outputEvents.first);
+
+ expect(vmServiceUri.host, equals('::1'));
+ });
+ // These tests can be slow due to starting up the external server process.
+ }, timeout: Timeout.none);
}
/// Extracts the VM Service URI from the "Connecting to ..." banner output by
@@ -122,15 +126,6 @@
Uri _extractVmServiceUri(OutputEventBody vmConnectionBanner) {
// TODO(dantup): Change this to use the dart.debuggerUris custom event
// if implemented (whch VS Code also needs).
- final vmServiceUriPattern = RegExp(r'Connecting to VM Service at ([^\s]+)\s');
final match = vmServiceUriPattern.firstMatch(vmConnectionBanner.output);
return Uri.parse(match!.group(1)!);
}
-
-/// Checks for the presence of an auth token in a VM Service URI in the
-/// "Connecting to VM Service" [OutputEvent].
-bool _hasAuthCode(OutputEventBody vmConnectionBanner) {
- final vmServiceUri = _extractVmServiceUri(vmConnectionBanner);
- final authCodePattern = RegExp(r'^/[\w=]{5,15}/ws');
- return authCodePattern.hasMatch(vmServiceUri.path);
-}
diff --git a/pkg/dds/test/dap/integration/debug_variables_test.dart b/pkg/dds/test/dap/integration/debug_variables_test.dart
index e04e36e..b5e357c 100644
--- a/pkg/dds/test/dap/integration/debug_variables_test.dart
+++ b/pkg/dds/test/dap/integration/debug_variables_test.dart
@@ -8,11 +8,16 @@
import 'test_support.dart';
main() {
- testDap((dap) async {
- group('debug mode variables', () {
- test('provides variable list for frames', () async {
- final client = dap.client;
- final testFile = await dap.createTestFile(r'''
+ late DapTestSession dap;
+ setUp(() async {
+ dap = await DapTestSession.setUp();
+ });
+ tearDown(() => dap.tearDown());
+
+ group('debug mode variables', () {
+ test('provides variable list for frames', () async {
+ final client = dap.client;
+ final testFile = await dap.createTestFile(r'''
void main(List<String> args) {
final myVariable = 1;
foo();
@@ -23,135 +28,135 @@
print('Hello!'); // BREAKPOINT
}
''');
- final breakpointLine = lineWith(testFile, '// BREAKPOINT');
+ final breakpointLine = lineWith(testFile, '// BREAKPOINT');
- final stop = await client.hitBreakpoint(testFile, breakpointLine);
- final stack = await client.getValidStack(
- stop.threadId!,
- startFrame: 0,
- numFrames: 2,
- );
+ final stop = await client.hitBreakpoint(testFile, breakpointLine);
+ final stack = await client.getValidStack(
+ stop.threadId!,
+ startFrame: 0,
+ numFrames: 2,
+ );
- // Check top two frames (in `foo` and in `main`).
- await client.expectScopeVariables(
- stack.stackFrames[0].id, // Top frame: foo
- 'Variables',
- '''
+ // Check top two frames (in `foo` and in `main`).
+ await client.expectScopeVariables(
+ stack.stackFrames[0].id, // Top frame: foo
+ 'Variables',
+ '''
b: 2
''',
- );
- await client.expectScopeVariables(
- stack.stackFrames[1].id, // Second frame: main
- 'Variables',
- '''
+ );
+ await client.expectScopeVariables(
+ stack.stackFrames[1].id, // Second frame: main
+ 'Variables',
+ '''
args: List (0 items)
myVariable: 1
''',
- );
- });
+ );
+ });
- test('provides simple exception types for frames', () async {
- final client = dap.client;
- final testFile = await dap.createTestFile(r'''
+ test('provides simple exception types for frames', () async {
+ final client = dap.client;
+ final testFile = await dap.createTestFile(r'''
void main(List<String> args) {
throw 'my error';
}
''');
- final stop = await client.hitException(testFile);
- final stack = await client.getValidStack(
- stop.threadId!,
- startFrame: 0,
- numFrames: 1,
- );
- final topFrameId = stack.stackFrames.first.id;
+ final stop = await client.hitException(testFile);
+ final stack = await client.getValidStack(
+ stop.threadId!,
+ startFrame: 0,
+ numFrames: 1,
+ );
+ final topFrameId = stack.stackFrames.first.id;
- // Check for an additional Scope named "Exceptions" that includes the
- // exception.
- await client.expectScopeVariables(
- topFrameId,
- 'Exceptions',
- '''
+ // Check for an additional Scope named "Exceptions" that includes the
+ // exception.
+ await client.expectScopeVariables(
+ topFrameId,
+ 'Exceptions',
+ '''
String: "my error"
''',
- );
- });
+ );
+ });
- test('provides complex exception types frames', () async {
- final client = dap.client;
- final testFile = await dap.createTestFile(r'''
+ test('provides complex exception types frames', () async {
+ final client = dap.client;
+ final testFile = await dap.createTestFile(r'''
void main(List<String> args) {
throw ArgumentError.notNull('args');
}
''');
- final stop = await client.hitException(testFile);
- final stack = await client.getValidStack(
- stop.threadId!,
- startFrame: 0,
- numFrames: 1,
- );
- final topFrameId = stack.stackFrames.first.id;
+ final stop = await client.hitException(testFile);
+ final stack = await client.getValidStack(
+ stop.threadId!,
+ startFrame: 0,
+ numFrames: 1,
+ );
+ final topFrameId = stack.stackFrames.first.id;
- // Check for an additional Scope named "Exceptions" that includes the
- // exception.
- await client.expectScopeVariables(
- topFrameId,
- 'Exceptions',
- // TODO(dantup): evaluateNames
- '''
+ // Check for an additional Scope named "Exceptions" that includes the
+ // exception.
+ await client.expectScopeVariables(
+ topFrameId,
+ 'Exceptions',
+ // TODO(dantup): evaluateNames
+ '''
invalidValue: null
message: "Must not be null"
name: "args"
''',
- );
- });
+ );
+ });
- test('includes simple variable fields', () async {
- final client = dap.client;
- final testFile = await dap.createTestFile(r'''
+ test('includes simple variable fields', () async {
+ final client = dap.client;
+ final testFile = await dap.createTestFile(r'''
void main(List<String> args) {
final myVariable = DateTime(2000, 1, 1);
print('Hello!'); // BREAKPOINT
}
''');
- final breakpointLine = lineWith(testFile, '// BREAKPOINT');
+ final breakpointLine = lineWith(testFile, '// BREAKPOINT');
- final stop = await client.hitBreakpoint(testFile, breakpointLine);
- await client.expectLocalVariable(
- stop.threadId!,
- expectedName: 'myVariable',
- expectedDisplayString: 'DateTime',
- expectedVariables: '''
+ final stop = await client.hitBreakpoint(testFile, breakpointLine);
+ await client.expectLocalVariable(
+ stop.threadId!,
+ expectedName: 'myVariable',
+ expectedDisplayString: 'DateTime',
+ expectedVariables: '''
isUtc: false
''',
- );
- });
+ );
+ });
- test('includes variable getters when evaluateGettersInDebugViews=true',
- () async {
- final client = dap.client;
- final testFile = await dap.createTestFile(r'''
+ test('includes variable getters when evaluateGettersInDebugViews=true',
+ () async {
+ final client = dap.client;
+ final testFile = await dap.createTestFile(r'''
void main(List<String> args) {
final myVariable = DateTime(2000, 1, 1);
print('Hello!'); // BREAKPOINT
}
''');
- final breakpointLine = lineWith(testFile, '// BREAKPOINT');
+ final breakpointLine = lineWith(testFile, '// BREAKPOINT');
- final stop = await client.hitBreakpoint(
- testFile,
- breakpointLine,
- launch: () => client.launch(
- testFile.path,
- evaluateGettersInDebugViews: true,
- ),
- );
- await client.expectLocalVariable(
- stop.threadId!,
- expectedName: 'myVariable',
- expectedDisplayString: 'DateTime',
- expectedVariables: '''
+ final stop = await client.hitBreakpoint(
+ testFile,
+ breakpointLine,
+ launch: () => client.launch(
+ testFile.path,
+ evaluateGettersInDebugViews: true,
+ ),
+ );
+ await client.expectLocalVariable(
+ stop.threadId!,
+ expectedName: 'myVariable',
+ expectedDisplayString: 'DateTime',
+ expectedVariables: '''
day: 1
hour: 0
isUtc: false
@@ -165,72 +170,71 @@
weekday: 6
year: 2000
''',
- ignore: {
- // Don't check fields that may very based on timezone as it'll make
- // these tests fragile, and this isn't really what's being tested.
- 'timeZoneName',
- 'microsecondsSinceEpoch',
- 'millisecondsSinceEpoch',
- },
- );
- });
+ ignore: {
+ // Don't check fields that may very based on timezone as it'll make
+ // these tests fragile, and this isn't really what's being tested.
+ 'timeZoneName',
+ 'microsecondsSinceEpoch',
+ 'millisecondsSinceEpoch',
+ },
+ );
+ });
- test('renders a simple list', () async {
- final client = dap.client;
- final testFile = await dap.createTestFile(r'''
+ test('renders a simple list', () async {
+ final client = dap.client;
+ final testFile = await dap.createTestFile(r'''
void main(List<String> args) {
final myVariable = ["first", "second", "third"];
print('Hello!'); // BREAKPOINT
}
''');
- final breakpointLine = lineWith(testFile, '// BREAKPOINT');
+ final breakpointLine = lineWith(testFile, '// BREAKPOINT');
- final stop = await client.hitBreakpoint(testFile, breakpointLine);
- await client.expectLocalVariable(
- stop.threadId!,
- expectedName: 'myVariable',
- expectedDisplayString: 'List (3 items)',
- // TODO(dantup): evaluateNames
- expectedVariables: '''
+ final stop = await client.hitBreakpoint(testFile, breakpointLine);
+ await client.expectLocalVariable(
+ stop.threadId!,
+ expectedName: 'myVariable',
+ expectedDisplayString: 'List (3 items)',
+ // TODO(dantup): evaluateNames
+ expectedVariables: '''
0: "first"
1: "second"
2: "third"
''',
- );
- });
+ );
+ });
- test('renders a simple list subset', () async {
- final client = dap.client;
- final testFile = await dap.createTestFile(r'''
+ test('renders a simple list subset', () async {
+ final client = dap.client;
+ final testFile = await dap.createTestFile(r'''
void main(List<String> args) {
final myVariable = ["first", "second", "third"];
print('Hello!'); // BREAKPOINT
}
''');
- final breakpointLine = lineWith(testFile, '// BREAKPOINT');
+ final breakpointLine = lineWith(testFile, '// BREAKPOINT');
- final stop = await client.hitBreakpoint(testFile, breakpointLine);
- await client.expectLocalVariable(
- stop.threadId!,
- expectedName: 'myVariable',
- expectedDisplayString: 'List (3 items)',
- // TODO(dantup): evaluateNames
- expectedVariables: '''
+ final stop = await client.hitBreakpoint(testFile, breakpointLine);
+ await client.expectLocalVariable(
+ stop.threadId!,
+ expectedName: 'myVariable',
+ expectedDisplayString: 'List (3 items)',
+ // TODO(dantup): evaluateNames
+ expectedVariables: '''
1: "second"
''',
- start: 1,
- count: 1,
- );
- });
+ start: 1,
+ count: 1,
+ );
+ });
- test('renders a simple map', () {
- // TODO(dantup): Implement this (inc evaluateNames)
- }, skip: true);
+ test('renders a simple map', () {
+ // TODO(dantup): Implement this (inc evaluateNames)
+ }, skip: true);
- test('renders a simple map subset', () {
- // TODO(dantup): Implement this (inc evaluateNames)
- }, skip: true);
- // These tests can be slow due to starting up the external server process.
- }, timeout: Timeout.none);
- });
+ test('renders a simple map subset', () {
+ // TODO(dantup): Implement this (inc evaluateNames)
+ }, skip: true);
+ // These tests can be slow due to starting up the external server process.
+ }, timeout: Timeout.none);
}
diff --git a/pkg/dds/test/dap/integration/no_debug_test.dart b/pkg/dds/test/dap/integration/no_debug_test.dart
index e9f5dd2..bb0af1d 100644
--- a/pkg/dds/test/dap/integration/no_debug_test.dart
+++ b/pkg/dds/test/dap/integration/no_debug_test.dart
@@ -4,13 +4,19 @@
import 'package:test/test.dart';
+import 'test_client.dart';
import 'test_support.dart';
main() {
- testDap((dap) async {
- group('noDebug mode', () {
- test('runs a simple script', () async {
- final testFile = dap.createTestFile(r'''
+ late DapTestSession dap;
+ setUp(() async {
+ dap = await DapTestSession.setUp();
+ });
+ tearDown(() => dap.tearDown());
+
+ group('noDebug mode', () {
+ test('runs a simple script', () async {
+ final testFile = dap.createTestFile(r'''
void main(List<String> args) async {
print('Hello!');
print('World!');
@@ -18,24 +24,23 @@
}
''');
- final outputEvents = await dap.client.collectOutput(
- launch: () => dap.client.launch(
- testFile.path,
- noDebug: true,
- args: ['one', 'two'],
- ),
- );
+ final outputEvents = await dap.client.collectOutput(
+ launch: () => dap.client.launch(
+ testFile.path,
+ noDebug: true,
+ args: ['one', 'two'],
+ ),
+ );
- final output = outputEvents.map((e) => e.output).join();
- expectLines(output, [
- 'Hello!',
- 'World!',
- 'args: [one, two]',
- '',
- 'Exited.',
- ]);
- });
- // These tests can be slow due to starting up the external server process.
- }, timeout: Timeout.none);
- });
+ final output = outputEvents.map((e) => e.output).join();
+ expectLines(output, [
+ 'Hello!',
+ 'World!',
+ 'args: [one, two]',
+ '',
+ 'Exited.',
+ ]);
+ });
+ // These tests can be slow due to starting up the external server process.
+ }, timeout: Timeout.none);
}
diff --git a/pkg/dds/test/dap/integration/test_client.dart b/pkg/dds/test/dap/integration/test_client.dart
index c130e00..bfa05c6 100644
--- a/pkg/dds/test/dap/integration/test_client.dart
+++ b/pkg/dds/test/dap/integration/test_client.dart
@@ -10,7 +10,6 @@
import 'package:dds/src/dap/logging.dart';
import 'package:dds/src/dap/protocol_generated.dart';
import 'package:dds/src/dap/protocol_stream.dart';
-import 'package:dds/src/dap/protocol_stream_transformers.dart';
import 'package:test/test.dart';
import 'package:vm_service/vm_service.dart' as vm;
@@ -22,19 +21,17 @@
/// Methods on this class should map directly to protocol methods. Additional
/// helpers are available in [DapTestClientExtension].
class DapTestClient {
- final Socket _socket;
final ByteStreamServerChannel _channel;
late final StreamSubscription<String> _subscription;
final Logger? _logger;
final bool captureVmServiceTraffic;
- final _requestWarningDuration = const Duration(seconds: 2);
+ final _requestWarningDuration = const Duration(seconds: 5);
final Map<int, _OutgoingRequest> _pendingRequests = {};
final _eventController = StreamController<Event>.broadcast();
int _seq = 1;
DapTestClient._(
- this._socket,
this._channel,
this._logger, {
this.captureVmServiceTraffic = false,
@@ -57,21 +54,6 @@
Stream<OutputEventBody> get outputEvents => events('output')
.map((e) => OutputEventBody.fromJson(e.body as Map<String, Object?>));
- /// Collects all output events until the program terminates.
- Future<List<OutputEventBody>> collectOutput(
- {File? file, Future<Response> Function()? launch}) async {
- final outputEventsFuture = outputEvents.toList();
-
- // Launch script and wait for termination.
- await Future.wait([
- event('terminated'),
- initialize(),
- launch?.call() ?? this.launch(file!.path),
- ], eagerError: true);
-
- return outputEventsFuture;
- }
-
/// Sends a continue request for the given thread.
///
/// Returns a Future that completes when the server returns a corresponding
@@ -210,6 +192,19 @@
sendRequest(StackTraceArguments(
threadId: threadId, startFrame: startFrame, levels: numFrames));
+ /// Initializes the debug adapter and launches [file] or calls the custom
+ /// [launch] method.
+ Future<void> start({
+ File? file,
+ Future<Response> Function()? launch,
+ }) {
+ // Launch script and wait for termination.
+ return Future.wait([
+ initialize(),
+ launch?.call() ?? this.launch(file!.path),
+ ], eagerError: true);
+ }
+
/// Sends a stepIn request for the given thread.
///
/// Returns a Future that completes when the server returns a corresponding
@@ -226,7 +221,6 @@
Future<void> stop() async {
_channel.close();
- await _socket.close();
await _subscription.cancel();
}
@@ -305,16 +299,12 @@
/// Creates a [DapTestClient] that connects the server listening on
/// [host]:[port].
static Future<DapTestClient> connect(
- String host,
- int port, {
+ DapTestServer server, {
bool captureVmServiceTraffic = false,
Logger? logger,
}) async {
- final socket = await Socket.connect(host, port);
- final channel = ByteStreamServerChannel(
- socket.transform(Uint8ListTransformer()), socket, logger);
-
- return DapTestClient._(socket, channel, logger,
+ final channel = ByteStreamServerChannel(server.stream, server.sink, logger);
+ return DapTestClient._(channel, logger,
captureVmServiceTraffic: captureVmServiceTraffic);
}
}
@@ -441,6 +431,21 @@
return ThreadsResponseBody.fromJson(response.body as Map<String, Object?>);
}
+ /// Collects all output events until the program terminates.
+ ///
+ /// These results include all events in the order they are recieved, including
+ /// console, stdout and stderr.
+ Future<List<OutputEventBody>> collectOutput({
+ File? file,
+ Future<Response> Function()? launch,
+ }) async {
+ final outputEventsFuture = outputEvents.toList();
+
+ await start(file: file, launch: launch);
+
+ return outputEventsFuture;
+ }
+
/// A helper that fetches scopes for a frame, checks for one with the name
/// [expectedName] and verifies its variables.
Future<Scope> expectScopeVariables(
diff --git a/pkg/dds/test/dap/integration/test_server.dart b/pkg/dds/test/dap/integration/test_server.dart
index c2a11f7..dc96dc7 100644
--- a/pkg/dds/test/dap/integration/test_server.dart
+++ b/pkg/dds/test/dap/integration/test_server.dart
@@ -13,10 +13,9 @@
import 'package:pedantic/pedantic.dart';
abstract class DapTestServer {
- List<String> get errorLogs;
- String get host;
- int get port;
Future<void> stop();
+ StreamSink<List<int>> get sink;
+ Stream<List<int>> get stream;
}
/// An instance of a DAP server running in-process (to aid debugging).
@@ -25,22 +24,27 @@
/// serialized and deserialized but it's not quite the same running out of
/// process.
class InProcessDapTestServer extends DapTestServer {
- final DapServer _server;
+ late final DapServer _server;
+ final stdinController = StreamController<List<int>>();
+ final stdoutController = StreamController<List<int>>();
- InProcessDapTestServer._(this._server);
+ StreamSink<List<int>> get sink => stdinController.sink;
+ Stream<List<int>> get stream => stdoutController.stream;
- String get host => _server.host;
- int get port => _server.port;
- List<String> get errorLogs => const []; // In-proc errors just throw in-line.
+ InProcessDapTestServer._() {
+ _server = DapServer(stdinController.stream, stdoutController.sink);
+ }
@override
Future<void> stop() async {
- await _server.stop();
+ _server.stop();
}
- static Future<InProcessDapTestServer> create({Logger? logger}) async {
- final DapServer server = await DapServer.create(logger: logger);
- return InProcessDapTestServer._(server);
+ static Future<InProcessDapTestServer> create({
+ Logger? logger,
+ List<String>? additionalArgs,
+ }) async {
+ return InProcessDapTestServer._();
}
}
@@ -52,28 +56,22 @@
class OutOfProcessDapTestServer extends DapTestServer {
var _isShuttingDown = false;
final Process _process;
- final int port;
- final String host;
- final List<String> _errors = [];
- List<String> get errorLogs => _errors;
+ StreamSink<List<int>> get sink => _process.stdin;
+ Stream<List<int>> get stream => _process.stdout;
OutOfProcessDapTestServer._(
this._process,
- this.host,
- this.port,
Logger? logger,
) {
// Treat anything written to stderr as the DAP crashing and fail the test.
_process.stderr.transform(utf8.decoder).listen((error) {
logger?.call(error);
- _errors.add(error);
throw error;
});
unawaited(_process.exitCode.then((code) {
final message = 'Out-of-process DAP server terminated with code $code';
logger?.call(message);
- _errors.add(message);
if (!_isShuttingDown && code != 0) {
throw message;
}
@@ -107,27 +105,6 @@
],
);
- final startedCompleter = Completer<void>();
- late String host;
- late int port;
-
- // Scrape the `started` event to get the host/port. Any other output
- // should be sent to the logger (as it may be verbose output for diagnostic
- // purposes).
- _process.stdout.transform(utf8.decoder).listen((text) {
- if (!startedCompleter.isCompleted) {
- final event = jsonDecode(text);
- if (event['state'] == 'started') {
- host = event['dapHost'];
- port = event['dapPort'];
- startedCompleter.complete();
- return;
- }
- }
- logger?.call(text);
- });
- await startedCompleter.future;
-
- return OutOfProcessDapTestServer._(_process, host, port, logger);
+ return OutOfProcessDapTestServer._(_process, logger);
}
}
diff --git a/pkg/dds/test/dap/integration/test_support.dart b/pkg/dds/test/dap/integration/test_support.dart
index 45460b2..a44a791 100644
--- a/pkg/dds/test/dap/integration/test_support.dart
+++ b/pkg/dds/test/dap/integration/test_support.dart
@@ -12,20 +12,6 @@
import 'test_client.dart';
import 'test_server.dart';
-/// A logger to use to log all traffic (both DAP and VM) to stdout.
-///
-/// If the enviroment variable is `DAP_TEST_VERBOSE` then `print` will be used,
-/// otherwise there will be no verbose logging.
-///
-/// DAP_TEST_VERBOSE=true pub run test --chain-stack-traces test/dap/integration
-///
-///
-/// When using the out-of-process DAP, this causes `--verbose` to be passed to
-/// the server which causes it to write all traffic to `stdout` which is then
-/// picked up by [OutOfProcessDapTestServer] and passed to this logger.
-final logger =
- Platform.environment['DAP_TEST_VERBOSE'] == 'true' ? print : null;
-
/// Whether to run the DAP server in-process with the tests, or externally in
/// another process.
///
@@ -35,6 +21,14 @@
/// simplified in VS Code by using a launch config with custom CodeLens links).
final useInProcessDap = Platform.environment['DAP_TEST_INTERNAL'] == 'true';
+/// A [RegExp] that matches the `path` part of a VM Service URI that contains
+/// an authentication token.
+final vmServiceAuthCodePathPattern = RegExp(r'^/[\w_\-=]{5,15}/ws$');
+
+/// A [RegExp] that matches the "Connecting to VM Service" banner that is sent
+/// as the first output event for a debug session.
+final vmServiceUriPattern = RegExp(r'Connecting to VM Service at ([^\s]+)\s');
+
/// Expects [actual] to equal the lines [expected], ignoring differences in line
/// endings.
void expectLines(String actual, List<String> expected) {
@@ -45,33 +39,13 @@
int lineWith(File file, String searchText) =>
file.readAsLinesSync().indexWhere((line) => line.contains(searchText)) + 1;
-/// A helper function to wrap all tests in a library with setup/teardown functions
-/// to start a shared server for all tests in the library and an individual
-/// client for each test.
-testDap(
- Future<void> Function(DapTestSession session) tests, {
- List<String>? additionalArgs,
-}) {
- final session = DapTestSession(additionalArgs: additionalArgs);
-
- setUpAll(session.setUpAll);
- tearDownAll(session.tearDownAll);
- setUp(session.setUp);
- tearDown(session.tearDown);
-
- return tests(session);
-}
-
-/// A helper class provided to DAP integration tests run with [testDap] to
-/// easily share setup/teardown without sharing state across tests from different
-/// files.
+/// A helper class containing the DAP server/client for DAP integration tests.
class DapTestSession {
- late DapTestServer server;
- late DapTestClient client;
+ DapTestServer server;
+ DapTestClient client;
final _testFolders = <Directory>[];
- final List<String>? additionalArgs;
- DapTestSession({this.additionalArgs});
+ DapTestSession._(this.server, this.client);
/// Creates a file in a temporary folder to be used as an application for testing.
///
@@ -84,60 +58,32 @@
return testFile;
}
- Future<void> setUp() async {
- client = await _startClient(server);
+ static Future<DapTestSession> setUp({List<String>? additionalArgs}) async {
+ final server = await _startServer(additionalArgs: additionalArgs);
+ final client = await DapTestClient.connect(server);
+ return DapTestSession._(server, client);
}
- Future<void> setUpAll() async {
- server = await _startServer(logger: logger, additionalArgs: additionalArgs);
- }
-
- Future<void> tearDown() => client.stop();
-
- Future<void> tearDownAll() async {
+ Future<void> tearDown() async {
+ await client.stop();
await server.stop();
// Clean up any temp folders created during the test runs.
- _testFolders.forEach((dir) => dir.deleteSync(recursive: true));
- }
-
- /// Creates and connects a new [DapTestClient] to [server].
- Future<DapTestClient> _startClient(DapTestServer server) async {
- // Since we don't get a signal from the DAP server when it's ready and we
- // just started it, add a short retry to connections.
- // Since the bots can be quite slow, it may take 6-7 seconds for the server
- // to initially start up (including compilation).
- var attempt = 1;
- while (attempt++ <= 100) {
- try {
- return await DapTestClient.connect(server.host, server.port);
- } catch (e) {
- await Future.delayed(const Duration(milliseconds: 200));
- }
- }
-
- final errorMessage = StringBuffer();
- errorMessage.writeln(
- 'Failed to connect to DAP server on port ${server.port}'
- ' after $attempt attempts. Did the server start correctly?',
- );
-
- final serverErrorLogs = server.errorLogs;
- if (serverErrorLogs.isNotEmpty) {
- errorMessage.writeln('Server errors:');
- errorMessage.writeAll(serverErrorLogs);
- }
-
- throw Exception(errorMessage.toString());
+ _testFolders
+ ..forEach((dir) => dir.deleteSync(recursive: true))
+ ..clear();
}
/// Starts a DAP server that can be shared across tests.
- Future<DapTestServer> _startServer({
+ static Future<DapTestServer> _startServer({
Logger? logger,
List<String>? additionalArgs,
}) async {
return useInProcessDap
- ? await InProcessDapTestServer.create(logger: logger)
+ ? await InProcessDapTestServer.create(
+ logger: logger,
+ additionalArgs: additionalArgs,
+ )
: await OutOfProcessDapTestServer.create(
logger: logger,
additionalArgs: additionalArgs,
diff --git a/pkg/dds/test/handles_client_disconnect_state_error_test.dart b/pkg/dds/test/handles_client_disconnect_state_error_test.dart
index 816703b..c9d35fa 100644
--- a/pkg/dds/test/handles_client_disconnect_state_error_test.dart
+++ b/pkg/dds/test/handles_client_disconnect_state_error_test.dart
@@ -9,7 +9,6 @@
import 'package:dds/src/rpc_error_codes.dart';
import 'package:json_rpc_2/json_rpc_2.dart' as json_rpc;
import 'package:pedantic/pedantic.dart';
-import 'package:test/fake.dart';
import 'package:test/test.dart';
import 'package:web_socket_channel/web_socket_channel.dart';
@@ -42,19 +41,6 @@
}
}
-class FakeWebSocketSink extends Fake implements WebSocketSink {
- @override
- Future close([int? closeCode, String? closeReason]) {
- // Do nothing.
- return Future.value();
- }
-}
-
-class FakeWebSocketChannel extends Fake implements WebSocketChannel {
- @override
- WebSocketSink get sink => FakeWebSocketSink();
-}
-
void main() {
webSocketBuilder = (Uri _) => FakeWebSocketChannel();
peerBuilder =
diff --git a/pkg/dds/test/handles_shutdown_before_startup_test.dart b/pkg/dds/test/handles_shutdown_before_startup_test.dart
new file mode 100644
index 0000000..ae1b06a
--- /dev/null
+++ b/pkg/dds/test/handles_shutdown_before_startup_test.dart
@@ -0,0 +1,54 @@
+// 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.
+
+import 'dart:async';
+
+import 'package:dds/dds.dart';
+import 'package:dds/src/dds_impl.dart';
+import 'package:test/test.dart';
+import 'package:web_socket_channel/web_socket_channel.dart';
+
+import 'common/fakes.dart';
+
+class ImmediatelyClosedPeer extends FakePeer {
+ // Immediately complete the returned future to act as if we've closed.
+ @override
+ Future<void> listen() => Future.value();
+}
+
+class ImmediatelyClosedErrorPeer extends FakePeer {
+ // Immediately complete the returned future with an error to act as if we've
+ // encountered a connection issue.
+ @override
+ Future<void> listen() => Future.error('Connection lost');
+}
+
+// Regression test for https://github.com/flutter/flutter/issues/86361.
+void main() {
+ webSocketBuilder = (Uri _) => FakeWebSocketChannel();
+
+ test('Shutdown before server startup complete', () async {
+ peerBuilder =
+ (WebSocketChannel _, dynamic __) async => ImmediatelyClosedPeer();
+ try {
+ await DartDevelopmentService.startDartDevelopmentService(
+ Uri(scheme: 'http'),
+ );
+ } on DartDevelopmentServiceException {
+ /* We expect to fail to start */
+ }
+ });
+
+ test('Error shutdown before server startup complete', () async {
+ peerBuilder =
+ (WebSocketChannel _, dynamic __) async => ImmediatelyClosedErrorPeer();
+ try {
+ await DartDevelopmentService.startDartDevelopmentService(
+ Uri(scheme: 'http'),
+ );
+ } on DartDevelopmentServiceException {
+ /* We expect to fail to start */
+ }
+ });
+}
diff --git a/pkg/dds/tool/dap/run_server.dart b/pkg/dds/tool/dap/run_server.dart
index 5fd19f2..cfddd48 100644
--- a/pkg/dds/tool/dap/run_server.dart
+++ b/pkg/dds/tool/dap/run_server.dart
@@ -2,7 +2,7 @@
// 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.
-import 'dart:convert';
+import 'dart:async';
import 'dart:io';
import 'package:args/command_runner.dart';
@@ -12,7 +12,7 @@
// TODO(dantup): "dap_tool" is a placeholder and will likely eventually be a
// "dart" command.
final runner = CommandRunner('dap_tool', 'Dart DAP Tool')
- ..addCommand(DapCommand());
+ ..addCommand(DapCommand(stdin, stdout.nonBlocking));
try {
await runner.run(arguments);
@@ -23,33 +23,22 @@
}
class DapCommand extends Command {
- static const argHost = 'host';
- static const argPort = 'port';
static const argIpv6 = 'ipv6';
static const argDds = 'dds';
static const argAuthCodes = 'auth-codes';
static const argVerbose = 'verbose';
+ final Stream<List<int>> _inputStream;
+ final StreamSink<List<int>> _outputSink;
+
@override
final String description = 'Start a DAP debug server.';
@override
final String name = 'dap';
- DapCommand() {
+ DapCommand(this._inputStream, this._outputSink) {
argParser
- ..addOption(
- argHost,
- help: 'The hostname/IP to bind the server to. If not supplied, will'
- ' use the appropriate loopback address depending on whether'
- ' --ipv6 is set',
- )
- ..addOption(
- argPort,
- abbr: 'p',
- defaultsTo: '0',
- help: 'The port to bind the server to',
- )
..addFlag(
argIpv6,
help: 'Whether to bind DAP/VM Service/DDS to IPv6 addresses',
@@ -63,33 +52,21 @@
argAuthCodes,
defaultsTo: true,
help: 'Whether to enable authentication codes for VM Services',
- )
- ..addFlag(
- argVerbose,
- abbr: 'v',
- help: 'Whether to print diagnostic output to stdout',
);
}
Future<void> run() async {
final args = argResults!;
- final port = int.parse(args[argPort]);
- final host = args[argHost];
final ipv6 = args[argIpv6] as bool;
- final server = await DapServer.create(
- host: host,
- port: port,
+ final server = DapServer(
+ _inputStream,
+ _outputSink,
ipv6: ipv6,
- enableDdds: args[argDds],
+ enableDds: args[argDds],
enableAuthCodes: args[argAuthCodes],
- logger: args[argVerbose] ? print : null,
);
- stdout.write(jsonEncode({
- 'state': 'started',
- 'dapHost': server.host,
- 'dapPort': server.port,
- }));
+ await server.channel.closed;
}
}
diff --git a/pkg/dev_compiler/lib/src/kernel/asset_file_system.dart b/pkg/dev_compiler/lib/src/kernel/asset_file_system.dart
index 4d73fb2..54fd3b5 100644
--- a/pkg/dev_compiler/lib/src/kernel/asset_file_system.dart
+++ b/pkg/dev_compiler/lib/src/kernel/asset_file_system.dart
@@ -16,11 +16,18 @@
/// A wrapper around asset server that redirects file read requests
/// to http get requests to the asset server.
class AssetFileSystem implements FileSystem {
- FileSystem original;
+ final FileSystem original;
final String server;
final String port;
+ final RetryTimeoutClient client;
- AssetFileSystem(this.original, this.server, this.port);
+ AssetFileSystem(this.original, this.server, this.port)
+ : client = RetryTimeoutClient(
+ HttpClient()
+ ..maxConnectionsPerHost = 200
+ ..connectionTimeout = const Duration(seconds: 30)
+ ..idleTimeout = const Duration(seconds: 30),
+ retries: 4);
/// Convert the uri to a server uri.
Uri _resourceUri(Uri uri) => Uri.parse('http://$server:$port/${uri.path}');
@@ -34,6 +41,10 @@
// Pass the uri to the asset server in the debugger.
return AssetFileSystemEntity(this, _resourceUri(uri));
}
+
+ void close() {
+ client?.close(force: true);
+ }
}
class AssetFileSystemEntity implements FileSystemEntity {
@@ -85,20 +96,16 @@
});
}
- /// Execute the [body] with the new http client.
+ /// Execute the [body] with the http client created in [fileSystem].
///
/// Throws a [FileSystemException] on failure,
/// and cleans up the client on return or error.
Future<T> _runWithClient<T>(
Future<T> Function(RetryTimeoutClient httpClient) body) async {
- RetryTimeoutClient httpClient;
try {
- httpClient = RetryTimeoutClient(HttpClient(), retries: 4);
- return await body(httpClient);
+ return await body(fileSystem.client);
} on Exception catch (e, s) {
throw FileSystemException(uri, '$e:$s');
- } finally {
- httpClient?.close(force: true);
}
}
diff --git a/pkg/dev_compiler/lib/src/kernel/command.dart b/pkg/dev_compiler/lib/src/kernel/command.dart
index c0e4c51..408d757 100644
--- a/pkg/dev_compiler/lib/src/kernel/command.dart
+++ b/pkg/dev_compiler/lib/src/kernel/command.dart
@@ -18,6 +18,7 @@
import 'package:kernel/kernel.dart';
import 'package:kernel/target/targets.dart';
import 'package:kernel/text/ast_to_text.dart' as kernel show Printer;
+import 'package:kernel/text/debug_printer.dart';
import 'package:path/path.dart' as p;
import 'package:source_maps/source_maps.dart' show SourceMapBuilder;
@@ -88,7 +89,7 @@
..addOption('packages', help: 'The package spec file to use.')
// TODO(jmesserly): is this still useful for us, or can we remove it now?
..addFlag('summarize-text',
- help: 'Emit API summary in a .js.txt file.',
+ help: 'Emit API summary and AST in .js.txt and .ast.xml files.',
defaultsTo: false,
hide: true)
..addFlag('track-widget-creation',
@@ -413,6 +414,8 @@
var sb = StringBuffer();
kernel.Printer(sb).writeComponentFile(component);
outFiles.add(File(outPaths.first + '.txt').writeAsString(sb.toString()));
+ outFiles.add(File(outPaths.first.split('.')[0] + '.ast.xml')
+ .writeAsString(DebugPrinter.prettyPrint(compiledLibraries)));
}
final importToSummary = Map<Library, Component>.identity();
@@ -729,7 +732,8 @@
: null;
var debugSymbols = emitDebugSymbols
- ? _emitSymbols(compiler, nameListener.identifierNames, component)
+ ? _emitSymbols(
+ compiler, moduleTree.name, nameListener.identifierNames, component)
: null;
return JSCode(text, builtMap, symbols: debugSymbols, metadata: debugMetadata);
@@ -741,19 +745,23 @@
/// Uses information from the [compiler] used to compile the JS module combined
/// with [identifierNames] that maps JavaScript identifier nodes to their actual
/// names used when outputting the JavaScript.
-ModuleSymbols _emitSymbols(ProgramCompiler compiler,
+ModuleSymbols _emitSymbols(ProgramCompiler compiler, String moduleName,
Map<js_ast.Identifier, String> identifierNames, Component component) {
var classJsNames = <Class, String>{
for (var e in compiler.classIdentifiers.entries)
e.key: identifierNames[e.value],
};
+ var procedureJsNames = <Procedure, String>{
+ for (var e in compiler.procedureIdentifiers.entries)
+ e.key: identifierNames[e.value],
+ };
var variableJsNames = <VariableDeclaration, String>{
for (var e in compiler.variableIdentifiers.entries)
e.key: identifierNames[e.value],
};
- return ModuleSymbolsCollector(
- classJsNames, compiler.memberNames, variableJsNames)
+ return ModuleSymbolsCollector(moduleName, classJsNames, compiler.memberNames,
+ procedureJsNames, variableJsNames)
.collectSymbolInfo(component);
}
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index c11ced8..e777ddf 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -61,6 +61,13 @@
/// module.
final memberNames = <Member, String>{};
+ /// Maps each `Procedure` node compiled in the module to the `Identifier`s
+ /// used to name the class in JavaScript.
+ ///
+ /// This mapping is used when generating the symbol information for the
+ /// module.
+ final procedureIdentifiers = <Procedure, js_ast.Identifier>{};
+
/// Maps each `VariableDeclaration` node compiled in the module to the name
/// used for the variable in JavaScript.
///
@@ -1670,7 +1677,7 @@
ctorFields = ctor.initializers
.map((c) => c is FieldInitializer ? c.field : null)
.toSet()
- ..remove(null);
+ ..remove(null);
}
var body = <js_ast.Statement>[];
@@ -2368,8 +2375,9 @@
Class memberClass}) {
// Static members skip the rename steps and may require JS interop renames.
if (isStatic) {
- // TODO(nshahan) Record the name for this member in memberNames.
- return _emitStaticMemberName(name, member);
+ var memberName = _emitStaticMemberName(name, member);
+ memberNames[member] = memberName.valueWithoutQuotes;
+ return memberName;
}
// We allow some (illegal in Dart) member names to be used in our private
@@ -2379,6 +2387,7 @@
var runtimeName = _jsExportName(member);
if (runtimeName != null) {
var parts = runtimeName.split('.');
+ // TODO(nshahan) Record the name for this member in memberNames.
if (parts.length < 2) return propertyName(runtimeName);
js_ast.Expression result = _emitIdentifier(parts[0]);
@@ -2652,8 +2661,9 @@
_currentUri = node.fileUri;
var name = node.name.text;
+ memberNames[node] = name;
var result = js_ast.Method(
- propertyName(name), _emitFunction(node.function, node.name.text),
+ propertyName(name), _emitFunction(node.function, name),
isGetter: node.isGetter, isSetter: node.isSetter)
..sourceInformation = _nodeEnd(node.fileEndOffset);
@@ -2678,8 +2688,10 @@
var nameExpr = _emitTopLevelName(p);
var jsName = _safeFunctionNameForSafari(p.name.text, fn);
- body.add(js.statement('# = #',
- [nameExpr, js_ast.NamedFunction(_emitTemporaryId(jsName), fn)]));
+ var functionName = _emitTemporaryId(jsName);
+ procedureIdentifiers[p] = functionName;
+ body.add(js.statement(
+ '# = #', [nameExpr, js_ast.NamedFunction(functionName, fn)]));
_currentUri = savedUri;
_staticTypeContext.leaveMember(p);
@@ -2872,27 +2884,15 @@
js_ast.Expression typeRep;
// Type parameters don't matter as JS interop types cannot be reified.
- // We have to use lazy JS types because until we have proper module
- // loading for JS libraries bundled with Dart libraries, we will sometimes
- // need to load Dart libraries before the corresponding JS libraries are
- // actually loaded.
- // Given a JS type such as:
- // @JS('google.maps.Location')
- // class Location { ... }
- // We can't emit a reference to MyType because the JS library that defines
- // it may be loaded after our code. So for now, we use a special lazy type
- // object to represent MyType.
- // Anonymous JS types do not have a corresponding concrete JS type so we
- // have to use a helper to define them.
- if (isJSAnonymousType(c)) {
- typeRep = runtimeCall(
- 'anonymousJSType(#)', [js.escapedString(getLocalClassName(c))]);
- } else {
- var jsName = _emitJsNameWithoutGlobal(c);
- if (jsName != null) {
- typeRep = runtimeCall('lazyJSType(() => #, #)',
- [_emitJSInteropForGlobal(jsName), js.escapedString(jsName)]);
- }
+ // package:js types fall under either named or anonymous types. Named types
+ // are used to correspond to JS types that exist, but we do not use the
+ // underlying type for type checks, so they operate virtually the same as
+ // anonymous types. We represent package:js types with a corresponding type
+ // object.
+ var jsName = isJSAnonymousType(c) ?
+ getLocalClassName(c) : _emitJsNameWithoutGlobal(c);
+ if (jsName != null) {
+ typeRep = runtimeCall('packageJSType(#)', [js.escapedString(jsName)]);
}
if (typeRep != null) {
@@ -3605,7 +3605,7 @@
}
for (var p in f.positionalParameters) {
- var jsParam = _emitVariableDef(p);
+ var jsParam = _emitVariableRef(p);
if (_checkParameters) {
initParameter(p, jsParam);
}
@@ -4510,13 +4510,9 @@
var name = v.name;
if (name == null || name.startsWith('#')) {
name = name == null ? 't${_tempVariables.length}' : name.substring(1);
- // TODO(nshahan) Record the Identifier for this variable in
- // variableIdentifiers.
return _tempVariables.putIfAbsent(v, () => _emitTemporaryId(name));
}
- var identifier = _emitIdentifier(name);
- variableIdentifiers[v] = identifier;
- return identifier;
+ return _emitIdentifier(name);
}
/// Emits the declaration of a variable.
@@ -4524,7 +4520,9 @@
/// This is similar to [_emitVariableRef] but it also attaches source
/// location information, so hover will work as expected.
js_ast.Identifier _emitVariableDef(VariableDeclaration v) {
- return _emitVariableRef(v)..sourceInformation = _nodeStart(v);
+ var identifier = _emitVariableRef(v)..sourceInformation = _nodeStart(v);
+ variableIdentifiers[v] = identifier;
+ return identifier;
}
js_ast.Statement _initLetVariables() {
@@ -4563,12 +4561,6 @@
}
@override
- js_ast.Expression visitPropertyGet(PropertyGet node) {
- return _emitPropertyGet(
- node.receiver, node.interfaceTarget, node.name.text);
- }
-
- @override
js_ast.Expression visitDynamicSet(DynamicSet node) {
return _emitPropertySet(node.receiver, null, node.value, node.name.text);
}
@@ -4579,12 +4571,6 @@
node.receiver, node.interfaceTarget, node.value, node.name.text);
}
- @override
- js_ast.Expression visitPropertySet(PropertySet node) {
- return _emitPropertySet(
- node.receiver, node.interfaceTarget, node.value, node.name.text);
- }
-
js_ast.Expression _emitPropertyGet(Expression receiver, Member member,
[String memberName]) {
memberName ??= member.name.text;
@@ -4759,12 +4745,6 @@
negated: false);
}
- @override
- js_ast.Expression visitMethodInvocation(MethodInvocation node) {
- return _emitMethodCall(
- node.receiver, node.interfaceTarget, node.arguments, node);
- }
-
js_ast.Expression _emitMethodCall(Expression receiver, Member target,
Arguments arguments, InvocationExpression node) {
var name = node.name.text;
@@ -5749,11 +5729,7 @@
@override
js_ast.Expression visitNot(Not node) {
var operand = node.operand;
- if (operand is MethodInvocation && operand.name.text == '==') {
- return _emitEqualityOperator(operand.receiver, operand.interfaceTarget,
- operand.arguments.positional[0],
- negated: true);
- } else if (operand is EqualsCall) {
+ if (operand is EqualsCall) {
return _emitEqualityOperator(
operand.left, operand.interfaceTarget, operand.right,
negated: true);
@@ -5853,6 +5829,12 @@
}
@override
+ js_ast.Expression visitRedirectingFactoryTearOff(
+ RedirectingFactoryTearOff node) {
+ throw UnsupportedError('RedirectingFactory tear off');
+ }
+
+ @override
js_ast.Expression visitTypedefTearOff(TypedefTearOff node) {
throw UnsupportedError('Typedef instantiation');
}
@@ -6241,13 +6223,13 @@
js_ast.Expression visitConstant(Constant node) {
if (node is StaticTearOffConstant) {
// JS() or external JS consts should not be lazily loaded.
- var isSdk = node.procedure.enclosingLibrary.importUri.scheme == 'dart';
+ var isSdk = node.target.enclosingLibrary.importUri.scheme == 'dart';
if (_isInForeignJS) {
- return _emitStaticTarget(node.procedure);
+ return _emitStaticTarget(node.target);
}
- if (node.procedure.isExternal && !isSdk) {
+ if (node.target.isExternal && !isSdk) {
return runtimeCall(
- 'tearoffInterop(#)', [_emitStaticTarget(node.procedure)]);
+ 'tearoffInterop(#)', [_emitStaticTarget(node.target)]);
}
}
if (node is TypeLiteralConstant) {
@@ -6419,15 +6401,16 @@
Library library, String className, Member member,
[js_ast.TemporaryId id]) {
var name = '$className.${member.name.text}';
- // Names used in the symbols for the public fields
- // memberNames[member] = 'Symbol($name)';
+ // Wrap the name as a symbol here so it matches what you would find at
+ // runtime when you get all properties and symbols from an instance.
+ memberNames[member] = 'Symbol($name)';
return emitPrivateNameSymbol(library, name, id);
}
@override
js_ast.Expression visitStaticTearOffConstant(StaticTearOffConstant node) {
- _declareBeforeUse(node.procedure.enclosingClass);
- return _emitStaticGet(node.procedure);
+ _declareBeforeUse(node.target.enclosingClass);
+ return _emitStaticGet(node.target);
}
@override
diff --git a/pkg/dev_compiler/lib/src/kernel/constants.dart b/pkg/dev_compiler/lib/src/kernel/constants.dart
index d5b538f..87df7e3 100644
--- a/pkg/dev_compiler/lib/src/kernel/constants.dart
+++ b/pkg/dev_compiler/lib/src/kernel/constants.dart
@@ -2,8 +2,7 @@
// 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.
-// @dart = 2.9
-
+import 'package:collection/collection.dart';
import 'package:kernel/kernel.dart';
import 'package:kernel/target/targets.dart';
@@ -21,7 +20,7 @@
/// failed, or if the constant was unavailable.
///
/// Returns [NullConstant] to represent the `null` value.
- Constant evaluate(Expression e) {
+ Constant? evaluate(Expression e) {
return e is ConstantExpression ? e.constant : null;
}
@@ -43,13 +42,12 @@
/// main() { ... }
///
/// Given the node for `@MyAnnotation('FooBar')` this will return `'FooBar'`.
- Object getFieldValueFromAnnotation(Expression node, String name) {
+ Object? getFieldValueFromAnnotation(Expression node, String name) {
if (node is ConstantExpression) {
var constant = node.constant;
if (constant is InstanceConstant) {
var value = constant.fieldValues.entries
- .firstWhere((e) => e.key.asField.name.text == name,
- orElse: () => null)
+ .firstWhereOrNull((e) => e.key.asField.name.text == name)
?.value;
if (value is PrimitiveConstant) return value.value;
if (value is UnevaluatedConstant) {
@@ -64,11 +62,10 @@
//
// We may need to address this in the kernel outline files.
if (node is ConstructorInvocation) {
- Expression first;
+ Expression? first;
var named = node.arguments.named;
if (named.isNotEmpty) {
- first =
- named.firstWhere((n) => n.name == name, orElse: () => null)?.value;
+ first = named.firstWhereOrNull((n) => n.name == name)?.value;
}
var positional = node.arguments.positional;
if (positional.isNotEmpty) first ??= positional[0];
@@ -79,7 +76,7 @@
return null;
}
- Object _evaluateAnnotationArgument(Expression node) {
+ Object? _evaluateAnnotationArgument(Expression node) {
if (node is ConstantExpression) {
var constant = node.constant;
if (constant is PrimitiveConstant) return constant.value;
@@ -87,7 +84,7 @@
if (node is StaticGet) {
var target = node.target;
if (target is Field) {
- return _evaluateAnnotationArgument(target.initializer);
+ return _evaluateAnnotationArgument(target.initializer!);
}
}
return node is BasicLiteral ? node.value : null;
diff --git a/pkg/dev_compiler/lib/src/kernel/expression_compiler.dart b/pkg/dev_compiler/lib/src/kernel/expression_compiler.dart
index 7ac69c9..23cc5bb 100644
--- a/pkg/dev_compiler/lib/src/kernel/expression_compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/expression_compiler.dart
@@ -28,7 +28,7 @@
Member,
Node,
Procedure,
- RedirectingFactoryConstructor,
+ RedirectingFactory,
TreeNode,
TypeParameter,
VariableDeclaration,
@@ -253,7 +253,7 @@
if (node is Constructor) return node.fileEndOffset;
if (node is Procedure) return node.fileEndOffset;
if (node is Field) return node.fileEndOffset;
- if (node is RedirectingFactoryConstructor) return node.fileEndOffset;
+ if (node is RedirectingFactory) return node.fileEndOffset;
if (node is FunctionNode) return node.fileEndOffset;
return noOffset;
}
diff --git a/pkg/dev_compiler/lib/src/kernel/expression_compiler_worker.dart b/pkg/dev_compiler/lib/src/kernel/expression_compiler_worker.dart
index 1cdbd66..86a0cc2 100644
--- a/pkg/dev_compiler/lib/src/kernel/expression_compiler_worker.dart
+++ b/pkg/dev_compiler/lib/src/kernel/expression_compiler_worker.dart
@@ -113,24 +113,30 @@
/// receive port corresponding to [sendPort].
static Future<void> createAndStart(List<String> args,
{SendPort sendPort}) async {
+ ExpressionCompilerWorker worker;
if (sendPort != null) {
var receivePort = ReceivePort();
sendPort.send(receivePort.sendPort);
try {
- var worker = await createFromArgs(args,
+ worker = await createFromArgs(args,
requestStream: receivePort.cast<Map<String, dynamic>>(),
sendResponse: sendPort.send);
- await worker.start();
+ await worker.run();
} catch (e, s) {
sendPort
.send({'exception': '$e', 'stackTrace': '$s', 'succeeded': false});
rethrow;
} finally {
receivePort.close();
+ worker?.close();
}
} else {
- var worker = await createFromArgs(args);
- await worker.start();
+ try {
+ worker = await createFromArgs(args);
+ await worker.run();
+ } finally {
+ worker?.close();
+ }
}
}
@@ -243,7 +249,7 @@
///
/// Completes when the [requestStream] closes and we finish handling the
/// requests.
- Future<void> start() async {
+ Future<void> run() async {
await for (var request in requestStream) {
try {
var command = request['command'] as String;
@@ -275,6 +281,11 @@
_processedOptions.ticker.logMs('Stopped expression compiler worker.');
}
+ void close() {
+ var fileSystem = _processedOptions?.fileSystem;
+ if (fileSystem != null && fileSystem is AssetFileSystem) fileSystem.close();
+ }
+
/// Handles a `CompileExpression` request.
Future<Map<String, dynamic>> _compileExpression(
CompileExpressionRequest request) async {
diff --git a/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart b/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart
index 0c4e313..166080a 100644
--- a/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart
+++ b/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart
@@ -2,19 +2,18 @@
// 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.
-// @dart = 2.9
-
import 'dart:collection';
+import 'package:collection/collection.dart';
import 'package:front_end/src/api_unstable/ddc.dart';
import 'package:kernel/core_types.dart';
import 'package:kernel/kernel.dart';
-Constructor unnamedConstructor(Class c) =>
- c.constructors.firstWhere((c) => c.name.text == '', orElse: () => null);
+Constructor? unnamedConstructor(Class c) =>
+ c.constructors.firstWhereOrNull((c) => c.name.text == '');
/// Returns the enclosing library for reference [node].
-Library getLibrary(NamedNode node) {
- for (TreeNode n = node; n != null; n = n.parent) {
+Library? getLibrary(NamedNode node) {
+ for (TreeNode? n = node; n != null; n = n.parent) {
if (n is Library) return n;
}
return null;
@@ -22,14 +21,14 @@
final Pattern _syntheticTypeCharacters = RegExp('[&^#.|]');
-String escapeIdentifier(String identifier) {
+String? escapeIdentifier(String? identifier) {
// Remove the special characters used to encode mixin application class names
// and extension method / parameter names which are legal in Kernel, but not
// in JavaScript.
//
// Note, there is an implicit assumption here that we won't have
// collisions since everything is mapped to \$. That may work out fine given
- // how these are sythesized, but may need to revisit.
+ // how these are synthesized, but may need to revisit.
return identifier?.replaceAll(_syntheticTypeCharacters, r'$');
}
@@ -40,15 +39,15 @@
///
/// In the current encoding, generic classes are generated in a function scope
/// which avoids name clashes of the escaped class name.
-String getLocalClassName(Class node) => escapeIdentifier(node.name);
+String getLocalClassName(Class node) => escapeIdentifier(node.name)!;
/// Returns the escaped name for the type parameter [node].
///
/// In the current encoding, generic classes are generated in a function scope
/// which avoids name clashes of the escaped parameter name.
-String getTypeParameterName(TypeParameter node) => escapeIdentifier(node.name);
+String? getTypeParameterName(TypeParameter node) => escapeIdentifier(node.name);
-String getTopLevelName(NamedNode n) {
+String? getTopLevelName(NamedNode n) {
if (n is Procedure) return n.name.text;
if (n is Class) return n.name;
if (n is Typedef) return n.name;
@@ -69,7 +68,7 @@
///
/// (v) => v.type.name == 'Deprecated' && v.type.element.library.isDartCore
///
-Expression findAnnotation(TreeNode node, bool Function(Expression) test) {
+Expression? findAnnotation(TreeNode node, bool Function(Expression) test) {
List<Expression> annotations;
if (node is Class) {
annotations = node.annotations;
@@ -84,7 +83,7 @@
} else {
return null;
}
- return annotations.firstWhere(test, orElse: () => null);
+ return annotations.firstWhereOrNull(test);
}
/// Returns true if [value] represents an annotation for class [className] in
@@ -108,7 +107,7 @@
///
/// This function works regardless of whether the CFE is evaluating constants,
/// or whether the constant is a field reference (such as "anonymous" above).
-Class getAnnotationClass(Expression node) {
+Class? getAnnotationClass(Expression node) {
if (node is ConstantExpression) {
var constant = node.constant;
if (constant is InstanceConstant) return constant.classNode;
@@ -165,9 +164,9 @@
/// A mixin alias class is a mixin application, that can also be itself used as
/// a mixin.
bool isMixinAliasClass(Class c) =>
- c.isMixinApplication && c.superclass.superclass == null;
+ c.isMixinApplication && c.superclass!.superclass == null;
-List<Class> getSuperclasses(Class c) {
+List<Class> getSuperclasses(Class? c) {
var result = <Class>[];
var visited = HashSet<Class>();
while (c != null && visited.add(c)) {
@@ -191,10 +190,8 @@
return result;
}
-Expression getInvocationReceiver(InvocationExpression node) {
- if (node is MethodInvocation) {
- return node.receiver;
- } else if (node is InstanceInvocation) {
+Expression? getInvocationReceiver(InvocationExpression node) {
+ if (node is InstanceInvocation) {
return node.receiver;
} else if (node is DynamicInvocation) {
return node.receiver;
@@ -251,7 +248,7 @@
/// Returns the redirecting factory constructors for the enclosing class,
/// if the field [f] is storing that information, otherwise returns `null`.
-Iterable<Member> getRedirectingFactories(Field f) {
+Iterable<Member>? getRedirectingFactories(Field f) {
// TODO(jmesserly): this relies on implementation details in Kernel
if (isRedirectingFactoryField(f)) {
assert(f.isStatic);
@@ -269,14 +266,15 @@
// TODO(jmesserly): consider replacing this with Kernel's mixin unrolling
Class getSuperclassAndMixins(Class c, List<Class> mixins) {
assert(mixins.isEmpty);
+ assert(c.superclass != null);
var mixedInClass = c.mixedInClass;
if (mixedInClass != null) mixins.add(mixedInClass);
- var sc = c.superclass;
- for (; sc.isAnonymousMixin; sc = sc.superclass) {
+ var sc = c.superclass!;
+ for (; sc.isAnonymousMixin; sc = sc.superclass!) {
mixedInClass = sc.mixedInClass;
- if (mixedInClass != null) mixins.add(sc.mixedInClass);
+ if (mixedInClass != null) mixins.add(sc.mixedInClass!);
}
return sc;
}
@@ -291,7 +289,7 @@
class LabelContinueFinder extends StatementVisitor<void> {
var found = false;
- void visit(Statement s) {
+ void visit(Statement? s) {
if (!found && s != null) s.accept(this);
}
diff --git a/pkg/dev_compiler/lib/src/kernel/module_symbols_collector.dart b/pkg/dev_compiler/lib/src/kernel/module_symbols_collector.dart
index 253facf..acb2bcd 100644
--- a/pkg/dev_compiler/lib/src/kernel/module_symbols_collector.dart
+++ b/pkg/dev_compiler/lib/src/kernel/module_symbols_collector.dart
@@ -15,23 +15,24 @@
/// last element in the list represents the current scope.
final _scopes = <ScopeSymbol>[];
- final _moduleSymbols = ModuleSymbols(
- // TODO(nshahan) version
- // TODO(nshahan) moduleName
- libraries: <LibrarySymbol>[],
- scripts: <Script>[],
- classes: <ClassSymbol>[],
- // TODO(nshahan) functionTypes
- // TODO(nshahan) functions
- // TODO(nshahan) scopes
- variables: <VariableSymbol>[]);
-
+ final ModuleSymbols _moduleSymbols;
final Map<Class, String> _classJsNames;
final Map<Member, String> _memberJsNames;
+ final Map<Procedure, String> _procedureJsNames;
final Map<VariableDeclaration, String> _variableJsNames;
- ModuleSymbolsCollector(
- this._classJsNames, this._memberJsNames, this._variableJsNames);
+ ModuleSymbolsCollector(String moduleName, this._classJsNames,
+ this._memberJsNames, this._procedureJsNames, this._variableJsNames)
+ : _moduleSymbols = ModuleSymbols(
+ version: ModuleSymbols.current.version,
+ moduleName: moduleName,
+ libraries: <LibrarySymbol>[],
+ scripts: <Script>[],
+ classes: <ClassSymbol>[],
+ // TODO(nshahan) functionTypes
+ functions: <FunctionSymbol>[],
+ // TODO(nshahan) scopes
+ variables: <VariableSymbol>[]);
ModuleSymbols collectSymbolInfo(Component node) {
node.accept(this);
@@ -143,8 +144,27 @@
// Legacy libraries contain procedures with no bodies for all Object methods
// in every class. We can ignore these unless they actually contain a body.
if (node.function.body == null) return;
- // TODO(nshahan) implement visitProcedure
- super.visitProcedure(node);
+ var functionSymbol = FunctionSymbol(
+ name: node.name.text,
+ // TODO(nshahan) typeId - probably should canonicalize but keep original
+ // type argument names.
+ isStatic: node.isStatic,
+ isConst: node.isConst,
+ localId: _memberJsNames[node] ?? _procedureJsNames[node],
+ scopeId: _scopes.last.id,
+ variableIds: <String>[],
+ scopeIds: <String>[],
+ location: SourceLocation(
+ scriptId: _scriptId(node.location.file),
+ tokenPos: node.fileOffset,
+ endTokenPos: node.fileEndOffset));
+
+ _scopes.add(functionSymbol);
+ node.visitChildren(this);
+ _scopes
+ ..removeLast()
+ ..last.scopeIds.add(functionSymbol.id);
+ _moduleSymbols.functions.add(functionSymbol);
}
@override
diff --git a/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart b/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart
index 07fa7d4..71aaed2 100644
--- a/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart
+++ b/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart
@@ -91,10 +91,6 @@
bool visitVariableSet(VariableSet node) => isNullable(node.value);
@override
- bool visitPropertyGet(PropertyGet node) =>
- _getterIsNullable(node.interfaceTarget, node);
-
- @override
bool visitInstanceGet(InstanceGet node) =>
_getterIsNullable(node.interfaceTarget, node);
@@ -110,9 +106,6 @@
_getterIsNullable(null, node);
@override
- bool visitPropertySet(PropertySet node) => isNullable(node.value);
-
- @override
bool visitInstanceSet(InstanceSet node) => isNullable(node.value);
@override
@@ -136,10 +129,6 @@
bool visitStaticSet(StaticSet node) => isNullable(node.value);
@override
- bool visitMethodInvocation(MethodInvocation node) => _invocationIsNullable(
- node.interfaceTarget, node.name.text, node, node.receiver);
-
- @override
bool visitInstanceInvocation(InstanceInvocation node) =>
_invocationIsNullable(
node.interfaceTarget, node.name.text, node, node.receiver);
diff --git a/pkg/dev_compiler/lib/src/kernel/retry_timeout_client.dart b/pkg/dev_compiler/lib/src/kernel/retry_timeout_client.dart
index 36a768e..dfaa3d9 100644
--- a/pkg/dev_compiler/lib/src/kernel/retry_timeout_client.dart
+++ b/pkg/dev_compiler/lib/src/kernel/retry_timeout_client.dart
@@ -99,7 +99,8 @@
void close({bool force = false}) => _inner.close(force: force);
}
-bool _defaultWhen(HttpClientResponse response) => response.statusCode == 503;
+bool _defaultWhen(HttpClientResponse response) =>
+ response.statusCode == 500 || response.statusCode == 503;
bool _defaultWhenError(Object error, StackTrace stackTrace) =>
error is OSError ||
diff --git a/pkg/dev_compiler/lib/src/kernel/target.dart b/pkg/dev_compiler/lib/src/kernel/target.dart
index b6020ee..1beb7d8 100644
--- a/pkg/dev_compiler/lib/src/kernel/target.dart
+++ b/pkg/dev_compiler/lib/src/kernel/target.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'dart:collection';
import 'package:_fe_analyzer_shared/src/messages/codes.dart'
@@ -28,9 +26,9 @@
@override
final TargetFlags flags;
- WidgetCreatorTracker _widgetTracker;
+ WidgetCreatorTracker? _widgetTracker;
- Map<String, Class> _nativeClasses;
+ Map<String, Class>? _nativeClasses;
@override
bool get enableSuperMixins => true;
@@ -50,9 +48,6 @@
bool get supportsExplicitGetterCalls => false;
@override
- bool get supportsNewMethodInvocationEncoding => true;
-
- @override
int get enabledConstructorTearOffLowerings => ConstructorTearOffLowering.none;
@override
@@ -156,11 +151,11 @@
CoreTypes coreTypes,
ClassHierarchy hierarchy,
List<Library> libraries,
- Map<String, String> environmentDefines,
+ Map<String, String>? environmentDefines,
DiagnosticReporter diagnosticReporter,
- ReferenceFromIndex referenceFromIndex,
- {void Function(String msg) logger,
- ChangedStructureNotifier changedStructureNotifier}) {
+ ReferenceFromIndex? referenceFromIndex,
+ {void Function(String msg)? logger,
+ ChangedStructureNotifier? changedStructureNotifier}) {
_nativeClasses ??= JsInteropChecks.getNativeClasses(component);
var jsUtilOptimizer = JsUtilOptimizer(coreTypes, hierarchy);
for (var library in libraries) {
@@ -169,7 +164,7 @@
JsInteropChecks(
coreTypes,
diagnosticReporter as DiagnosticReporter<Message, LocatedMessage>,
- _nativeClasses)
+ _nativeClasses!)
.visitLibrary(library);
}
}
@@ -180,11 +175,11 @@
CoreTypes coreTypes,
List<Library> libraries,
DiagnosticReporter diagnosticReporter,
- {void Function(String msg) logger,
- ChangedStructureNotifier changedStructureNotifier}) {
+ {void Function(String msg)? logger,
+ ChangedStructureNotifier? changedStructureNotifier}) {
if (flags.trackWidgetCreation) {
_widgetTracker ??= WidgetCreatorTracker();
- _widgetTracker.transform(component, libraries, changedStructureNotifier);
+ _widgetTracker!.transform(component, libraries, changedStructureNotifier);
}
}
@@ -352,7 +347,7 @@
/// If the member needs a check it will be stored in [_checkedMembers].
///
/// See [transform] for more information.
- void _checkTarget(Expression receiver, Member target) {
+ void _checkTarget(Expression receiver, Member? target) {
if (target != null &&
target.name.isPrivate &&
target.isInstanceMember &&
@@ -370,7 +365,7 @@
/// escape, and it also has a different runtime type.
///
/// See [transform] for more information.
- void _checkTearoff(Member target) {
+ void _checkTearoff(Member? target) {
if (target != null &&
target.name.isPrivate &&
target.isInstanceMember &&
@@ -411,36 +406,18 @@
}
@override
- void visitPropertyGet(PropertyGet node) {
- _checkTearoff(node.interfaceTarget);
- super.visitPropertyGet(node);
- }
-
- @override
void visitInstanceGet(InstanceGet node) {
_checkTearoff(node.interfaceTarget);
super.visitInstanceGet(node);
}
@override
- void visitPropertySet(PropertySet node) {
- _checkTarget(node.receiver, node.interfaceTarget);
- super.visitPropertySet(node);
- }
-
- @override
void visitInstanceSet(InstanceSet node) {
_checkTarget(node.receiver, node.interfaceTarget);
super.visitInstanceSet(node);
}
@override
- void visitMethodInvocation(MethodInvocation node) {
- _checkTarget(node.receiver, node.interfaceTarget);
- super.visitMethodInvocation(node);
- }
-
- @override
void visitInstanceInvocation(InstanceInvocation node) {
_checkTarget(node.receiver, node.interfaceTarget);
super.visitInstanceInvocation(node);
diff --git a/pkg/dev_compiler/pubspec.yaml b/pkg/dev_compiler/pubspec.yaml
index 89ca585..e0271f3 100644
--- a/pkg/dev_compiler/pubspec.yaml
+++ b/pkg/dev_compiler/pubspec.yaml
@@ -3,7 +3,7 @@
publish_to: none
environment:
- sdk: '>=2.3.0 <3.0.0'
+ sdk: '>=2.12.0 <3.0.0'
dependencies:
_fe_analyzer_shared:
@@ -16,6 +16,7 @@
build_integration:
path: ../build_integration
cli_util: any
+ collection: ^1.15.0
front_end:
path: ../front_end
kernel:
@@ -28,7 +29,7 @@
source_span: any
dev_dependencies:
- browser_launcher: ^0.1.9
+ browser_launcher: ^1.0.0
expect:
path: ../expect
http_multi_server:
@@ -48,5 +49,5 @@
path: ../testing
vm:
path: ../vm
- webkit_inspection_protocol: ^0.7.4
+ webkit_inspection_protocol: ^1.0.0
diff --git a/pkg/dev_compiler/test/expression_compiler/asset_file_system_test.dart b/pkg/dev_compiler/test/expression_compiler/asset_file_system_test.dart
index a11668a..ca481dc 100644
--- a/pkg/dev_compiler/test/expression_compiler/asset_file_system_test.dart
+++ b/pkg/dev_compiler/test/expression_compiler/asset_file_system_test.dart
@@ -66,6 +66,35 @@
return Response.internalServerError();
}
+int _attempts = 0;
+FutureOr<Response> unreliableHandler(Request request) {
+ final uri = request.requestedUri;
+ final headers = {
+ 'content-length': '${utf8.encode(_smallFileContents).length}',
+ ...request.headers,
+ };
+
+ if ((_attempts++) % 5 == 0) return Response.internalServerError();
+
+ if (request.method == 'HEAD') {
+ // 'exists'
+ return uri.pathSegments.last == _existingFile
+ ? Response.ok(null, headers: headers)
+ : Response.notFound(uri.toString());
+ }
+ if (request.method == 'GET') {
+ // 'readAsBytes'
+ return uri.pathSegments.last == _existingFile
+ ? Response.ok(_smallFileContents, headers: headers)
+ : Response.notFound(uri.toString());
+ }
+ return Response.internalServerError();
+}
+
+FutureOr<Response> alwaysFailingHandler(Request request) {
+ return Response.internalServerError();
+}
+
void main() async {
HttpServer server;
AssetFileSystem fileSystem;
@@ -83,6 +112,7 @@
tearDownAll(() async {
await expectLater(server.close(), completes);
+ fileSystem.close();
});
test('can tell if file exists', () async {
@@ -119,12 +149,10 @@
test('can read a lot of files concurrently', () async {
var entity = fileSystem.entityForUri(Uri.parse(_existingFile));
var futures = [
- for (var i = 0; i < 512; i++) entity.readAsBytes(),
+ for (var i = 0; i < 512; i++)
+ _expectContents(entity, _smallFileContents),
];
- var results = await Future.wait(futures);
- for (var result in results) {
- expect(utf8.decode(result), _smallFileContents);
- }
+ await Future.wait(futures);
}, timeout: const Timeout.factor(2));
});
@@ -142,6 +170,7 @@
tearDownAll(() async {
await expectLater(server.close(), completes);
+ fileSystem.close();
});
test('can tell if file exists', () async {
@@ -196,15 +225,124 @@
});
test('can read a lot of files concurrently', () async {
+ var fileContents = _largeFileContents();
var entity = fileSystem.entityForUri(Uri.parse(_existingFile));
var futures = [
- for (var i = 0; i < 512; i++) entity.readAsBytes(),
+ for (var i = 0; i < 512; i++) _expectContents(entity, fileContents),
];
- var results = await Future.wait(futures);
- var fileContents = _largeFileContents();
- for (var result in results) {
- expect(utf8.decode(result), fileContents);
- }
+ await Future.wait(futures);
}, timeout: const Timeout.factor(2));
});
+
+ group('AssetFileSystem with an unreliable server', () {
+ setUpAll(() async {
+ var hostname = 'localhost';
+ var port = await findUnusedPort();
+
+ server = await HttpMultiServer.bind(hostname, port);
+ fileSystem =
+ AssetFileSystem(StandardFileSystem.instance, hostname, '$port');
+
+ serveRequests(server, unreliableHandler);
+ });
+
+ tearDownAll(() async {
+ await expectLater(server.close(), completes);
+ fileSystem.close();
+ });
+
+ test('can tell if file exists', () async {
+ var entity = fileSystem.entityForUri(Uri.parse(_existingFile));
+ expect(await entity.exists(), true);
+ });
+
+ test('can tell if file does not exist', () async {
+ var entity = fileSystem.entityForUri(Uri.parse(_nonExistingFile));
+ expect(await entity.exists(), false);
+ });
+
+ test('can read existing file using readAsBytes', () async {
+ var entity = fileSystem.entityForUri(Uri.parse(_existingFile));
+ expect(await entity.readAsBytes(), _smallFileBytes);
+ });
+
+ test('can read and decode existing file using readAsBytes', () async {
+ var entity = fileSystem.entityForUri(Uri.parse(_existingFile));
+ expect(utf8.decode(await entity.readAsBytes()), _smallFileContents);
+ });
+
+ test('can read existing file using readAsString', () async {
+ var entity = fileSystem.entityForUri(Uri.parse(_existingFile));
+ expect(await entity.readAsString(), _smallFileContents);
+ });
+
+ test('cannot read non-existing file', () async {
+ var entity = fileSystem.entityForUri(Uri.parse(_nonExistingFile));
+ await expectLater(
+ entity.readAsBytes(), throwsA(isA<FileSystemException>()));
+ });
+
+ test('can read a lot of files concurrently', () async {
+ var entity = fileSystem.entityForUri(Uri.parse(_existingFile));
+ var futures = [
+ for (var i = 0; i < 512; i++)
+ _expectContents(entity, _smallFileContents),
+ ];
+ await Future.wait(futures);
+ }, timeout: const Timeout.factor(2));
+ });
+
+ group('AssetFileSystem with failing server', () {
+ setUpAll(() async {
+ var hostname = 'localhost';
+ var port = await findUnusedPort();
+
+ server = await HttpMultiServer.bind(hostname, port);
+ fileSystem =
+ AssetFileSystem(StandardFileSystem.instance, hostname, '$port');
+
+ serveRequests(server, alwaysFailingHandler);
+ });
+
+ tearDownAll(() async {
+ await expectLater(server.close(), completes);
+ fileSystem.close();
+ });
+
+ test('cannot tell if file exists', () async {
+ var entity = fileSystem.entityForUri(Uri.parse(_existingFile));
+ expect(await entity.exists(), false);
+ });
+
+ test('cannot tell if file does not exist', () async {
+ var entity = fileSystem.entityForUri(Uri.parse(_nonExistingFile));
+ expect(await entity.exists(), false);
+ });
+
+ test('cannot read existing file using readAsBytes', () async {
+ var entity = fileSystem.entityForUri(Uri.parse(_existingFile));
+ await expectLater(
+ entity.readAsBytes(), throwsA(isA<FileSystemException>()));
+ });
+
+ test('cannot read existing file using readAsString', () async {
+ var entity = fileSystem.entityForUri(Uri.parse(_existingFile));
+ await expectLater(
+ entity.readAsString(), throwsA(isA<FileSystemException>()));
+ });
+
+ test('cannot read non-existing file', () async {
+ var entity = fileSystem.entityForUri(Uri.parse(_nonExistingFile));
+ await expectLater(
+ entity.readAsBytes(), throwsA(isA<FileSystemException>()));
+ });
+ });
+}
+
+// Read the response (and free the socket) as soon as we get it.
+// That allows some connection to buffer and wait for free sockets
+// when the limit if connections is reached.
+Future<void> _expectContents(FileSystemEntity entity, String contents) async {
+ var result = await entity.readAsString();
+ expect(result, contents);
}
diff --git a/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_shared.dart b/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_shared.dart
index 1e1f94d..40f3f36 100644
--- a/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_shared.dart
+++ b/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_shared.dart
@@ -420,7 +420,7 @@
await driver.check(
breakpointId: 'globalFunctionBP',
expression: 'C._staticField',
- expectedError: "Error: Getter not found: '_staticField'.");
+ expectedResult: '2');
});
test('access field', () async {
@@ -476,7 +476,7 @@
await driver.check(
breakpointId: 'globalFunctionBP',
expression: 'C._staticField = 2',
- expectedError: "Setter not found: '_staticField'.");
+ expectedResult: '2');
});
test('static field modification', () async {
diff --git a/pkg/dev_compiler/test/expression_compiler/expression_compiler_worker_test.dart b/pkg/dev_compiler/test/expression_compiler/expression_compiler_worker_test.dart
index 9a06c77..c54916b 100644
--- a/pkg/dev_compiler/test/expression_compiler/expression_compiler_worker_test.dart
+++ b/pkg/dev_compiler/test/expression_compiler/expression_compiler_worker_test.dart
@@ -836,13 +836,14 @@
soundNullSafety: soundNullSafety,
verbose: verbose,
);
- workerDone = worker.start();
+ workerDone = worker.run();
}
Future<void> tearDown() async {
unawaited(requestController.close());
await workerDone;
unawaited(responseController.close());
+ worker?.close();
}
}
diff --git a/pkg/dev_compiler/test/module_symbols/class_symbols_test.dart b/pkg/dev_compiler/test/module_symbols/class_symbols_test.dart
index ee907ce..c08995f 100644
--- a/pkg/dev_compiler/test/module_symbols/class_symbols_test.dart
+++ b/pkg/dev_compiler/test/module_symbols/class_symbols_test.dart
@@ -293,6 +293,394 @@
expect(fieldSymbol.isStatic, isFalse);
});
});
+ group('class public instance method debug symbols', () {
+ TestDriver driver;
+ ClassSymbol classSymbol;
+ FunctionSymbol methodSymbol;
+ final source = '''
+ ${options.dartLangComment}
+
+ class A {
+ String publicInstanceMethod() => 'Cello';
+ }
+ ''';
+ setUpAll(() async {
+ driver = TestDriver(options, source);
+ var result = await driver.compile();
+ classSymbol = result.symbols.classes.single;
+ methodSymbol = result.symbols.functions.single;
+ });
+ tearDownAll(() {
+ driver.cleanUp();
+ });
+ test('functionId in classSymbol', () async {
+ expect(methodSymbol.id, endsWith('A|publicInstanceMethod'));
+ expect(methodSymbol.id, classSymbol.functionIds.single);
+ });
+ test('has class scopeId', () async {
+ expect(methodSymbol.scopeId, endsWith('|A'));
+ expect(methodSymbol.scopeId, classSymbol.id);
+ });
+ test('is not static', () async {
+ expect(methodSymbol.isStatic, isFalse);
+ });
+ });
+ group('class private instance method debug symbols', () {
+ TestDriver driver;
+ ClassSymbol classSymbol;
+ FunctionSymbol methodSymbol;
+ final source = '''
+ ${options.dartLangComment}
+
+ class A {
+ String _privateInstanceMethod() => 'Cello';
+ }
+ ''';
+ setUpAll(() async {
+ driver = TestDriver(options, source);
+ var result = await driver.compile();
+ classSymbol = result.symbols.classes.single;
+ methodSymbol = result.symbols.functions.single;
+ });
+ tearDownAll(() {
+ driver.cleanUp();
+ });
+ test('functionId in classSymbol', () async {
+ expect(methodSymbol.id, endsWith('A|Symbol(_privateInstanceMethod)'));
+ expect(methodSymbol.id, classSymbol.functionIds.single);
+ });
+ test('has class scopeId', () async {
+ expect(methodSymbol.scopeId, endsWith('|A'));
+ expect(methodSymbol.scopeId, classSymbol.id);
+ });
+ test('is not static', () async {
+ expect(methodSymbol.isStatic, isFalse);
+ });
+ });
+ group('class public static method debug symbols', () {
+ TestDriver driver;
+ ClassSymbol classSymbol;
+ FunctionSymbol methodSymbol;
+ final source = '''
+ ${options.dartLangComment}
+
+ class A {
+ static String publicStaticMethod() => 'Cello';
+ }
+ ''';
+ setUpAll(() async {
+ driver = TestDriver(options, source);
+ var result = await driver.compile();
+ classSymbol = result.symbols.classes.single;
+ methodSymbol = result.symbols.functions.single;
+ });
+ tearDownAll(() {
+ driver.cleanUp();
+ });
+ test('functionId in classSymbol', () async {
+ expect(methodSymbol.id, endsWith('A|publicStaticMethod'));
+ expect(methodSymbol.id, classSymbol.functionIds.single);
+ });
+ test('has class scopeId', () async {
+ expect(methodSymbol.scopeId, endsWith('|A'));
+ expect(methodSymbol.scopeId, classSymbol.id);
+ });
+ test('is static', () async {
+ expect(methodSymbol.isStatic, isTrue);
+ });
+ });
+ group('class private static method debug symbols', () {
+ TestDriver driver;
+ ClassSymbol classSymbol;
+ FunctionSymbol methodSymbol;
+ final source = '''
+ ${options.dartLangComment}
+
+ class A {
+ static String _privateStaticMethod() => 'Fosse';
+ }
+ ''';
+ setUpAll(() async {
+ driver = TestDriver(options, source);
+ var result = await driver.compile();
+ classSymbol = result.symbols.classes.single;
+ methodSymbol = result.symbols.functions.single;
+ });
+ tearDownAll(() {
+ driver.cleanUp();
+ });
+ test('functionId in classSymbol', () async {
+ expect(methodSymbol.id, endsWith('A|_privateStaticMethod'));
+ expect(methodSymbol.id, classSymbol.functionIds.single);
+ });
+ test('has class scopeId', () async {
+ expect(methodSymbol.scopeId, endsWith('|A'));
+ expect(methodSymbol.scopeId, classSymbol.id);
+ });
+ test('is static', () async {
+ expect(methodSymbol.isStatic, isTrue);
+ });
+ });
+ group('class public instance getter debug symbols', () {
+ TestDriver driver;
+ ClassSymbol classSymbol;
+ FunctionSymbol methodSymbol;
+ final source = '''
+ ${options.dartLangComment}
+
+ class A {
+ String get publicGetter() => 'Fosse';
+ }
+ ''';
+ setUpAll(() async {
+ driver = TestDriver(options, source);
+ var result = await driver.compile();
+ classSymbol = result.symbols.classes.single;
+ methodSymbol = result.symbols.functions.single;
+ });
+ tearDownAll(() {
+ driver.cleanUp();
+ });
+ test('functionId in classSymbol', () async {
+ expect(methodSymbol.id, endsWith('A|publicGetter'));
+ expect(methodSymbol.id, classSymbol.functionIds.single);
+ });
+ test('has class scopeId', () async {
+ expect(methodSymbol.scopeId, endsWith('|A'));
+ expect(methodSymbol.scopeId, classSymbol.id);
+ });
+ test('is not static', () async {
+ expect(methodSymbol.isStatic, isFalse);
+ });
+ });
+ group('class private instance getter debug symbols', () {
+ TestDriver driver;
+ ClassSymbol classSymbol;
+ FunctionSymbol methodSymbol;
+ final source = '''
+ ${options.dartLangComment}
+
+ class A {
+ String get _privateGetter() => 'Fosse';
+ }
+ ''';
+ setUpAll(() async {
+ driver = TestDriver(options, source);
+ var result = await driver.compile();
+ classSymbol = result.symbols.classes.single;
+ methodSymbol = result.symbols.functions.single;
+ });
+ tearDownAll(() {
+ driver.cleanUp();
+ });
+ test('functionId in classSymbol', () async {
+ expect(methodSymbol.id, endsWith('A|Symbol(_privateGetter)'));
+ expect(methodSymbol.id, classSymbol.functionIds.single);
+ });
+ test('has class scopeId', () async {
+ expect(methodSymbol.scopeId, endsWith('|A'));
+ expect(methodSymbol.scopeId, classSymbol.id);
+ });
+ test('is not static', () async {
+ expect(methodSymbol.isStatic, isFalse);
+ });
+ });
+ group('class public instance setter debug symbols', () {
+ TestDriver driver;
+ ClassSymbol classSymbol;
+ FunctionSymbol methodSymbol;
+ final source = '''
+ ${options.dartLangComment}
+
+ class A {
+ var _value
+ set publicSetter(String v) => _value = v;
+ }
+ ''';
+ setUpAll(() async {
+ driver = TestDriver(options, source);
+ var result = await driver.compile();
+ classSymbol = result.symbols.classes.single;
+ methodSymbol = result.symbols.functions.single;
+ });
+ tearDownAll(() {
+ driver.cleanUp();
+ });
+ test('functionId in classSymbol', () async {
+ expect(methodSymbol.id, endsWith('A|publicSetter'));
+ expect(methodSymbol.id, classSymbol.functionIds.single);
+ });
+ test('has class scopeId', () async {
+ expect(methodSymbol.scopeId, endsWith('|A'));
+ expect(methodSymbol.scopeId, classSymbol.id);
+ });
+ test('is not static', () async {
+ expect(methodSymbol.isStatic, isFalse);
+ });
+ });
+ group('class private instance setter debug symbols', () {
+ TestDriver driver;
+ ClassSymbol classSymbol;
+ FunctionSymbol methodSymbol;
+ final source = '''
+ ${options.dartLangComment}
+
+ class A {
+ var _value
+ set _privateSetter(String v) => _value = v;
+ }
+ ''';
+ setUpAll(() async {
+ driver = TestDriver(options, source);
+ var result = await driver.compile();
+ classSymbol = result.symbols.classes.single;
+ methodSymbol = result.symbols.functions.single;
+ });
+ tearDownAll(() {
+ driver.cleanUp();
+ });
+ test('functionId in classSymbol', () async {
+ expect(methodSymbol.id, endsWith('A|Symbol(_privateSetter)'));
+ expect(methodSymbol.id, classSymbol.functionIds.single);
+ });
+ test('has class scopeId', () async {
+ expect(methodSymbol.scopeId, endsWith('|A'));
+ expect(methodSymbol.scopeId, classSymbol.id);
+ });
+ test('is not static', () async {
+ expect(methodSymbol.isStatic, isFalse);
+ });
+ });
+ group('class public static getter debug symbols', () {
+ TestDriver driver;
+ ClassSymbol classSymbol;
+ FunctionSymbol methodSymbol;
+ final source = '''
+ ${options.dartLangComment}
+
+ class A {
+ static String get publicGetter() => 'Fosse';
+ }
+ ''';
+ setUpAll(() async {
+ driver = TestDriver(options, source);
+ var result = await driver.compile();
+ classSymbol = result.symbols.classes.single;
+ methodSymbol = result.symbols.functions.single;
+ });
+ tearDownAll(() {
+ driver.cleanUp();
+ });
+ test('functionId in classSymbol', () async {
+ expect(methodSymbol.id, endsWith('A|publicGetter'));
+ expect(methodSymbol.id, classSymbol.functionIds.single);
+ });
+ test('has class scopeId', () async {
+ expect(methodSymbol.scopeId, endsWith('|A'));
+ expect(methodSymbol.scopeId, classSymbol.id);
+ });
+ test('is static', () async {
+ expect(methodSymbol.isStatic, isTrue);
+ });
+ });
+ group('class private static getter debug symbols', () {
+ TestDriver driver;
+ ClassSymbol classSymbol;
+ FunctionSymbol methodSymbol;
+ final source = '''
+ ${options.dartLangComment}
+
+ class A {
+ static String get _privateGetter() => 'Fosse';
+ }
+ ''';
+ setUpAll(() async {
+ driver = TestDriver(options, source);
+ var result = await driver.compile();
+ classSymbol = result.symbols.classes.single;
+ methodSymbol = result.symbols.functions.single;
+ });
+ tearDownAll(() {
+ driver.cleanUp();
+ });
+ test('functionId in classSymbol', () async {
+ expect(methodSymbol.id, endsWith('A|_privateGetter'));
+ expect(methodSymbol.id, classSymbol.functionIds.single);
+ });
+ test('has class scopeId', () async {
+ expect(methodSymbol.scopeId, endsWith('|A'));
+ expect(methodSymbol.scopeId, classSymbol.id);
+ });
+ test('is static', () async {
+ expect(methodSymbol.isStatic, isTrue);
+ });
+ });
+ group('class public static setter debug symbols', () {
+ TestDriver driver;
+ ClassSymbol classSymbol;
+ FunctionSymbol methodSymbol;
+ final source = '''
+ ${options.dartLangComment}
+
+ class A {
+ var _value;
+ static set publicSetter(String v) => _value = v;
+ }
+ ''';
+ setUpAll(() async {
+ driver = TestDriver(options, source);
+ var result = await driver.compile();
+ classSymbol = result.symbols.classes.single;
+ methodSymbol = result.symbols.functions.single;
+ });
+ tearDownAll(() {
+ driver.cleanUp();
+ });
+ test('functionId in classSymbol', () async {
+ expect(methodSymbol.id, endsWith('A|publicSetter'));
+ expect(methodSymbol.id, classSymbol.functionIds.single);
+ });
+ test('has class scopeId', () async {
+ expect(methodSymbol.scopeId, endsWith('|A'));
+ expect(methodSymbol.scopeId, classSymbol.id);
+ });
+ test('is static', () async {
+ expect(methodSymbol.isStatic, isTrue);
+ });
+ });
+ group('class private static setter debug symbols', () {
+ TestDriver driver;
+ ClassSymbol classSymbol;
+ FunctionSymbol methodSymbol;
+ final source = '''
+ ${options.dartLangComment}
+
+ class A {
+ var _value;
+ static set _privateSetter(String v) => _value = v;
+ }
+ ''';
+ setUpAll(() async {
+ driver = TestDriver(options, source);
+ var result = await driver.compile();
+ classSymbol = result.symbols.classes.single;
+ methodSymbol = result.symbols.functions.single;
+ });
+ tearDownAll(() {
+ driver.cleanUp();
+ });
+ test('functionId in classSymbol', () async {
+ expect(methodSymbol.id, endsWith('A|_privateSetter'));
+ expect(methodSymbol.id, classSymbol.functionIds.single);
+ });
+ test('has class scopeId', () async {
+ expect(methodSymbol.scopeId, endsWith('|A'));
+ expect(methodSymbol.scopeId, classSymbol.id);
+ });
+ test('is static', () async {
+ expect(methodSymbol.isStatic, isTrue);
+ });
+ });
});
}
}
diff --git a/pkg/dev_compiler/test/module_symbols/function_symbols_test.dart b/pkg/dev_compiler/test/module_symbols/function_symbols_test.dart
new file mode 100644
index 0000000..f39f27b
--- /dev/null
+++ b/pkg/dev_compiler/test/module_symbols/function_symbols_test.dart
@@ -0,0 +1,326 @@
+// 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.
+
+// @dart = 2.9
+
+import 'package:dev_compiler/src/kernel/module_symbols.dart';
+import 'package:test/test.dart';
+
+import '../shared_test_options.dart';
+import 'module_symbols_test_shared.dart';
+
+void main() async {
+ for (var mode in [
+ NullSafetyTestOption('Sound Mode:', true),
+ NullSafetyTestOption('Weak Mode:', false)
+ ]) {
+ group(mode.description, () {
+ var options = SetupCompilerOptions(soundNullSafety: mode.soundNullSafety);
+ group('top level function debug symbols', () {
+ TestDriver driver;
+ FunctionSymbol functionSymbol;
+ LibrarySymbol librarySymbol;
+ final source = '''
+ ${options.dartLangComment}
+
+ void topLevelFunction() {
+ return;
+ }
+ ''';
+ setUpAll(() async {
+ driver = TestDriver(options, source);
+ var result = await driver.compile();
+ librarySymbol = result.symbols.libraries.single;
+ functionSymbol = result.symbols.functions.single;
+ });
+ tearDownAll(() {
+ driver.cleanUp();
+ });
+ test('has name', () async {
+ expect(functionSymbol.name, equals('topLevelFunction'));
+ });
+ // TODO(nshahan) Test for typeId.
+ test('is static', () async {
+ expect(functionSymbol.isStatic, isTrue);
+ });
+ test('is not const', () async {
+ expect(functionSymbol.isConst, isFalse);
+ });
+ test('has localId', () async {
+ expect(functionSymbol.localId, 'topLevelFunction');
+ });
+ test('has library scopeId', () async {
+ expect(functionSymbol.scopeId, endsWith('package:foo/foo.dart'));
+ expect(functionSymbol.scopeId, librarySymbol.id);
+ });
+ test('no local variables', () async {
+ expect(functionSymbol.variableIds, isEmpty);
+ });
+ test('no scopes', () async {
+ expect(functionSymbol.scopeIds, isEmpty);
+ });
+ group('location', () {
+ test('has scriptId', () async {
+ expect(functionSymbol.location.scriptId, endsWith('/foo.dart'));
+ });
+ test('has start token', () async {
+ expect(functionSymbol.location.tokenPos,
+ 27 + options.dartLangComment.length);
+ });
+ test('has end token', () async {
+ expect(functionSymbol.location.endTokenPos,
+ 78 + options.dartLangComment.length);
+ });
+ });
+ test('id in LibrarySymbol scopes', () async {
+ expect(functionSymbol.id, endsWith('foo.dart|topLevelFunction'));
+ expect(functionSymbol.id, librarySymbol.scopeIds.single);
+ });
+ });
+ group('top level private function debug symbols', () {
+ TestDriver driver;
+ FunctionSymbol functionSymbol;
+ LibrarySymbol librarySymbol;
+ final source = '''
+ ${options.dartLangComment}
+
+ void _topLevelFunction() {
+ return;
+ }
+ ''';
+ setUpAll(() async {
+ driver = TestDriver(options, source);
+ var result = await driver.compile();
+ functionSymbol = result.symbols.functions.single;
+ librarySymbol = result.symbols.libraries.single;
+ });
+ tearDownAll(() {
+ driver.cleanUp();
+ });
+ test('id in LibrarySymbol scopes', () async {
+ expect(functionSymbol.id, endsWith('foo.dart|_topLevelFunction'));
+ expect(functionSymbol.id, librarySymbol.scopeIds.single);
+ });
+ test('scopeId is LibrarySymbol id', () async {
+ expect(functionSymbol.scopeId, endsWith('package:foo/foo.dart'));
+ expect(functionSymbol.scopeId, librarySymbol.id);
+ });
+ });
+ group('top level public getter debug symbols', () {
+ TestDriver driver;
+ FunctionSymbol functionSymbol;
+ LibrarySymbol librarySymbol;
+ final source = '''
+ ${options.dartLangComment}
+
+ String get topLevelGetter => 'Cello';
+ ''';
+ setUpAll(() async {
+ driver = TestDriver(options, source);
+ var result = await driver.compile();
+ functionSymbol = result.symbols.functions.single;
+ librarySymbol = result.symbols.libraries.single;
+ });
+ tearDownAll(() {
+ driver.cleanUp();
+ });
+ test('id in LibrarySymbol scopes', () async {
+ expect(functionSymbol.id, endsWith('foo.dart|topLevelGetter'));
+ expect(functionSymbol.id, librarySymbol.scopeIds.single);
+ });
+ test('scopeId is LibrarySymbol id', () async {
+ expect(functionSymbol.scopeId, endsWith('package:foo/foo.dart'));
+ expect(functionSymbol.scopeId, librarySymbol.id);
+ });
+ test('is static', () async {
+ expect(functionSymbol.isStatic, isTrue);
+ });
+ });
+ group('top level private getter debug symbols', () {
+ TestDriver driver;
+ FunctionSymbol functionSymbol;
+ LibrarySymbol librarySymbol;
+ final source = '''
+ ${options.dartLangComment}
+
+ String get _topLevelGetter => 'Cello';
+ ''';
+ setUpAll(() async {
+ driver = TestDriver(options, source);
+ var result = await driver.compile();
+ functionSymbol = result.symbols.functions.single;
+ librarySymbol = result.symbols.libraries.single;
+ });
+ tearDownAll(() {
+ driver.cleanUp();
+ });
+ test('id in LibrarySymbol scopes', () async {
+ expect(functionSymbol.id, endsWith('foo.dart|_topLevelGetter'));
+ expect(functionSymbol.id, librarySymbol.scopeIds.single);
+ });
+ test('scopeId is LibrarySymbol id', () async {
+ expect(functionSymbol.scopeId, endsWith('package:foo/foo.dart'));
+ expect(functionSymbol.scopeId, librarySymbol.id);
+ });
+ test('is static', () async {
+ expect(functionSymbol.isStatic, isTrue);
+ });
+ });
+ group('top level public setter debug symbols', () {
+ TestDriver driver;
+ FunctionSymbol functionSymbol;
+ LibrarySymbol librarySymbol;
+ final source = '''
+ ${options.dartLangComment}
+ var _value;
+ set topLevelSetter(String v) => _value = v;
+ ''';
+ setUpAll(() async {
+ driver = TestDriver(options, source);
+ var result = await driver.compile();
+ functionSymbol = result.symbols.functions.single;
+ librarySymbol = result.symbols.libraries.single;
+ });
+ tearDownAll(() {
+ driver.cleanUp();
+ });
+ test('id in LibrarySymbol scopes', () async {
+ expect(functionSymbol.id, endsWith('foo.dart|topLevelSetter'));
+ expect(functionSymbol.id, librarySymbol.scopeIds.single);
+ });
+ test('scopeId is LibrarySymbol id', () async {
+ expect(functionSymbol.scopeId, endsWith('package:foo/foo.dart'));
+ expect(functionSymbol.scopeId, librarySymbol.id);
+ });
+ test('is static', () async {
+ expect(functionSymbol.isStatic, isTrue);
+ });
+ });
+ group('top level private setter debug symbols', () {
+ TestDriver driver;
+ FunctionSymbol functionSymbol;
+ LibrarySymbol librarySymbol;
+ final source = '''
+ ${options.dartLangComment}
+
+ var _value;
+ set _topLevelSetter(String v) => _value = v;
+ ''';
+ setUpAll(() async {
+ driver = TestDriver(options, source);
+ var result = await driver.compile();
+ functionSymbol = result.symbols.functions.single;
+ librarySymbol = result.symbols.libraries.single;
+ });
+ tearDownAll(() {
+ driver.cleanUp();
+ });
+ test('id in LibrarySymbol scopes', () async {
+ expect(functionSymbol.id, endsWith('foo.dart|_topLevelSetter'));
+ expect(functionSymbol.id, librarySymbol.scopeIds.single);
+ });
+ test('scopeId is LibrarySymbol id', () async {
+ expect(functionSymbol.scopeId, endsWith('package:foo/foo.dart'));
+ expect(functionSymbol.scopeId, librarySymbol.id);
+ });
+ test('is static', () async {
+ expect(functionSymbol.isStatic, isTrue);
+ });
+ });
+ group('function arguments debug symbols', () {
+ TestDriver driver;
+ FunctionSymbol functionWithPositionalArgSymbol;
+ FunctionSymbol functionWithOptionalArgSymbol;
+ FunctionSymbol functionWithNamedArgSymbol;
+ VariableSymbol xSymbol;
+ VariableSymbol ySymbol;
+ VariableSymbol zSymbol;
+ final source = '''
+ ${options.dartLangComment}
+
+ class A {
+ const A();
+ }
+ const a = A();
+ void functionWithPositionalArg(A x) {}
+ void functionWithOptionalArg([A y = a]) {}
+ void functionWithNamedArg({A z = a}) {}
+ ''';
+ setUpAll(() async {
+ driver = TestDriver(options, source);
+ var result = await driver.compile();
+ functionWithPositionalArgSymbol = result.symbols.functions
+ .singleWhere((f) => f.name == 'functionWithPositionalArg');
+ functionWithOptionalArgSymbol = result.symbols.functions
+ .singleWhere((f) => f.name == 'functionWithOptionalArg');
+ functionWithNamedArgSymbol = result.symbols.functions
+ .singleWhere((f) => f.name == 'functionWithNamedArg');
+ xSymbol = result.symbols.variables.singleWhere((v) => v.name == 'x');
+ ySymbol = result.symbols.variables.singleWhere((v) => v.name == 'y');
+ zSymbol = result.symbols.variables.singleWhere((v) => v.name == 'z');
+ });
+ tearDownAll(() {
+ driver.cleanUp();
+ });
+ test('function has a variable id for positional argument', () async {
+ var argumentId = functionWithPositionalArgSymbol.variableIds.single;
+ expect(argumentId, endsWith('|x'));
+ expect(argumentId, xSymbol.id);
+ });
+ test('positional argument symbol has a function scope', () async {
+ expect(xSymbol.scopeId, endsWith('|functionWithPositionalArg'));
+ expect(xSymbol.scopeId, functionWithPositionalArgSymbol.id);
+ });
+ test('function has a variable id for optional argument', () async {
+ var argumentId = functionWithOptionalArgSymbol.variableIds.single;
+ expect(argumentId, endsWith('|y'));
+ expect(argumentId, ySymbol.id);
+ });
+ test('optional argument symbol has a function scope', () async {
+ expect(ySymbol.scopeId, endsWith('|functionWithOptionalArg'));
+ expect(ySymbol.scopeId, functionWithOptionalArgSymbol.id);
+ });
+ test('function has a variable id for named argument', () async {
+ var argumentId = functionWithNamedArgSymbol.variableIds.single;
+ expect(argumentId, endsWith('|z'));
+ expect(argumentId, zSymbol.id);
+ });
+ test('named argument symbol has a function scope', () async {
+ expect(zSymbol.scopeId, endsWith('|functionWithNamedArg'));
+ expect(zSymbol.scopeId, functionWithNamedArgSymbol.id);
+ });
+ });
+ group('function local variable debug symbols', () {
+ TestDriver driver;
+ FunctionSymbol functionSymbol;
+ VariableSymbol variableSymbol;
+ final source = '''
+ ${options.dartLangComment}
+
+ int topLevelFunction() {
+ int i = 42;
+ return i;
+ }
+ ''';
+ setUpAll(() async {
+ driver = TestDriver(options, source);
+ var result = await driver.compile();
+ variableSymbol = result.symbols.variables.single;
+ functionSymbol = result.symbols.functions.single;
+ });
+ tearDownAll(() {
+ driver.cleanUp();
+ });
+ test('local variableId in FunctionSymbol', () async {
+ expect(variableSymbol.id, endsWith('|i'));
+ expect(variableSymbol.id, functionSymbol.variableIds.single);
+ });
+ test('scopeId is FunctionSymbol id', () async {
+ expect(variableSymbol.scopeId, endsWith('|topLevelFunction'));
+ expect(variableSymbol.scopeId, functionSymbol.id);
+ });
+ });
+ });
+ }
+}
diff --git a/pkg/dev_compiler/test/shared_test_options.dart b/pkg/dev_compiler/test/shared_test_options.dart
index 53d8879..88013a3 100644
--- a/pkg/dev_compiler/test/shared_test_options.dart
+++ b/pkg/dev_compiler/test/shared_test_options.dart
@@ -6,7 +6,6 @@
import 'package:cli_util/cli_util.dart';
import 'package:dev_compiler/dev_compiler.dart';
-import 'package:dev_compiler/src/compiler/module_builder.dart';
import 'package:front_end/src/api_unstable/ddc.dart';
import 'package:front_end/src/compute_platform_binaries_location.dart';
import 'package:front_end/src/fasta/incremental_serializer.dart';
diff --git a/pkg/front_end/lib/src/api_prototype/incremental_kernel_generator.dart b/pkg/front_end/lib/src/api_prototype/incremental_kernel_generator.dart
index 12614bb..a6d071f 100644
--- a/pkg/front_end/lib/src/api_prototype/incremental_kernel_generator.dart
+++ b/pkg/front_end/lib/src/api_prototype/incremental_kernel_generator.dart
@@ -42,7 +42,7 @@
/// Notice that the component has to include the platform, and that no other
/// platform will be loaded.
factory IncrementalKernelGenerator.fromComponent(
- CompilerOptions options, Uri entryPoint, Component component,
+ CompilerOptions options, Uri entryPoint, Component? component,
[bool? outlineOnly, IncrementalSerializer? incrementalSerializer]) {
return new IncrementalCompiler.fromComponent(
new CompilerContext(
@@ -72,7 +72,7 @@
/// Returns a component whose libraries are the recompiled libraries,
/// or - in the case of [fullComponent] - a full Component.
- Future<Component> computeDelta({List<Uri> entryPoints, bool fullComponent});
+ Future<Component> computeDelta({List<Uri>? entryPoints, bool fullComponent});
/// Returns [CoreTypes] used during compilation.
/// Valid after [computeDelta] is called.
@@ -136,7 +136,7 @@
List<TypeParameter> typeDefinitions,
String syntheticProcedureName,
Uri libraryUri,
- [String className,
+ [String? className,
bool isStatic = false]);
/// Sets experimental features.
diff --git a/pkg/front_end/lib/src/api_prototype/lowering_predicates.dart b/pkg/front_end/lib/src/api_prototype/lowering_predicates.dart
index cf307b8..d1a2a4e 100644
--- a/pkg/front_end/lib/src/api_prototype/lowering_predicates.dart
+++ b/pkg/front_end/lib/src/api_prototype/lowering_predicates.dart
@@ -280,22 +280,7 @@
block.statements.first is ExpressionStatement) {
ExpressionStatement firstStatement =
block.statements.first as ExpressionStatement;
- if (firstStatement.expression is PropertySet) {
- // We have
- //
- // get field {
- // if (!_#isSet#field) {
- // this._#field = <init>;
- // ...
- // }
- // return _#field;
- // }
- //
- // in case `<init>` is the initializer.
- PropertySet propertySet = firstStatement.expression as PropertySet;
- assert(propertySet.interfaceTarget == getLateFieldTarget(node));
- return propertySet.value;
- } else if (firstStatement.expression is InstanceSet) {
+ if (firstStatement.expression is InstanceSet) {
// We have
//
// get field {
@@ -368,15 +353,6 @@
//
// in which case there is no initializer.
return null;
- } else if (then is PropertySet) {
- // We have
- //
- // get field => let # = this._#field in <is-unset>
- // ? this._#field = <init> : #;
- //
- // in which case `<init>` is the initializer.
- assert(then.interfaceTarget == getLateFieldTarget(node));
- return then.value;
} else if (then is InstanceSet) {
// We have
//
diff --git a/pkg/front_end/lib/src/api_unstable/bazel_worker.dart b/pkg/front_end/lib/src/api_unstable/bazel_worker.dart
index 46566f1..8cf810b 100644
--- a/pkg/front_end/lib/src/api_unstable/bazel_worker.dart
+++ b/pkg/front_end/lib/src/api_unstable/bazel_worker.dart
@@ -58,7 +58,7 @@
/// Re-uses cached components from [oldState.workerInputCache], and reloads them
/// as necessary based on [workerInputDigests].
Future<InitializedCompilerState> initializeIncrementalCompiler(
- InitializedCompilerState oldState,
+ InitializedCompilerState? oldState,
Set<String> tags,
Uri sdkSummary,
Uri packagesFile,
@@ -99,7 +99,7 @@
}
Future<InitializedCompilerState> initializeCompiler(
- InitializedCompilerState oldState,
+ InitializedCompilerState? oldState,
Uri sdkSummary,
Uri librariesSpecificationUri,
Uri packagesFile,
diff --git a/pkg/front_end/lib/src/api_unstable/dart2js.dart b/pkg/front_end/lib/src/api_unstable/dart2js.dart
index d29d1ea..ee007f5 100644
--- a/pkg/front_end/lib/src/api_unstable/dart2js.dart
+++ b/pkg/front_end/lib/src/api_unstable/dart2js.dart
@@ -240,7 +240,7 @@
/// Desugar API to determine whether [member] is a redirecting factory
/// constructor.
-// TODO(sigmund): Delete this API once `member.isRedirectingFactoryConstructor`
+// TODO(sigmund): Delete this API once `member.isRedirectingFactory`
// is implemented correctly for patch files (Issue #33495).
bool isRedirectingFactory(ir.Procedure member) {
if (member.kind == ir.ProcedureKind.Factory) {
diff --git a/pkg/front_end/lib/src/api_unstable/vm.dart b/pkg/front_end/lib/src/api_unstable/vm.dart
index 35d7c8b..42a227f 100644
--- a/pkg/front_end/lib/src/api_unstable/vm.dart
+++ b/pkg/front_end/lib/src/api_unstable/vm.dart
@@ -53,6 +53,7 @@
messageFfiLeafCallMustNotReturnHandle,
messageFfiLeafCallMustNotTakeHandle,
messageFfiPackedAnnotationAlignment,
+ messageFfiNativeAnnotationMustAnnotateStatic,
messageNonPositiveArrayDimensions,
noLength,
templateFfiDartTypeMismatch,
diff --git a/pkg/front_end/lib/src/compute_platform_binaries_location.dart b/pkg/front_end/lib/src/compute_platform_binaries_location.dart
index 0ecacc07..96039c4 100644
--- a/pkg/front_end/lib/src/compute_platform_binaries_location.dart
+++ b/pkg/front_end/lib/src/compute_platform_binaries_location.dart
@@ -23,9 +23,17 @@
case 'dartdevc':
switch (nnbdMode) {
case NnbdMode.Strong:
- return 'ddc_platform_sound.dill';
+ // DDC is always compiled against the outline so we use it here by
+ // default.
+ return 'ddc_outline_sound.dill';
+ //TODO(johnniwinther): Support using the full dill.
+ //return 'ddc_platform_sound.dill';
case NnbdMode.Weak:
- return 'ddc_platform.dill';
+ // DDC is always compiled against the outline so we use it here by
+ // default.
+ return 'ddc_outline.dill';
+ //TODO(johnniwinther): Support using the full dill.
+ //return 'ddc_platform.dill';
case NnbdMode.Agnostic:
break;
}
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 7701321..4de08b9 100644
--- a/pkg/front_end/lib/src/fasta/builder/class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
@@ -42,7 +42,7 @@
import '../fasta_codes.dart';
-import '../kernel/redirecting_factory_body.dart' show getRedirectingFactoryBody;
+import '../kernel/kernel_helper.dart';
import '../loader.dart';
@@ -74,7 +74,7 @@
import 'named_type_builder.dart';
import 'never_type_declaration_builder.dart';
import 'nullability_builder.dart';
-import 'procedure_builder.dart';
+import 'factory_builder.dart';
import 'type_alias_builder.dart';
import 'type_builder.dart';
import 'type_declaration_builder.dart';
@@ -123,7 +123,8 @@
void buildOutlineExpressions(
SourceLibraryBuilder library,
CoreTypes coreTypes,
- List<DelayedActionPerformer> delayedActionPerformers);
+ List<DelayedActionPerformer> delayedActionPerformers,
+ List<SynthesizedFunctionNode> synthesizedFunctionNodes);
/// Registers a constructor redirection for this class and returns true if
/// this redirection gives rise to a cycle that has not been reported before.
@@ -343,11 +344,12 @@
void buildOutlineExpressions(
SourceLibraryBuilder library,
CoreTypes coreTypes,
- List<DelayedActionPerformer> delayedActionPerformers) {
+ List<DelayedActionPerformer> delayedActionPerformers,
+ List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
void build(String ignore, Builder declaration) {
MemberBuilder member = declaration as MemberBuilder;
- member.buildOutlineExpressions(
- library, coreTypes, delayedActionPerformers);
+ member.buildOutlineExpressions(library, coreTypes,
+ delayedActionPerformers, synthesizedFunctionNodes);
}
MetadataBuilder.buildAnnotations(
@@ -914,8 +916,7 @@
charOffset, fileUri);
}
- List<DartType>? typeArguments =
- getRedirectingFactoryBody(factory.procedure)!.typeArguments;
+ List<DartType>? typeArguments = factory.getTypeArguments();
FunctionType targetFunctionType =
targetNode.computeFunctionType(library.nonNullable);
if (typeArguments != null &&
@@ -1007,7 +1008,7 @@
// The factory type cannot contain any type parameters other than those of
// its enclosing class, because constructors cannot specify type parameters
// of their own.
- FunctionType factoryType = factory.procedure.function
+ FunctionType factoryType = factory.function
.computeThisFunctionType(library.nonNullable)
.withoutTypeParameters;
FunctionType? redirecteeType =
@@ -1129,6 +1130,10 @@
@override
Constructor? lookupConstructor(Name name, {bool isSuper: false}) {
+ if (name.text == "new") {
+ name = new Name("", name.library);
+ }
+
Class? instanceClass = cls;
if (isSuper) {
instanceClass = instanceClass.superclass;
diff --git a/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart b/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart
index f2810a8..4d0f32a 100644
--- a/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart
@@ -20,7 +20,7 @@
show ExpressionGeneratorHelper;
import '../kernel/kernel_builder.dart'
show isRedirectingGenerativeConstructorImplementation;
-import '../kernel/kernel_target.dart' show ClonedFunctionNode;
+import '../kernel/kernel_helper.dart' show SynthesizedFunctionNode;
import '../loader.dart' show Loader;
@@ -51,7 +51,6 @@
abstract class ConstructorBuilder implements FunctionBuilder {
abstract Token? beginInitializers;
- @override
ConstructorBuilder? get actualOrigin;
ConstructorBuilder? get patchForTesting;
@@ -139,7 +138,7 @@
..fileEndOffset = charEndOffset
..isNonNullableByDefault = compilationUnit.isNonNullableByDefault,
_constructorTearOff = createConstructorTearOffProcedure(
- name, compilationUnit, charOffset,
+ name, compilationUnit, compilationUnit.fileUri, charOffset,
forAbstractClassOrEnum: forAbstractClassOrEnum),
super(metadata, modifiers, returnType, name, typeVariables, formals,
compilationUnit, charOffset, nativeMethodName);
@@ -230,8 +229,8 @@
library == libraryBuilder,
"Unexpected library builder ${libraryBuilder} for"
" constructor $this in ${library}.");
- libraryBuilder.loader.typeInferenceEngine.toBeInferred[_constructor] =
- this;
+ libraryBuilder.loader
+ .registerConstructorToBeInferred(_constructor, this);
}
}
return _constructor;
@@ -248,12 +247,21 @@
}
}
+ bool _hasBuiltOutlines = false;
+
@override
void buildOutlineExpressions(
SourceLibraryBuilder library,
CoreTypes coreTypes,
- List<DelayedActionPerformer> delayedActionPerformers) {
- super.buildOutlineExpressions(library, coreTypes, delayedActionPerformers);
+ List<DelayedActionPerformer> delayedActionPerformers,
+ List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
+ if (_hasBuiltOutlines) return;
+ if (isConst && isPatch) {
+ origin.buildOutlineExpressions(library, coreTypes,
+ delayedActionPerformers, synthesizedFunctionNodes);
+ }
+ super.buildOutlineExpressions(
+ library, coreTypes, delayedActionPerformers, synthesizedFunctionNodes);
// For modular compilation purposes we need to include initializers
// for const constructors into the outline.
@@ -265,11 +273,11 @@
bodyBuilder.parseInitializers(beginInitializers!);
bodyBuilder.resolveRedirectingFactoryTargets();
}
- if (_constructorTearOff != null) {
- buildConstructorTearOffOutline(
- _constructorTearOff!, constructor, classBuilder!.cls);
- }
beginInitializers = null;
+ if (isConst && isPatch) {
+ _finishPatch();
+ }
+ _hasBuiltOutlines = true;
}
@override
@@ -391,10 +399,7 @@
return null;
}
- @override
- int finishPatch() {
- if (!isPatch) return 0;
-
+ void _finishPatch() {
// TODO(ahe): restore file-offset once we track both origin and patch file
// URIs. See https://github.com/dart-lang/sdk/issues/31579
origin.constructor.fileUri = fileUri;
@@ -409,6 +414,12 @@
origin.constructor.function.parent = origin.constructor;
origin.constructor.initializers = _constructor.initializers;
setParents(origin.constructor.initializers, origin.constructor);
+ }
+
+ @override
+ int finishPatch() {
+ if (!isPatch) return 0;
+ _finishPatch();
return 1;
}
@@ -441,7 +452,7 @@
// compile), and so we also clear them.
// Note: this method clears both initializers from the target Kernel node
// and internal state associated with parsing initializers.
- _constructor.initializers.length = 0;
+ _constructor.initializers = [];
redirectingInitializer = null;
superInitializer = null;
hasMovedSuperInitializer = false;
@@ -470,31 +481,33 @@
class SyntheticConstructorBuilder extends DillConstructorBuilder {
MemberBuilderImpl? _origin;
- ClonedFunctionNode? _clonedFunctionNode;
+ SynthesizedFunctionNode? _synthesizedFunctionNode;
SyntheticConstructorBuilder(SourceClassBuilder parent,
Constructor constructor, Procedure? constructorTearOff,
- {MemberBuilderImpl? origin, ClonedFunctionNode? clonedFunctionNode})
+ {MemberBuilderImpl? origin,
+ SynthesizedFunctionNode? synthesizedFunctionNode})
: _origin = origin,
- _clonedFunctionNode = clonedFunctionNode,
+ _synthesizedFunctionNode = synthesizedFunctionNode,
super(constructor, constructorTearOff, parent);
@override
void buildOutlineExpressions(
SourceLibraryBuilder libraryBuilder,
CoreTypes coreTypes,
- List<DelayedActionPerformer> delayedActionPerformers) {
+ List<DelayedActionPerformer> delayedActionPerformers,
+ List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
if (_origin != null) {
// Ensure that default value expressions have been created for [_origin].
LibraryBuilder originLibraryBuilder = _origin!.library;
if (originLibraryBuilder is SourceLibraryBuilder) {
// If [_origin] is from a source library, we need to build the default
// values and initializers first.
- _origin!.buildOutlineExpressions(
- originLibraryBuilder, coreTypes, delayedActionPerformers);
+ _origin!.buildOutlineExpressions(originLibraryBuilder, coreTypes,
+ delayedActionPerformers, synthesizedFunctionNodes);
}
- _clonedFunctionNode!.cloneDefaultValues();
- _clonedFunctionNode = null;
+ _synthesizedFunctionNode!.cloneDefaultValues();
+ _synthesizedFunctionNode = null;
_origin = null;
}
}
diff --git a/pkg/front_end/lib/src/fasta/builder/enum_builder.dart b/pkg/front_end/lib/src/fasta/builder/enum_builder.dart
index 8947531..98e54de 100644
--- a/pkg/front_end/lib/src/fasta/builder/enum_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/enum_builder.dart
@@ -21,7 +21,6 @@
ListLiteral,
Name,
ProcedureKind,
- PropertyGet,
Reference,
ReturnStatement,
StaticGet,
@@ -42,6 +41,8 @@
templateDuplicatedDeclarationSyntheticCause,
templateEnumConstantSameNameAsEnclosing;
+import '../kernel/kernel_helper.dart';
+
import '../util/helpers.dart';
import '../modifier.dart'
@@ -460,15 +461,10 @@
Field nameField = nameFieldBuilder.field;
ProcedureBuilder toStringBuilder =
firstMemberNamed("toString") as ProcedureBuilder;
- if (libraryBuilder
- .loader.target.backendTarget.supportsNewMethodInvocationEncoding) {
- toStringBuilder.body = new ReturnStatement(new InstanceGet(
- InstanceAccessKind.Instance, new ThisExpression(), nameField.name,
- interfaceTarget: nameField, resultType: nameField.type));
- } else {
- toStringBuilder.body = new ReturnStatement(
- new PropertyGet(new ThisExpression(), nameField.name, nameField));
- }
+ toStringBuilder.body = new ReturnStatement(new InstanceGet(
+ InstanceAccessKind.Instance, new ThisExpression(), nameField.name,
+ interfaceTarget: nameField, resultType: nameField.type));
+
List<Expression> values = <Expression>[];
if (enumConstantInfos != null) {
for (EnumConstantInfo? enumConstantInfo in enumConstantInfos!) {
@@ -520,7 +516,8 @@
void buildOutlineExpressions(
SourceLibraryBuilder libraryBuilder,
CoreTypes coreTypes,
- List<DelayedActionPerformer> delayedActionPerformers) {
+ List<DelayedActionPerformer> delayedActionPerformers,
+ List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
List<Expression> values = <Expression>[];
if (enumConstantInfos != null) {
for (EnumConstantInfo? enumConstantInfo in enumConstantInfos!) {
@@ -564,7 +561,8 @@
}
}
}
- super.buildOutlineExpressions(library, coreTypes, delayedActionPerformers);
+ super.buildOutlineExpressions(
+ library, coreTypes, delayedActionPerformers, synthesizedFunctionNodes);
}
@override
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 0ca4e45..d0250bf 100644
--- a/pkg/front_end/lib/src/fasta/builder/extension_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/extension_builder.dart
@@ -7,6 +7,7 @@
import '../fasta_codes.dart'
show templateInternalProblemNotFoundIn, templateTypeArgumentMismatch;
+import '../kernel/kernel_helper.dart';
import '../scope.dart';
import '../source/source_library_builder.dart';
import '../problems.dart';
@@ -36,7 +37,8 @@
void buildOutlineExpressions(
SourceLibraryBuilder library,
CoreTypes coreTypes,
- List<DelayedActionPerformer> delayedActionPerformers);
+ List<DelayedActionPerformer> delayedActionPerformers,
+ List<SynthesizedFunctionNode> synthesizedFunctionNodes);
/// Looks up extension member by [name] taking privacy into account.
///
diff --git a/pkg/front_end/lib/src/fasta/builder/factory_builder.dart b/pkg/front_end/lib/src/fasta/builder/factory_builder.dart
new file mode 100644
index 0000000..22e54cb
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/builder/factory_builder.dart
@@ -0,0 +1,467 @@
+// Copyright (c) 2019, 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.
+
+import 'package:kernel/ast.dart';
+import 'package:kernel/type_algebra.dart';
+
+import '../dill/dill_member_builder.dart';
+
+import '../kernel/class_hierarchy_builder.dart';
+import '../kernel/constructor_tearoff_lowering.dart';
+import '../kernel/forest.dart';
+import '../kernel/internal_ast.dart';
+import '../kernel/kernel_api.dart';
+import '../kernel/kernel_helper.dart';
+import '../kernel/redirecting_factory_body.dart'
+ show getRedirectingFactoryBody, RedirectingFactoryBody;
+
+import '../loader.dart' show Loader;
+
+import '../messages.dart'
+ show messageConstFactoryRedirectionToNonConst, noLength;
+
+import '../problems.dart' show unexpected, unhandled;
+
+import '../source/source_library_builder.dart' show SourceLibraryBuilder;
+
+import '../type_inference/type_inferrer.dart';
+import '../type_inference/type_schema.dart';
+
+import '../util/helpers.dart';
+
+import 'builder.dart';
+import 'constructor_reference_builder.dart';
+import 'formal_parameter_builder.dart';
+import 'function_builder.dart';
+import 'member_builder.dart';
+import 'metadata_builder.dart';
+import 'procedure_builder.dart';
+import 'type_builder.dart';
+import 'type_variable_builder.dart';
+
+class SourceFactoryBuilder extends FunctionBuilderImpl {
+ final int charOpenParenOffset;
+
+ AsyncMarker actualAsyncModifier = AsyncMarker.Sync;
+
+ final bool isExtensionInstanceMember = false;
+
+ final Procedure _procedureInternal;
+ final Procedure? _factoryTearOff;
+
+ SourceFactoryBuilder? actualOrigin;
+
+ SourceFactoryBuilder(
+ List<MetadataBuilder>? metadata,
+ int modifiers,
+ TypeBuilder returnType,
+ String name,
+ List<TypeVariableBuilder> typeVariables,
+ List<FormalParameterBuilder>? formals,
+ SourceLibraryBuilder libraryBuilder,
+ int startCharOffset,
+ int charOffset,
+ this.charOpenParenOffset,
+ int charEndOffset,
+ Reference? procedureReference,
+ AsyncMarker asyncModifier,
+ ProcedureNameScheme procedureNameScheme,
+ {String? nativeMethodName})
+ : _procedureInternal = new Procedure(
+ procedureNameScheme.getName(ProcedureKind.Factory, name),
+ ProcedureKind.Factory,
+ new FunctionNode(null),
+ fileUri: libraryBuilder.fileUri,
+ reference: procedureReference)
+ ..startFileOffset = startCharOffset
+ ..fileOffset = charOffset
+ ..fileEndOffset = charEndOffset
+ ..isNonNullableByDefault = libraryBuilder.isNonNullableByDefault,
+ _factoryTearOff = createFactoryTearOffProcedure(
+ name, libraryBuilder, libraryBuilder.fileUri, charOffset),
+ super(metadata, modifiers, returnType, name, typeVariables, formals,
+ libraryBuilder, charOffset, nativeMethodName) {
+ this.asyncModifier = asyncModifier;
+ }
+
+ SourceFactoryBuilder? get patchForTesting =>
+ dataForTesting?.patchForTesting as SourceFactoryBuilder?;
+
+ @override
+ AsyncMarker get asyncModifier => actualAsyncModifier;
+
+ @override
+ Statement? get body {
+ if (bodyInternal == null && !isAbstract && !isExternal) {
+ bodyInternal = new EmptyStatement();
+ }
+ return bodyInternal;
+ }
+
+ void set asyncModifier(AsyncMarker newModifier) {
+ actualAsyncModifier = newModifier;
+ function.asyncMarker = actualAsyncModifier;
+ function.dartAsyncMarker = actualAsyncModifier;
+ }
+
+ @override
+ Member get member => _procedure;
+
+ @override
+ SourceFactoryBuilder get origin => actualOrigin ?? this;
+
+ @override
+ ProcedureKind get kind => ProcedureKind.Factory;
+
+ Procedure get _procedure => isPatch ? origin._procedure : _procedureInternal;
+
+ @override
+ FunctionNode get function => _procedureInternal.function;
+
+ @override
+ Member? get readTarget => origin._factoryTearOff ?? _procedure;
+
+ @override
+ Member? get writeTarget => null;
+
+ @override
+ Member? get invokeTarget => _procedure;
+
+ @override
+ Iterable<Member> get exportedMembers => [_procedure];
+
+ @override
+ void buildMembers(
+ SourceLibraryBuilder library, void Function(Member, BuiltMemberKind) f) {
+ Member member = build(library);
+ f(member, BuiltMemberKind.Method);
+ if (_factoryTearOff != null) {
+ f(_factoryTearOff!, BuiltMemberKind.Method);
+ }
+ }
+
+ @override
+ Procedure build(SourceLibraryBuilder libraryBuilder) {
+ buildFunction(libraryBuilder);
+ _procedureInternal.function.fileOffset = charOpenParenOffset;
+ _procedureInternal.function.fileEndOffset =
+ _procedureInternal.fileEndOffset;
+ _procedureInternal.isAbstract = isAbstract;
+ _procedureInternal.isExternal = isExternal;
+ _procedureInternal.isConst = isConst;
+ updatePrivateMemberName(_procedureInternal, libraryBuilder);
+ _procedureInternal.isStatic = isStatic;
+
+ if (_factoryTearOff != null) {
+ buildConstructorTearOffProcedure(_factoryTearOff!, _procedureInternal,
+ classBuilder!.cls, libraryBuilder);
+ }
+ return _procedureInternal;
+ }
+
+ bool _hasBuiltOutlines = false;
+
+ @override
+ void buildOutlineExpressions(
+ SourceLibraryBuilder library,
+ CoreTypes coreTypes,
+ List<DelayedActionPerformer> delayedActionPerformers,
+ List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
+ if (_hasBuiltOutlines) return;
+ super.buildOutlineExpressions(
+ library, coreTypes, delayedActionPerformers, synthesizedFunctionNodes);
+ _hasBuiltOutlines = true;
+ }
+
+ @override
+ VariableDeclaration? getTearOffParameter(int index) {
+ if (_factoryTearOff != null) {
+ if (index < _factoryTearOff!.function.positionalParameters.length) {
+ return _factoryTearOff!.function.positionalParameters[index];
+ } else {
+ index -= _factoryTearOff!.function.positionalParameters.length;
+ if (index < _factoryTearOff!.function.namedParameters.length) {
+ return _factoryTearOff!.function.namedParameters[index];
+ }
+ }
+ }
+ return null;
+ }
+
+ @override
+ List<ClassMember> get localMembers =>
+ throw new UnsupportedError('${runtimeType}.localMembers');
+
+ @override
+ List<ClassMember> get localSetters =>
+ throw new UnsupportedError('${runtimeType}.localSetters');
+
+ @override
+ void becomeNative(Loader loader) {
+ _procedureInternal.isExternal = true;
+ super.becomeNative(loader);
+ }
+
+ void setRedirectingFactoryBody(Member target, List<DartType> typeArguments) {
+ if (bodyInternal != null) {
+ unexpected("null", "${bodyInternal.runtimeType}", charOffset, fileUri);
+ }
+ bodyInternal = new RedirectingFactoryBody(target, typeArguments);
+ function.body = bodyInternal;
+ bodyInternal?.parent = function;
+ if (isPatch) {
+ actualOrigin!.setRedirectingFactoryBody(target, typeArguments);
+ }
+ }
+
+ @override
+ void applyPatch(Builder patch) {
+ if (patch is SourceFactoryBuilder) {
+ if (checkPatch(patch)) {
+ patch.actualOrigin = this;
+ dataForTesting?.patchForTesting = patch;
+ }
+ } else {
+ reportPatchMismatch(patch);
+ }
+ }
+
+ void _finishPatch() {
+ // TODO(ahe): restore file-offset once we track both origin and patch file
+ // URIs. See https://github.com/dart-lang/sdk/issues/31579
+ origin._procedure.fileUri = fileUri;
+ origin._procedure.startFileOffset = _procedureInternal.startFileOffset;
+ origin._procedure.fileOffset = _procedureInternal.fileOffset;
+ origin._procedure.fileEndOffset = _procedureInternal.fileEndOffset;
+ origin._procedure.annotations
+ .forEach((m) => m.fileOffset = _procedureInternal.fileOffset);
+
+ origin._procedure.isAbstract = _procedureInternal.isAbstract;
+ origin._procedure.isExternal = _procedureInternal.isExternal;
+ origin._procedure.function = _procedureInternal.function;
+ origin._procedure.function.parent = origin._procedure;
+ origin._procedure.isRedirectingFactory =
+ _procedureInternal.isRedirectingFactory;
+ }
+
+ @override
+ int finishPatch() {
+ if (!isPatch) return 0;
+ _finishPatch();
+ return 1;
+ }
+}
+
+class RedirectingFactoryBuilder extends SourceFactoryBuilder {
+ final ConstructorReferenceBuilder redirectionTarget;
+ List<DartType>? typeArguments;
+
+ FreshTypeParameters? _tearOffTypeParameters;
+
+ RedirectingFactoryBuilder(
+ List<MetadataBuilder>? metadata,
+ int modifiers,
+ TypeBuilder returnType,
+ String name,
+ List<TypeVariableBuilder> typeVariables,
+ List<FormalParameterBuilder>? formals,
+ SourceLibraryBuilder libraryBuilder,
+ int startCharOffset,
+ int charOffset,
+ int charOpenParenOffset,
+ int charEndOffset,
+ Reference? procedureReference,
+ ProcedureNameScheme procedureNameScheme,
+ String? nativeMethodName,
+ this.redirectionTarget)
+ : super(
+ metadata,
+ modifiers,
+ returnType,
+ name,
+ typeVariables,
+ formals,
+ libraryBuilder,
+ startCharOffset,
+ charOffset,
+ charOpenParenOffset,
+ charEndOffset,
+ procedureReference,
+ AsyncMarker.Sync,
+ procedureNameScheme,
+ nativeMethodName: nativeMethodName);
+
+ @override
+ Statement? get body => bodyInternal;
+
+ @override
+ void setRedirectingFactoryBody(Member target, List<DartType> typeArguments) {
+ if (bodyInternal != null) {
+ unexpected("null", "${bodyInternal.runtimeType}", charOffset, fileUri);
+ }
+
+ // Ensure that constant factories only have constant targets/bodies.
+ if (isConst && !target.isConst) {
+ library.addProblem(messageConstFactoryRedirectionToNonConst, charOffset,
+ noLength, fileUri);
+ }
+
+ bodyInternal = new RedirectingFactoryBody(target, typeArguments);
+ function.body = bodyInternal;
+ bodyInternal?.parent = function;
+ _procedure.isRedirectingFactory = true;
+ if (isPatch) {
+ // ignore: unnecessary_null_comparison
+ if (function.typeParameters != null) {
+ Map<TypeParameter, DartType> substitution = <TypeParameter, DartType>{};
+ for (int i = 0; i < function.typeParameters.length; i++) {
+ substitution[function.typeParameters[i]] =
+ new TypeParameterType.withDefaultNullabilityForLibrary(
+ actualOrigin!.function.typeParameters[i], library.library);
+ }
+ typeArguments = new List<DartType>.generate(typeArguments.length,
+ (int i) => substitute(typeArguments[i], substitution),
+ growable: false);
+ }
+ actualOrigin!.setRedirectingFactoryBody(target, typeArguments);
+ }
+ }
+
+ @override
+ void buildMembers(
+ SourceLibraryBuilder library, void Function(Member, BuiltMemberKind) f) {
+ Member member = build(library);
+ f(member, BuiltMemberKind.RedirectingFactory);
+ if (_factoryTearOff != null) {
+ f(_factoryTearOff!, BuiltMemberKind.Method);
+ }
+ }
+
+ @override
+ Procedure build(SourceLibraryBuilder libraryBuilder) {
+ buildFunction(libraryBuilder);
+ _procedureInternal.function.fileOffset = charOpenParenOffset;
+ _procedureInternal.function.fileEndOffset =
+ _procedureInternal.fileEndOffset;
+ _procedureInternal.isAbstract = isAbstract;
+ _procedureInternal.isExternal = isExternal;
+ _procedureInternal.isConst = isConst;
+ _procedureInternal.isStatic = isStatic;
+ _procedureInternal.isRedirectingFactory = true;
+ if (redirectionTarget.typeArguments != null) {
+ typeArguments = new List<DartType>.generate(
+ redirectionTarget.typeArguments!.length,
+ (int i) => redirectionTarget.typeArguments![i].build(library),
+ growable: false);
+ }
+ updatePrivateMemberName(_procedureInternal, libraryBuilder);
+ if (_factoryTearOff != null) {
+ _tearOffTypeParameters =
+ buildRedirectingFactoryTearOffProcedureParameters(
+ _factoryTearOff!, _procedureInternal, libraryBuilder);
+ }
+ return _procedureInternal;
+ }
+
+ bool _hasBuiltOutlines = false;
+
+ @override
+ void buildOutlineExpressions(
+ SourceLibraryBuilder library,
+ CoreTypes coreTypes,
+ List<DelayedActionPerformer> delayedActionPerformers,
+ List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
+ if (_hasBuiltOutlines) return;
+ if (isConst && isPatch) {
+ origin.buildOutlineExpressions(library, coreTypes,
+ delayedActionPerformers, synthesizedFunctionNodes);
+ }
+ super.buildOutlineExpressions(
+ library, coreTypes, delayedActionPerformers, synthesizedFunctionNodes);
+ RedirectingFactoryBody redirectingFactoryBody =
+ _procedureInternal.function.body as RedirectingFactoryBody;
+ List<DartType>? typeArguments = redirectingFactoryBody.typeArguments;
+ Member? target = redirectingFactoryBody.target;
+ if (typeArguments != null && typeArguments.any((t) => t is UnknownType)) {
+ TypeInferrerImpl inferrer = library.loader.typeInferenceEngine
+ .createLocalTypeInferrer(
+ fileUri, classBuilder!.thisType, library, null)
+ as TypeInferrerImpl;
+ inferrer.helper = library.loader.createBodyBuilderForOutlineExpression(
+ library, classBuilder, this, classBuilder!.scope, fileUri);
+ Builder? targetBuilder = redirectionTarget.target;
+ if (targetBuilder is FunctionBuilder) {
+ target = targetBuilder.member;
+ } else if (targetBuilder is DillMemberBuilder) {
+ target = targetBuilder.member;
+ } else {
+ unhandled("${targetBuilder.runtimeType}", "buildOutlineExpressions",
+ charOffset, fileUri);
+ }
+ Arguments targetInvocationArguments;
+ {
+ List<Expression> positionalArguments = <Expression>[];
+ for (VariableDeclaration parameter
+ in _procedure.function.positionalParameters) {
+ inferrer.flowAnalysis.declare(parameter, true);
+ positionalArguments
+ .add(new VariableGetImpl(parameter, forNullGuardedAccess: false));
+ }
+ List<NamedExpression> namedArguments = <NamedExpression>[];
+ for (VariableDeclaration parameter
+ in _procedure.function.namedParameters) {
+ inferrer.flowAnalysis.declare(parameter, true);
+ namedArguments.add(new NamedExpression(parameter.name!,
+ new VariableGetImpl(parameter, forNullGuardedAccess: false)));
+ }
+ // If arguments are created using [Forest.createArguments], and the
+ // type arguments are omitted, they are to be inferred.
+ targetInvocationArguments = const Forest().createArguments(
+ _procedure.fileOffset, positionalArguments,
+ named: namedArguments);
+ }
+ InvocationInferenceResult result = inferrer.inferInvocation(
+ function.returnType,
+ charOffset,
+ target.function!.computeFunctionType(Nullability.nonNullable),
+ targetInvocationArguments,
+ staticTarget: target);
+ if (result.inferredType is InterfaceType) {
+ typeArguments = (result.inferredType as InterfaceType).typeArguments;
+ } else {
+ // Assume that the error is reported elsewhere, use 'dynamic' for
+ // recovery.
+ typeArguments = new List<DartType>.filled(
+ target.enclosingClass!.typeParameters.length, const DynamicType(),
+ growable: true);
+ }
+ member.function!.body = new RedirectingFactoryBody(target, typeArguments);
+ }
+ if (_factoryTearOff != null &&
+ (target is Constructor || target is Procedure && target.isFactory)) {
+ synthesizedFunctionNodes.add(buildRedirectingFactoryTearOffBody(
+ _factoryTearOff!,
+ target!,
+ typeArguments ?? [],
+ _tearOffTypeParameters!));
+ }
+ if (isConst && isPatch) {
+ _finishPatch();
+ }
+ _hasBuiltOutlines = true;
+ }
+
+ void _finishPatch() {
+ super._finishPatch();
+
+ SourceFactoryBuilder redirectingOrigin = origin;
+ if (redirectingOrigin is RedirectingFactoryBuilder) {
+ redirectingOrigin.typeArguments = typeArguments;
+ }
+ }
+
+ List<DartType>? getTypeArguments() {
+ return getRedirectingFactoryBody(_procedure)!.typeArguments;
+ }
+}
diff --git a/pkg/front_end/lib/src/fasta/builder/field_builder.dart b/pkg/front_end/lib/src/fasta/builder/field_builder.dart
index 12b9103..eceff88 100644
--- a/pkg/front_end/lib/src/fasta/builder/field_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/field_builder.dart
@@ -17,6 +17,7 @@
import '../kernel/body_builder.dart' show BodyBuilder;
import '../kernel/class_hierarchy_builder.dart';
import '../kernel/kernel_builder.dart' show ImplicitFieldType;
+import '../kernel/kernel_helper.dart';
import '../kernel/late_lowering.dart' as late_lowering;
import '../kernel/member_covariance.dart';
@@ -329,11 +330,7 @@
internalProblem(
messageInternalProblemAlreadyInitialized, charOffset, fileUri);
}
- _fieldEncoding.createBodies(
- coreTypes,
- initializer,
- library
- .loader.target.backendTarget.supportsNewMethodInvocationEncoding);
+ _fieldEncoding.createBodies(coreTypes, initializer);
}
@override
@@ -398,7 +395,8 @@
void buildOutlineExpressions(
SourceLibraryBuilder library,
CoreTypes coreTypes,
- List<DelayedActionPerformer> delayedActionPerformers) {
+ List<DelayedActionPerformer> delayedActionPerformers,
+ List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
_fieldEncoding.completeSignature(coreTypes);
for (Annotatable annotatable in _fieldEncoding.annotatables) {
@@ -612,8 +610,7 @@
///
/// This method is not called for fields in outlines unless their are constant
/// or part of a const constructor.
- void createBodies(CoreTypes coreTypes, Expression? initializer,
- bool useNewMethodInvocationEncoding);
+ void createBodies(CoreTypes coreTypes, Expression? initializer);
List<Initializer> createInitializer(int fileOffset, Expression value,
{required bool isSynthetic});
@@ -723,8 +720,7 @@
void completeSignature(CoreTypes coreTypes) {}
@override
- void createBodies(CoreTypes coreTypes, Expression? initializer,
- bool useNewMethodInvocationEncoding) {
+ void createBodies(CoreTypes coreTypes, Expression? initializer) {
if (initializer != null) {
_field.initializer = initializer..parent = _field;
}
@@ -960,8 +956,7 @@
}
@override
- void createBodies(CoreTypes coreTypes, Expression? initializer,
- bool useNewMethodInvocationEncoding) {
+ void createBodies(CoreTypes coreTypes, Expression? initializer) {
assert(_type != null, "Type has not been computed for field $name.");
if (isSetEncoding == late_lowering.IsSetEncoding.useSentinel) {
_field.initializer = new StaticInvocation(coreTypes.createSentinelMethod,
@@ -978,15 +973,11 @@
..fileOffset = fileOffset
..parent = _lateIsSetField;
}
- _lateGetter.function.body = _createGetterBody(
- coreTypes, name, initializer, useNewMethodInvocationEncoding)
+ _lateGetter.function.body = _createGetterBody(coreTypes, name, initializer)
..parent = _lateGetter.function;
if (_lateSetter != null) {
_lateSetter!.function.body = _createSetterBody(
- coreTypes,
- name,
- _lateSetter!.function.positionalParameters.first,
- useNewMethodInvocationEncoding)
+ coreTypes, name, _lateSetter!.function.positionalParameters.first)
..parent = _lateSetter!.function;
}
}
@@ -1013,62 +1004,48 @@
/// expression that promotes the expression to [_type]. This is needed for a
/// sound encoding of fields with type variable type of undetermined
/// nullability.
- Expression _createFieldRead(bool useNewMethodInvocationEncoding,
- {bool needsPromotion: false}) {
+ Expression _createFieldRead({bool needsPromotion: false}) {
assert(_type != null, "Type has not been computed for field $name.");
if (needsPromotion) {
VariableDeclaration variable = new VariableDeclaration.forValue(
- _createFieldGet(_field, useNewMethodInvocationEncoding),
+ _createFieldGet(_field),
type: _type!.withDeclaredNullability(Nullability.nullable))
..fileOffset = fileOffset;
return new Let(
variable, new VariableGet(variable, _type)..fileOffset = fileOffset);
} else {
- return _createFieldGet(_field, useNewMethodInvocationEncoding);
+ return _createFieldGet(_field);
}
}
/// Creates an [Expression] that reads [field].
- Expression _createFieldGet(Field field, bool useNewMethodInvocationEncoding) {
+ Expression _createFieldGet(Field field) {
if (field.isStatic) {
return new StaticGet(field)..fileOffset = fileOffset;
} else {
- if (useNewMethodInvocationEncoding) {
- // No substitution needed for the result type, since any type variables
- // in there are also in scope at the access site.
- return new InstanceGet(InstanceAccessKind.Instance,
- new ThisExpression()..fileOffset = fileOffset, field.name,
- interfaceTarget: field, resultType: field.type)
- ..fileOffset = fileOffset;
- } else {
- return new PropertyGet(
- new ThisExpression()..fileOffset = fileOffset, field.name, field)
- ..fileOffset = fileOffset;
- }
+ // No substitution needed for the result type, since any type variables
+ // in there are also in scope at the access site.
+ return new InstanceGet(InstanceAccessKind.Instance,
+ new ThisExpression()..fileOffset = fileOffset, field.name,
+ interfaceTarget: field, resultType: field.type)
+ ..fileOffset = fileOffset;
}
}
/// Creates an [Expression] that writes [value] to [field].
- Expression _createFieldSet(
- Field field, Expression value, bool useNewMethodInvocationEncoding) {
+ Expression _createFieldSet(Field field, Expression value) {
if (field.isStatic) {
return new StaticSet(field, value)..fileOffset = fileOffset;
} else {
- if (useNewMethodInvocationEncoding) {
- return new InstanceSet(InstanceAccessKind.Instance,
- new ThisExpression()..fileOffset = fileOffset, field.name, value,
- interfaceTarget: field)
- ..fileOffset = fileOffset;
- } else {
- return new PropertySet(new ThisExpression()..fileOffset = fileOffset,
- field.name, value, field)
- ..fileOffset = fileOffset;
- }
+ return new InstanceSet(InstanceAccessKind.Instance,
+ new ThisExpression()..fileOffset = fileOffset, field.name, value,
+ interfaceTarget: field)
+ ..fileOffset = fileOffset;
}
}
- Statement _createGetterBody(CoreTypes coreTypes, String name,
- Expression? initializer, bool useNewMethodInvocationEncoding);
+ Statement _createGetterBody(
+ CoreTypes coreTypes, String name, Expression? initializer);
Procedure? _createSetter(
Name name, Uri fileUri, int charOffset, Reference? reference,
@@ -1092,8 +1069,8 @@
..isNonNullableByDefault = true;
}
- Statement _createSetterBody(CoreTypes coreTypes, String name,
- VariableDeclaration parameter, bool useNewMethodInvocationEncoding);
+ Statement _createSetterBody(
+ CoreTypes coreTypes, String name, VariableDeclaration parameter);
@override
DartType get type {
@@ -1253,30 +1230,29 @@
mixin NonFinalLate on AbstractLateFieldEncoding {
@override
- Statement _createSetterBody(CoreTypes coreTypes, String name,
- VariableDeclaration parameter, bool useNewMethodInvocationEncoding) {
+ Statement _createSetterBody(
+ CoreTypes coreTypes, String name, VariableDeclaration parameter) {
assert(_type != null, "Type has not been computed for field $name.");
return late_lowering.createSetterBody(
coreTypes, fileOffset, name, parameter, _type!,
shouldReturnValue: false,
createVariableWrite: (Expression value) =>
- _createFieldSet(_field, value, useNewMethodInvocationEncoding),
- createIsSetWrite: (Expression value) => _createFieldSet(
- _lateIsSetField!, value, useNewMethodInvocationEncoding),
+ _createFieldSet(_field, value),
+ createIsSetWrite: (Expression value) =>
+ _createFieldSet(_lateIsSetField!, value),
isSetEncoding: isSetEncoding);
}
}
mixin LateWithoutInitializer on AbstractLateFieldEncoding {
@override
- Statement _createGetterBody(CoreTypes coreTypes, String name,
- Expression? initializer, bool useNewMethodInvocationEncoding) {
+ Statement _createGetterBody(
+ CoreTypes coreTypes, String name, Expression? initializer) {
assert(_type != null, "Type has not been computed for field $name.");
return late_lowering.createGetterBodyWithoutInitializer(
- coreTypes, fileOffset, name, type, useNewMethodInvocationEncoding,
+ coreTypes, fileOffset, name, type,
createVariableRead: _createFieldRead,
- createIsSetRead: () =>
- _createFieldGet(_lateIsSetField!, useNewMethodInvocationEncoding),
+ createIsSetRead: () => _createFieldGet(_lateIsSetField!),
isSetEncoding: isSetEncoding,
forField: true);
}
@@ -1346,18 +1322,17 @@
isSetStrategy);
@override
- Statement _createGetterBody(CoreTypes coreTypes, String name,
- Expression? initializer, bool useNewMethodInvocationEncoding) {
+ Statement _createGetterBody(
+ CoreTypes coreTypes, String name, Expression? initializer) {
assert(_type != null, "Type has not been computed for field $name.");
- return late_lowering.createGetterWithInitializer(coreTypes, fileOffset,
- name, _type!, initializer!, useNewMethodInvocationEncoding,
+ return late_lowering.createGetterWithInitializer(
+ coreTypes, fileOffset, name, _type!, initializer!,
createVariableRead: _createFieldRead,
createVariableWrite: (Expression value) =>
- _createFieldSet(_field, value, useNewMethodInvocationEncoding),
- createIsSetRead: () =>
- _createFieldGet(_lateIsSetField!, useNewMethodInvocationEncoding),
- createIsSetWrite: (Expression value) => _createFieldSet(
- _lateIsSetField!, value, useNewMethodInvocationEncoding),
+ _createFieldSet(_field, value),
+ createIsSetRead: () => _createFieldGet(_lateIsSetField!),
+ createIsSetWrite: (Expression value) =>
+ _createFieldSet(_lateIsSetField!, value),
isSetEncoding: isSetEncoding);
}
}
@@ -1394,20 +1369,18 @@
isSetStrategy);
@override
- Statement _createSetterBody(CoreTypes coreTypes, String name,
- VariableDeclaration parameter, bool useNewMethodInvocationEncoding) {
+ Statement _createSetterBody(
+ CoreTypes coreTypes, String name, VariableDeclaration parameter) {
assert(_type != null, "Type has not been computed for field $name.");
- return late_lowering.createSetterBodyFinal(coreTypes, fileOffset, name,
- parameter, type, useNewMethodInvocationEncoding,
+ return late_lowering.createSetterBodyFinal(
+ coreTypes, fileOffset, name, parameter, type,
shouldReturnValue: false,
- createVariableRead: (bool useNewMethodInvocationEncoding) =>
- _createFieldGet(_field, useNewMethodInvocationEncoding),
+ createVariableRead: () => _createFieldGet(_field),
createVariableWrite: (Expression value) =>
- _createFieldSet(_field, value, useNewMethodInvocationEncoding),
- createIsSetRead: () =>
- _createFieldGet(_lateIsSetField!, useNewMethodInvocationEncoding),
- createIsSetWrite: (Expression value) => _createFieldSet(
- _lateIsSetField!, value, useNewMethodInvocationEncoding),
+ _createFieldSet(_field, value),
+ createIsSetRead: () => _createFieldGet(_lateIsSetField!),
+ createIsSetWrite: (Expression value) =>
+ _createFieldSet(_lateIsSetField!, value),
isSetEncoding: isSetEncoding,
forField: true);
}
@@ -1443,18 +1416,17 @@
isCovariant,
isSetStrategy);
@override
- Statement _createGetterBody(CoreTypes coreTypes, String name,
- Expression? initializer, bool useNewMethodInvocationEncoding) {
+ Statement _createGetterBody(
+ CoreTypes coreTypes, String name, Expression? initializer) {
assert(_type != null, "Type has not been computed for field $name.");
- return late_lowering.createGetterWithInitializerWithRecheck(coreTypes,
- fileOffset, name, _type!, initializer!, useNewMethodInvocationEncoding,
+ return late_lowering.createGetterWithInitializerWithRecheck(
+ coreTypes, fileOffset, name, _type!, initializer!,
createVariableRead: _createFieldRead,
createVariableWrite: (Expression value) =>
- _createFieldSet(_field, value, useNewMethodInvocationEncoding),
- createIsSetRead: () =>
- _createFieldGet(_lateIsSetField!, useNewMethodInvocationEncoding),
- createIsSetWrite: (Expression value) => _createFieldSet(
- _lateIsSetField!, value, useNewMethodInvocationEncoding),
+ _createFieldSet(_field, value),
+ createIsSetRead: () => _createFieldGet(_lateIsSetField!),
+ createIsSetWrite: (Expression value) =>
+ _createFieldSet(_lateIsSetField!, value),
isSetEncoding: isSetEncoding,
forField: true);
}
@@ -1466,8 +1438,8 @@
null;
@override
- Statement _createSetterBody(CoreTypes coreTypes, String name,
- VariableDeclaration parameter, bool useNewMethodInvocationEncoding) =>
+ Statement _createSetterBody(
+ CoreTypes coreTypes, String name, VariableDeclaration parameter) =>
throw new UnsupportedError(
'$runtimeType._createSetterBody is not supported.');
}
@@ -1690,8 +1662,7 @@
void completeSignature(CoreTypes coreTypes) {}
@override
- void createBodies(CoreTypes coreTypes, Expression? initializer,
- bool useNewMethodInvocationEncoding) {
+ void createBodies(CoreTypes coreTypes, Expression? initializer) {
//assert(initializer != null);
}
diff --git a/pkg/front_end/lib/src/fasta/builder/fixed_type_builder.dart b/pkg/front_end/lib/src/fasta/builder/fixed_type_builder.dart
index d9894e4..14f3d3d 100644
--- a/pkg/front_end/lib/src/fasta/builder/fixed_type_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/fixed_type_builder.dart
@@ -12,8 +12,8 @@
class FixedTypeBuilder extends TypeBuilder {
final DartType type;
- final Uri fileUri;
- final int charOffset;
+ final Uri? fileUri;
+ final int? charOffset;
const FixedTypeBuilder(this.type, this.fileUri, this.charOffset);
diff --git a/pkg/front_end/lib/src/fasta/builder/formal_parameter_builder.dart b/pkg/front_end/lib/src/fasta/builder/formal_parameter_builder.dart
index c1c89d3..cf242da 100644
--- a/pkg/front_end/lib/src/fasta/builder/formal_parameter_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/formal_parameter_builder.dart
@@ -14,7 +14,6 @@
show FormalParameterKind;
import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' show Token;
-import 'package:front_end/src/fasta/builder/procedure_builder.dart';
import 'package:kernel/ast.dart'
show DartType, DynamicType, Expression, VariableDeclaration;
@@ -40,6 +39,7 @@
import 'builder.dart';
import 'class_builder.dart';
import 'constructor_builder.dart';
+import 'factory_builder.dart';
import 'field_builder.dart';
import 'library_builder.dart';
import 'metadata_builder.dart';
@@ -51,6 +51,8 @@
/// constructor.
class FormalParameterBuilder extends ModifierBuilderImpl
implements VariableBuilder {
+ static const String noNameSentinel = 'no name sentinel';
+
/// List of metadata builders for the metadata declared on this parameter.
final List<MetadataBuilder>? metadata;
@@ -130,7 +132,8 @@
if (!library.isNonNullableByDefault && builtType != null) {
builtType = legacyErasure(builtType);
}
- variable = new VariableDeclarationImpl(name, functionNestingLevel,
+ variable = new VariableDeclarationImpl(
+ name == noNameSentinel ? null : name, functionNestingLevel,
type: builtType,
isFinal: isFinal,
isConst: isConst,
@@ -202,7 +205,7 @@
bool isConstConstructorParameter = false;
if (parent is ConstructorBuilder) {
isConstConstructorParameter = parent!.isConst;
- } else if (parent is ProcedureBuilder) {
+ } else if (parent is SourceFactoryBuilder) {
isConstConstructorParameter = parent!.isFactory && parent!.isConst;
}
if (isConstConstructorParameter || parent!.isClassInstanceMember) {
diff --git a/pkg/front_end/lib/src/fasta/builder/function_builder.dart b/pkg/front_end/lib/src/fasta/builder/function_builder.dart
index dd4d74a..71dc58a 100644
--- a/pkg/front_end/lib/src/fasta/builder/function_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/function_builder.dart
@@ -4,8 +4,8 @@
library fasta.procedure_builder;
-import 'package:front_end/src/fasta/kernel/kernel_api.dart';
import 'package:kernel/ast.dart';
+import 'package:kernel/core_types.dart';
import 'package:kernel/type_algebra.dart' show containsTypeVariable, substitute;
@@ -13,7 +13,7 @@
import '../scope.dart';
import '../kernel/internal_ast.dart' show VariableDeclarationImpl;
-import '../kernel/redirecting_factory_body.dart' show RedirectingFactoryBody;
+import '../kernel/kernel_helper.dart';
import '../loader.dart' show Loader;
@@ -28,8 +28,6 @@
import '../modifier.dart';
-import '../problems.dart' show unexpected;
-
import '../source/source_library_builder.dart' show SourceLibraryBuilder;
import '../type_inference/type_inference_engine.dart'
@@ -93,14 +91,10 @@
FunctionNode get function;
- FunctionBuilder? get actualOrigin;
-
Statement? get body;
void set body(Statement? newBody);
- void setRedirectingFactoryBody(Member target, List<DartType> typeArguments);
-
bool get isNative;
/// Returns the [index]th parameter of this function.
@@ -317,19 +311,6 @@
}
@override
- void setRedirectingFactoryBody(Member target, List<DartType> typeArguments) {
- if (bodyInternal != null) {
- unexpected("null", "${bodyInternal.runtimeType}", charOffset, fileUri);
- }
- bodyInternal = new RedirectingFactoryBody(target, typeArguments);
- function.body = bodyInternal;
- bodyInternal?.parent = function;
- if (isPatch) {
- actualOrigin!.setRedirectingFactoryBody(target, typeArguments);
- }
- }
-
- @override
Statement? get body => bodyInternal ??= new EmptyStatement();
@override
@@ -498,7 +479,8 @@
void buildOutlineExpressions(
SourceLibraryBuilder library,
CoreTypes coreTypes,
- List<DelayedActionPerformer> delayedActionPerformers) {
+ List<DelayedActionPerformer> delayedActionPerformers,
+ List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
if (!_hasBuiltOutlineExpressions) {
DeclarationBuilder? classOrExtensionBuilder =
isClassMember || isExtensionMember
diff --git a/pkg/front_end/lib/src/fasta/builder/member_builder.dart b/pkg/front_end/lib/src/fasta/builder/member_builder.dart
index 14ae7c9..bae23b9 100644
--- a/pkg/front_end/lib/src/fasta/builder/member_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/member_builder.dart
@@ -10,6 +10,7 @@
import '../../base/common.dart';
import '../kernel/class_hierarchy_builder.dart';
+import '../kernel/kernel_helper.dart';
import '../modifier.dart';
import '../problems.dart' show unsupported;
import '../source/source_library_builder.dart';
@@ -78,7 +79,8 @@
void buildOutlineExpressions(
SourceLibraryBuilder library,
CoreTypes coreTypes,
- List<DelayedActionPerformer> delayedActionPerformers);
+ List<DelayedActionPerformer> delayedActionPerformers,
+ List<SynthesizedFunctionNode> synthesizedFunctionNodes);
/// Returns the [ClassMember]s for the non-setter members created for this
/// member builder.
@@ -184,7 +186,8 @@
void buildOutlineExpressions(
SourceLibraryBuilder library,
CoreTypes coreTypes,
- List<DelayedActionPerformer> delayedActionPerformers) {}
+ List<DelayedActionPerformer> delayedActionPerformers,
+ List<SynthesizedFunctionNode> synthesizedFunctionNodes) {}
/// Builds the core AST structures for this member as needed for the outline.
void buildMembers(
diff --git a/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart b/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart
index 368e69c..8950e51 100644
--- a/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart
@@ -4,37 +4,20 @@
import 'package:kernel/ast.dart';
-import '../dill/dill_member_builder.dart';
-
import '../kernel/class_hierarchy_builder.dart';
-import '../kernel/forest.dart';
-import '../kernel/internal_ast.dart';
import '../kernel/kernel_api.dart';
import '../kernel/member_covariance.dart';
-import '../kernel/redirecting_factory_body.dart' show RedirectingFactoryBody;
import '../loader.dart' show Loader;
-import '../messages.dart'
- show messageConstFactoryRedirectionToNonConst, noLength;
-
-import '../problems.dart' show unexpected, unhandled;
-
import '../source/source_library_builder.dart' show SourceLibraryBuilder;
-import '../type_inference/type_inferrer.dart';
-import '../type_inference/type_schema.dart';
-
-import '../util/helpers.dart';
-
import 'builder.dart';
-import 'constructor_reference_builder.dart';
import 'extension_builder.dart';
import 'formal_parameter_builder.dart';
import 'function_builder.dart';
import 'member_builder.dart';
import 'metadata_builder.dart';
-import 'library_builder.dart';
import 'type_builder.dart';
import 'type_variable_builder.dart';
@@ -62,28 +45,38 @@
bool get isExtensionMethod;
}
-abstract class ProcedureBuilderImpl extends FunctionBuilderImpl
+class SourceProcedureBuilder extends FunctionBuilderImpl
implements ProcedureBuilder {
- late Procedure _procedure;
-
@override
final int charOpenParenOffset;
@override
- final ProcedureKind kind;
-
- @override
AsyncMarker actualAsyncModifier = AsyncMarker.Sync;
- @override
- ProcedureBuilder? actualOrigin;
-
- @override
- Procedure get actualProcedure => _procedure;
-
final bool isExtensionInstanceMember;
- ProcedureBuilderImpl(
+ late Procedure _procedure;
+
+ final Reference? _tearOffReference;
+
+ /// If this is an extension instance method then [_extensionTearOff] holds
+ /// the synthetically created tear off function.
+ Procedure? _extensionTearOff;
+
+ /// If this is an extension instance method then
+ /// [_extensionTearOffParameterMap] holds a map from the parameters of
+ /// the methods to the parameter of the closure returned in the tear-off.
+ ///
+ /// This map is used to set the default values on the closure parameters when
+ /// these have been built.
+ Map<VariableDeclaration, VariableDeclaration>? _extensionTearOffParameterMap;
+
+ @override
+ final ProcedureKind kind;
+
+ SourceProcedureBuilder? actualOrigin;
+
+ SourceProcedureBuilder(
List<MetadataBuilder>? metadata,
int modifiers,
TypeBuilder? returnType,
@@ -97,6 +90,8 @@
this.charOpenParenOffset,
int charEndOffset,
Reference? procedureReference,
+ this._tearOffReference,
+ AsyncMarker asyncModifier,
ProcedureNameScheme procedureNameScheme,
{required bool isExtensionMember,
required bool isInstanceMember,
@@ -105,6 +100,7 @@
: assert(isExtensionMember != null),
// ignore: unnecessary_null_comparison
assert(isInstanceMember != null),
+ assert(kind != ProcedureKind.Factory),
this.isExtensionInstanceMember = isInstanceMember && isExtensionMember,
super(metadata, modifiers, returnType, name, typeVariables, formals,
libraryBuilder, charOffset, nativeMethodName) {
@@ -118,13 +114,20 @@
..fileOffset = charOffset
..fileEndOffset = charEndOffset
..isNonNullableByDefault = libraryBuilder.isNonNullableByDefault;
+ this.asyncModifier = asyncModifier;
+ if (isExtensionMember && isInstanceMember && kind == ProcedureKind.Method) {
+ _extensionTearOff ??= new Procedure(
+ procedureNameScheme.getName(ProcedureKind.Getter, name),
+ ProcedureKind.Method,
+ new FunctionNode(null),
+ isStatic: true,
+ isExtensionMember: true,
+ reference: _tearOffReference,
+ fileUri: fileUri)
+ ..isNonNullableByDefault = library.isNonNullableByDefault;
+ }
}
- FunctionNode get function => _procedure.function;
-
- @override
- ProcedureBuilder get origin => actualOrigin ?? this;
-
@override
ProcedureBuilder? get patchForTesting =>
dataForTesting?.patchForTesting as ProcedureBuilder?;
@@ -166,118 +169,19 @@
}
@override
- Procedure get procedure => isPatch ? origin.procedure : _procedure;
-
- @override
Member get member => procedure;
@override
- void becomeNative(Loader loader) {
- _procedure.isExternal = true;
- super.becomeNative(loader);
- }
+ SourceProcedureBuilder get origin => actualOrigin ?? this;
@override
- void applyPatch(Builder patch) {
- if (patch is ProcedureBuilderImpl) {
- if (checkPatch(patch)) {
- patch.actualOrigin = this;
- dataForTesting?.patchForTesting = patch;
- }
- } else {
- reportPatchMismatch(patch);
- }
- }
+ Procedure get procedure => isPatch ? origin.procedure : _procedure;
@override
- int finishPatch() {
- if (!isPatch) return 0;
+ Procedure get actualProcedure => _procedure;
- // TODO(ahe): restore file-offset once we track both origin and patch file
- // URIs. See https://github.com/dart-lang/sdk/issues/31579
- origin.procedure.fileUri = fileUri;
- origin.procedure.startFileOffset = _procedure.startFileOffset;
- origin.procedure.fileOffset = _procedure.fileOffset;
- origin.procedure.fileEndOffset = _procedure.fileEndOffset;
- origin.procedure.annotations
- .forEach((m) => m.fileOffset = _procedure.fileOffset);
-
- origin.procedure.isAbstract = _procedure.isAbstract;
- origin.procedure.isExternal = _procedure.isExternal;
- origin.procedure.function = _procedure.function;
- origin.procedure.function.parent = origin.procedure;
- origin.procedure.isRedirectingFactoryConstructor =
- _procedure.isRedirectingFactoryConstructor;
- return 1;
- }
-}
-
-class SourceProcedureBuilder extends ProcedureBuilderImpl {
- final Reference? _tearOffReference;
-
- /// If this is an extension instance method then [_extensionTearOff] holds
- /// the synthetically created tear off function.
- Procedure? _extensionTearOff;
-
- /// If this is an extension instance method then
- /// [_extensionTearOffParameterMap] holds a map from the parameters of
- /// the methods to the parameter of the closure returned in the tear-off.
- ///
- /// This map is used to set the default values on the closure parameters when
- /// these have been built.
- Map<VariableDeclaration, VariableDeclaration>? _extensionTearOffParameterMap;
-
- SourceProcedureBuilder(
- List<MetadataBuilder>? metadata,
- int modifiers,
- TypeBuilder? returnType,
- String name,
- List<TypeVariableBuilder>? typeVariables,
- List<FormalParameterBuilder>? formals,
- ProcedureKind kind,
- SourceLibraryBuilder libraryBuilder,
- int startCharOffset,
- int charOffset,
- int charOpenParenOffset,
- int charEndOffset,
- Reference? procedureReference,
- this._tearOffReference,
- AsyncMarker asyncModifier,
- ProcedureNameScheme procedureNameScheme,
- {required bool isExtensionMember,
- required bool isInstanceMember,
- String? nativeMethodName})
- : super(
- metadata,
- modifiers,
- returnType,
- name,
- typeVariables,
- formals,
- kind,
- libraryBuilder,
- startCharOffset,
- charOffset,
- charOpenParenOffset,
- charEndOffset,
- procedureReference,
- procedureNameScheme,
- isExtensionMember: isExtensionMember,
- isInstanceMember: isInstanceMember,
- nativeMethodName: nativeMethodName) {
- this.asyncModifier = asyncModifier;
- if (isExtensionMember && isInstanceMember && kind == ProcedureKind.Method) {
- _extensionTearOff ??= new Procedure(
- procedureNameScheme.getName(ProcedureKind.Getter, name),
- ProcedureKind.Method,
- new FunctionNode(null),
- isStatic: true,
- isExtensionMember: true,
- reference: _tearOffReference,
- fileUri: fileUri)
- ..isNonNullableByDefault = library.isNonNullableByDefault;
- }
- }
+ @override
+ FunctionNode get function => _procedure.function;
bool _typeEnsured = false;
Set<ClassMember>? _overrideDependencies;
@@ -597,6 +501,45 @@
_localSetters ??= isSetter && !isConflictingSetter
? <ClassMember>[new SourceProcedureMember(this)]
: const <ClassMember>[];
+
+ @override
+ void becomeNative(Loader loader) {
+ _procedure.isExternal = true;
+ super.becomeNative(loader);
+ }
+
+ @override
+ void applyPatch(Builder patch) {
+ if (patch is SourceProcedureBuilder) {
+ if (checkPatch(patch)) {
+ patch.actualOrigin = this;
+ dataForTesting?.patchForTesting = patch;
+ }
+ } else {
+ reportPatchMismatch(patch);
+ }
+ }
+
+ @override
+ int finishPatch() {
+ if (!isPatch) return 0;
+
+ // TODO(ahe): restore file-offset once we track both origin and patch file
+ // URIs. See https://github.com/dart-lang/sdk/issues/31579
+ origin.procedure.fileUri = fileUri;
+ origin.procedure.startFileOffset = _procedure.startFileOffset;
+ origin.procedure.fileOffset = _procedure.fileOffset;
+ origin.procedure.fileEndOffset = _procedure.fileEndOffset;
+ origin.procedure.annotations
+ .forEach((m) => m.fileOffset = _procedure.fileOffset);
+
+ origin.procedure.isAbstract = _procedure.isAbstract;
+ origin.procedure.isExternal = _procedure.isExternal;
+ origin.procedure.function = _procedure.function;
+ origin.procedure.function.parent = origin.procedure;
+ origin.procedure.isRedirectingFactory = _procedure.isRedirectingFactory;
+ return 1;
+ }
}
class SourceProcedureMember extends BuilderClassMember {
@@ -647,216 +590,6 @@
}
}
-class RedirectingFactoryBuilder extends ProcedureBuilderImpl {
- final ConstructorReferenceBuilder redirectionTarget;
- List<DartType>? typeArguments;
-
- RedirectingFactoryBuilder(
- List<MetadataBuilder>? metadata,
- int modifiers,
- TypeBuilder returnType,
- String name,
- List<TypeVariableBuilder> typeVariables,
- List<FormalParameterBuilder>? formals,
- SourceLibraryBuilder compilationUnit,
- int startCharOffset,
- int charOffset,
- int charOpenParenOffset,
- int charEndOffset,
- Reference? reference,
- ProcedureNameScheme procedureNameScheme,
- String? nativeMethodName,
- this.redirectionTarget)
- : super(
- metadata,
- modifiers,
- returnType,
- name,
- typeVariables,
- formals,
- ProcedureKind.Factory,
- compilationUnit,
- startCharOffset,
- charOffset,
- charOpenParenOffset,
- charEndOffset,
- reference,
- procedureNameScheme,
- isExtensionMember: false,
- isInstanceMember: false,
- nativeMethodName: nativeMethodName);
-
- @override
- Member? get readTarget => null;
-
- @override
- Member? get writeTarget => null;
-
- @override
- Member? get invokeTarget => procedure;
-
- @override
- Iterable<Member> get exportedMembers => [procedure];
-
- @override
- Statement? get body => bodyInternal;
-
- @override
- void setRedirectingFactoryBody(Member target, List<DartType> typeArguments) {
- if (bodyInternal != null) {
- unexpected("null", "${bodyInternal.runtimeType}", charOffset, fileUri);
- }
-
- // Ensure that constant factories only have constant targets/bodies.
- if (isConst && !target.isConst) {
- library.addProblem(messageConstFactoryRedirectionToNonConst, charOffset,
- noLength, fileUri);
- }
-
- bodyInternal = new RedirectingFactoryBody(target, typeArguments);
- function.body = bodyInternal;
- bodyInternal?.parent = function;
- procedure.isRedirectingFactoryConstructor = true;
- if (isPatch) {
- // ignore: unnecessary_null_comparison
- if (function.typeParameters != null) {
- Map<TypeParameter, DartType> substitution = <TypeParameter, DartType>{};
- for (int i = 0; i < function.typeParameters.length; i++) {
- substitution[function.typeParameters[i]] =
- new TypeParameterType.withDefaultNullabilityForLibrary(
- actualOrigin!.function.typeParameters[i], library.library);
- }
- typeArguments = new List<DartType>.generate(typeArguments.length,
- (int i) => substitute(typeArguments[i], substitution),
- growable: false);
- }
- actualOrigin!.setRedirectingFactoryBody(target, typeArguments);
- }
- }
-
- @override
- void buildMembers(
- SourceLibraryBuilder library, void Function(Member, BuiltMemberKind) f) {
- Member member = build(library);
- f(member, BuiltMemberKind.RedirectingFactory);
- }
-
- @override
- Procedure build(SourceLibraryBuilder libraryBuilder) {
- buildFunction(libraryBuilder);
- _procedure.function.fileOffset = charOpenParenOffset;
- _procedure.function.fileEndOffset = _procedure.fileEndOffset;
- _procedure.isAbstract = isAbstract;
- _procedure.isExternal = isExternal;
- _procedure.isConst = isConst;
- _procedure.isStatic = isStatic;
- _procedure.isRedirectingFactoryConstructor = true;
- if (redirectionTarget.typeArguments != null) {
- typeArguments = new List<DartType>.generate(
- redirectionTarget.typeArguments!.length,
- (int i) => redirectionTarget.typeArguments![i].build(library),
- growable: false);
- }
- updatePrivateMemberName(_procedure, libraryBuilder);
- return _procedure;
- }
-
- @override
- void buildOutlineExpressions(
- SourceLibraryBuilder library,
- CoreTypes coreTypes,
- List<DelayedActionPerformer> delayedActionPerformers) {
- super.buildOutlineExpressions(library, coreTypes, delayedActionPerformers);
- LibraryBuilder thisLibrary = this.library;
- if (thisLibrary is SourceLibraryBuilder) {
- RedirectingFactoryBody redirectingFactoryBody =
- procedure.function.body as RedirectingFactoryBody;
- if (redirectingFactoryBody.typeArguments != null &&
- redirectingFactoryBody.typeArguments!.any((t) => t is UnknownType)) {
- TypeInferrerImpl inferrer = thisLibrary.loader.typeInferenceEngine
- .createLocalTypeInferrer(
- fileUri, classBuilder!.thisType, thisLibrary, null)
- as TypeInferrerImpl;
- inferrer.helper = thisLibrary.loader
- .createBodyBuilderForOutlineExpression(
- thisLibrary, classBuilder, this, classBuilder!.scope, fileUri);
- Builder? targetBuilder = redirectionTarget.target;
- Member target;
- if (targetBuilder is FunctionBuilder) {
- target = targetBuilder.member;
- } else if (targetBuilder is DillMemberBuilder) {
- target = targetBuilder.member;
- } else {
- unhandled("${targetBuilder.runtimeType}", "buildOutlineExpressions",
- charOffset, fileUri);
- }
- Arguments targetInvocationArguments;
- {
- List<Expression> positionalArguments = <Expression>[];
- for (VariableDeclaration parameter
- in procedure.function.positionalParameters) {
- inferrer.flowAnalysis.declare(parameter, true);
- positionalArguments.add(
- new VariableGetImpl(parameter, forNullGuardedAccess: false));
- }
- List<NamedExpression> namedArguments = <NamedExpression>[];
- for (VariableDeclaration parameter
- in procedure.function.namedParameters) {
- inferrer.flowAnalysis.declare(parameter, true);
- namedArguments.add(new NamedExpression(parameter.name!,
- new VariableGetImpl(parameter, forNullGuardedAccess: false)));
- }
- // If arguments are created using [Forest.createArguments], and the
- // type arguments are omitted, they are to be inferred.
- targetInvocationArguments = const Forest().createArguments(
- procedure.fileOffset, positionalArguments,
- named: namedArguments);
- }
- InvocationInferenceResult result = inferrer.inferInvocation(
- function.returnType,
- charOffset,
- target.function!.computeFunctionType(Nullability.nonNullable),
- targetInvocationArguments,
- staticTarget: target);
- List<DartType> typeArguments;
- if (result.inferredType is InterfaceType) {
- typeArguments = (result.inferredType as InterfaceType).typeArguments;
- } else {
- // Assume that the error is reported elsewhere, use 'dynamic' for
- // recovery.
- typeArguments = new List<DartType>.filled(
- target.enclosingClass!.typeParameters.length, const DynamicType(),
- growable: true);
- }
- member.function!.body =
- new RedirectingFactoryBody(target, typeArguments);
- }
- }
- }
-
- @override
- List<ClassMember> get localMembers =>
- throw new UnsupportedError('${runtimeType}.localMembers');
-
- @override
- List<ClassMember> get localSetters =>
- throw new UnsupportedError('${runtimeType}.localSetters');
-
- @override
- int finishPatch() {
- if (!isPatch) return 0;
-
- super.finishPatch();
-
- ProcedureBuilder redirectingOrigin = origin;
- if (redirectingOrigin is RedirectingFactoryBuilder) {
- redirectingOrigin.typeArguments = typeArguments;
- }
-
- return 1;
- }
-}
-
class ProcedureNameScheme {
final bool isExtensionMember;
final bool isStatic;
diff --git a/pkg/front_end/lib/src/fasta/builder/type_alias_builder.dart b/pkg/front_end/lib/src/fasta/builder/type_alias_builder.dart
index b012042..78e98ed 100644
--- a/pkg/front_end/lib/src/fasta/builder/type_alias_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/type_alias_builder.dart
@@ -5,7 +5,6 @@
library fasta.function_type_alias_builder;
import 'package:kernel/ast.dart';
-import 'package:kernel/core_types.dart';
import 'package:kernel/src/legacy_erasure.dart';
import 'package:kernel/type_algebra.dart' show substitute, uniteNullabilities;
@@ -20,7 +19,6 @@
import '../problems.dart' show unhandled;
import '../source/source_library_builder.dart';
-import '../util/helpers.dart';
import 'class_builder.dart';
import 'library_builder.dart';
@@ -113,10 +111,28 @@
// as stated in the docs? It is not needed for the implementation.
List<TypeBuilder>? unaliasTypeArguments(List<TypeBuilder>? typeArguments);
- void buildOutlineExpressions(
- SourceLibraryBuilder library,
- CoreTypes coreTypes,
- List<DelayedActionPerformer> delayedActionPerformers);
+ /// Returns the lowering for the constructor or factory named [name] on the
+ /// effective target class of this typedef.
+ ///
+ /// For instance, if we have
+ ///
+ /// class A<T> {
+ /// A();
+ /// }
+ /// typedef F = A<int>;
+ /// typedef G = F;
+ /// typedef H<X, Y> = A<X>;
+ ///
+ /// the lowering will create
+ ///
+ /// A<int> _#F#new#tearOff() => new A<int>();
+ /// A<int> _#G#new#tearOff() => new A<int>();
+ /// A<int> _#H#new#tearOff<X, Y>() => new A<X>();
+ ///
+ /// which will be return by [findConstructorOrFactory] on `F`, `G`, `H` with
+ /// name 'new' or ''.
+ Procedure? findConstructorOrFactory(
+ String name, int charOffset, Uri uri, LibraryBuilder accessingLibrary);
}
abstract class TypeAliasBuilderImpl extends TypeDeclarationBuilderImpl
@@ -494,6 +510,17 @@
}
return currentTypeArguments;
}
+
+ Map<Name, Procedure>? get tearOffs;
+
+ Procedure? findConstructorOrFactory(
+ String text, int charOffset, Uri uri, LibraryBuilder accessingLibrary) {
+ if (tearOffs != null) {
+ Name name = new Name(text == 'new' ? '' : text, accessingLibrary.library);
+ return tearOffs![name];
+ }
+ return null;
+ }
}
/// Used to detect cycles in the declaration of a typedef
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_class_builder.dart b/pkg/front_end/lib/src/fasta/dill/dill_class_builder.dart
index fe9e63c..1462633 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_class_builder.dart
@@ -72,39 +72,42 @@
@override
Class get actualCls => cls;
- void addMember(Member member) {
- if (member is Field) {
- DillFieldBuilder builder = new DillFieldBuilder(member, this);
- String name = member.name.text;
- scopeBuilder.addMember(name, builder);
- } else if (member is Procedure) {
- String name = member.name.text;
- switch (member.kind) {
- case ProcedureKind.Factory:
- constructorScopeBuilder.addMember(
- name, new DillFactoryBuilder(member, this));
- break;
- case ProcedureKind.Setter:
- scopeBuilder.addSetter(name, new DillSetterBuilder(member, this));
- break;
- case ProcedureKind.Getter:
- scopeBuilder.addMember(name, new DillGetterBuilder(member, this));
- break;
- case ProcedureKind.Operator:
- scopeBuilder.addMember(name, new DillOperatorBuilder(member, this));
- break;
- case ProcedureKind.Method:
- scopeBuilder.addMember(name, new DillMethodBuilder(member, this));
- break;
- }
- } else if (member is Constructor) {
- DillConstructorBuilder builder =
- new DillConstructorBuilder(member, null, this);
- String name = member.name.text;
- constructorScopeBuilder.addMember(name, builder);
- } else {
- throw new UnsupportedError(
- "Unexpected class member ${member} (${member.runtimeType})");
+ void addField(Field field) {
+ DillFieldBuilder builder = new DillFieldBuilder(field, this);
+ String name = field.name.text;
+ scopeBuilder.addMember(name, builder);
+ }
+
+ void addConstructor(Constructor constructor, Procedure? constructorTearOff) {
+ DillConstructorBuilder builder =
+ new DillConstructorBuilder(constructor, constructorTearOff, this);
+ String name = constructor.name.text;
+ constructorScopeBuilder.addMember(name, builder);
+ }
+
+ void addFactory(Procedure factory, Procedure? factoryTearOff) {
+ String name = factory.name.text;
+ constructorScopeBuilder.addMember(
+ name, new DillFactoryBuilder(factory, factoryTearOff, this));
+ }
+
+ void addProcedure(Procedure procedure) {
+ String name = procedure.name.text;
+ switch (procedure.kind) {
+ case ProcedureKind.Factory:
+ throw new UnsupportedError("Use addFactory for adding factories");
+ case ProcedureKind.Setter:
+ scopeBuilder.addSetter(name, new DillSetterBuilder(procedure, this));
+ break;
+ case ProcedureKind.Getter:
+ scopeBuilder.addMember(name, new DillGetterBuilder(procedure, this));
+ break;
+ case ProcedureKind.Operator:
+ scopeBuilder.addMember(name, new DillOperatorBuilder(procedure, this));
+ break;
+ case ProcedureKind.Method:
+ scopeBuilder.addMember(name, new DillMethodBuilder(procedure, this));
+ break;
}
}
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_extension_builder.dart b/pkg/front_end/lib/src/fasta/dill/dill_extension_builder.dart
index 94e7b8c..1a1857b 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_extension_builder.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_extension_builder.dart
@@ -11,6 +11,8 @@
import '../builder/type_builder.dart';
import '../builder/type_variable_builder.dart';
+import '../kernel/kernel_helper.dart';
+
import '../scope.dart';
import '../util/helpers.dart';
@@ -103,8 +105,11 @@
}
@override
- void buildOutlineExpressions(LibraryBuilder library, CoreTypes coreTypes,
- List<DelayedActionPerformer> delayedActionPerformers) {
+ void buildOutlineExpressions(
+ LibraryBuilder library,
+ CoreTypes coreTypes,
+ List<DelayedActionPerformer> delayedActionPerformers,
+ List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
// TODO(johnniwinther): Remove the need for this.
}
}
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart b/pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart
index c899e3df..4c1afba 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart
@@ -6,28 +6,7 @@
import 'dart:convert' show jsonDecode;
-import 'package:kernel/ast.dart'
- show
- Class,
- ConstantExpression,
- DartType,
- DynamicType,
- Expression,
- Extension,
- Field,
- FunctionType,
- Library,
- ListLiteral,
- Member,
- NamedNode,
- NeverType,
- Procedure,
- ProcedureKind,
- Reference,
- StaticGet,
- StringConstant,
- StringLiteral,
- Typedef;
+import 'package:kernel/ast.dart';
import '../builder/builder.dart';
import '../builder/class_builder.dart';
@@ -48,6 +27,7 @@
templateTypeNotFound,
templateUnspecified;
+import '../kernel/constructor_tearoff_lowering.dart';
import '../kernel/redirecting_factory_body.dart'
show RedirectingFactoryBody, isRedirectingFactoryField;
@@ -120,8 +100,23 @@
isBuilt = true;
library.classes.forEach(addClass);
library.extensions.forEach(addExtension);
+
+ Map<String, Map<Name, Procedure>> tearOffs = {};
+ List<Procedure> nonTearOffs = [];
+ for (Procedure procedure in library.procedures) {
+ List<Object>? names = extractTypedefNameFromTearOff(procedure.name);
+ if (names != null) {
+ Map<Name, Procedure> map = tearOffs[names[0] as String] ??= {};
+ map[names[1] as Name] = procedure;
+ } else {
+ nonTearOffs.add(procedure);
+ }
+ }
+ nonTearOffs.forEach(addMember);
library.procedures.forEach(addMember);
- library.typedefs.forEach(addTypedef);
+ for (Typedef typedef in library.typedefs) {
+ addTypedef(typedef, tearOffs[typedef.name]);
+ }
library.fields.forEach(addMember);
if (isReadyToFinalizeExports) {
@@ -167,10 +162,28 @@
}
void addClass(Class cls) {
- DillClassBuilder classBulder = new DillClassBuilder(cls, this);
- addBuilder(cls.name, classBulder, cls.fileOffset);
- cls.procedures.forEach(classBulder.addMember);
- cls.constructors.forEach(classBulder.addMember);
+ DillClassBuilder classBuilder = new DillClassBuilder(cls, this);
+ addBuilder(cls.name, classBuilder, cls.fileOffset);
+ Map<String, Procedure> tearOffs = {};
+ List<Procedure> nonTearOffs = [];
+ for (Procedure procedure in cls.procedures) {
+ String? name = extractConstructorNameFromTearOff(procedure.name);
+ if (name != null) {
+ tearOffs[name] = procedure;
+ } else {
+ nonTearOffs.add(procedure);
+ }
+ }
+ for (Procedure procedure in nonTearOffs) {
+ if (procedure.kind == ProcedureKind.Factory) {
+ classBuilder.addFactory(procedure, tearOffs[procedure.name.text]);
+ } else {
+ classBuilder.addProcedure(procedure);
+ }
+ }
+ for (Constructor constructor in cls.constructors) {
+ classBuilder.addConstructor(constructor, tearOffs[constructor.name.text]);
+ }
for (Field field in cls.fields) {
if (isRedirectingFactoryField(field)) {
ListLiteral initializer = field.initializer as ListLiteral;
@@ -179,7 +192,7 @@
RedirectingFactoryBody.restoreFromDill(get.target as Procedure);
}
} else {
- classBulder.addMember(field);
+ classBuilder.addField(field);
}
}
}
@@ -215,10 +228,6 @@
addBuilder(name, new DillFieldBuilder(member, this), member.fileOffset);
} else if (member is Procedure) {
switch (member.kind) {
- case ProcedureKind.Factory:
- addBuilder(
- name, new DillFactoryBuilder(member, this), member.fileOffset);
- break;
case ProcedureKind.Setter:
addBuilder(
name, new DillSetterBuilder(member, this), member.fileOffset);
@@ -269,12 +278,12 @@
return declaration;
}
- void addTypedef(Typedef typedef) {
+ void addTypedef(Typedef typedef, Map<Name, Procedure>? tearOffs) {
DartType? type = typedef.type;
if (type is FunctionType && type.typedefType == null) {
unhandled("null", "addTypedef", typedef.fileOffset, typedef.fileUri);
}
- addBuilder(typedef.name, new DillTypeAliasBuilder(typedef, this),
+ addBuilder(typedef.name, new DillTypeAliasBuilder(typedef, tearOffs, this),
typedef.fileOffset);
}
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_member_builder.dart b/pkg/front_end/lib/src/fasta/dill/dill_member_builder.dart
index d076161..54a3158 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_member_builder.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_member_builder.dart
@@ -188,13 +188,15 @@
class DillFactoryBuilder extends DillMemberBuilder {
final Procedure procedure;
+ final Procedure? _factoryTearOff;
- DillFactoryBuilder(this.procedure, Builder parent) : super(procedure, parent);
+ DillFactoryBuilder(this.procedure, this._factoryTearOff, Builder parent)
+ : super(procedure, parent);
Member get member => procedure;
@override
- Member? get readTarget => null;
+ Member? get readTarget => _factoryTearOff ?? procedure;
@override
Member? get writeTarget => null;
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_type_alias_builder.dart b/pkg/front_end/lib/src/fasta/dill/dill_type_alias_builder.dart
index f78420c..6dc3d32 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_type_alias_builder.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_type_alias_builder.dart
@@ -4,8 +4,7 @@
library fasta.dill_typedef_builder;
-import 'package:kernel/ast.dart' show DartType, InvalidType, NullType, Typedef;
-import 'package:kernel/core_types.dart';
+import 'package:kernel/ast.dart';
import '../builder/library_builder.dart';
import '../builder/metadata_builder.dart';
@@ -15,20 +14,20 @@
import '../problems.dart' show unimplemented;
-import '../util/helpers.dart';
-
import 'dill_class_builder.dart' show computeTypeVariableBuilders;
import 'dill_library_builder.dart' show DillLibraryBuilder;
class DillTypeAliasBuilder extends TypeAliasBuilderImpl {
final Typedef typedef;
+ final Map<Name, Procedure>? tearOffs;
+
List<TypeVariableBuilder>? _typeVariables;
TypeBuilder? _type;
DartType? thisType;
- DillTypeAliasBuilder(this.typedef, DillLibraryBuilder parent)
+ DillTypeAliasBuilder(this.typedef, this.tearOffs, DillLibraryBuilder parent)
: super(null, typedef.name, parent, typedef.fileOffset);
List<MetadataBuilder> get metadata {
@@ -91,10 +90,4 @@
@override
bool get isNullAlias => typedef.type is NullType;
-
- @override
- void buildOutlineExpressions(LibraryBuilder library, CoreTypes coreTypes,
- List<DelayedActionPerformer> delayedActionPerformers) {
- // TODO(johnniwinther): Remove the need for this.
- }
}
diff --git a/pkg/front_end/lib/src/fasta/incremental_compiler.dart b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
index cb1f2a1..48bbed7 100644
--- a/pkg/front_end/lib/src/fasta/incremental_compiler.dart
+++ b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
@@ -1918,7 +1918,7 @@
if (cls == null) return null;
}
- userCode!.loader.seenMessages.clear();
+ userCode!.loader.resetSeenMessages();
for (TypeParameter typeParam in typeDefinitions) {
if (!isLegalIdentifier(typeParam.name!)) {
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 4656d20..771e607 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -46,6 +46,7 @@
import '../builder/declaration_builder.dart';
import '../builder/enum_builder.dart';
import '../builder/extension_builder.dart';
+import '../builder/factory_builder.dart';
import '../builder/field_builder.dart';
import '../builder/fixed_type_builder.dart';
import '../builder/formal_parameter_builder.dart';
@@ -702,7 +703,8 @@
if (count == 0) {
push(NullValue.Metadata);
} else {
- push(const GrowableList<Expression>().pop(stack, count) ??
+ push(const GrowableList<Expression>()
+ .popNonNullable(stack, count, dummyExpression) ??
NullValue.Metadata /* Ignore parser recovery */);
}
}
@@ -950,7 +952,9 @@
DartType _computeReturnTypeContext(MemberBuilder member) {
if (member is ProcedureBuilder) {
- return member.actualProcedure.function.returnType;
+ return member.function.returnType;
+ } else if (member is SourceFactoryBuilder) {
+ return member.function.returnType;
} else {
assert(member is ConstructorBuilder);
return const DynamicType();
@@ -1018,6 +1022,8 @@
finishConstructor(builder, asyncModifier, body);
} else if (builder is ProcedureBuilder) {
builder.asyncModifier = asyncModifier;
+ } else if (builder is SourceFactoryBuilder) {
+ builder.asyncModifier = asyncModifier;
} else {
unhandled("${builder.runtimeType}", "finishFunction", builder.charOffset,
builder.fileUri);
@@ -1251,12 +1257,16 @@
} else {
Substitution substitution = Substitution.fromPairs(
initialTarget.function.typeParameters, arguments.types);
- arguments.types.clear();
- arguments.types.length = redirectionTarget!.typeArguments.length;
- for (int i = 0; i < arguments.types.length; i++) {
- arguments.types[i] =
+ for (int i = 0; i < redirectionTarget!.typeArguments.length; i++) {
+ DartType typeArgument =
substitution.substituteType(redirectionTarget.typeArguments[i]);
+ if (i < arguments.types.length) {
+ arguments.types[i] = typeArgument;
+ } else {
+ arguments.types.add(typeArgument);
+ }
}
+ arguments.types.length = redirectionTarget.typeArguments.length;
replacementNode = buildStaticInvocation(
resolvedTarget,
@@ -1681,7 +1691,10 @@
@override
void handleSend(Token beginToken, Token endToken) {
assert(checkState(beginToken, [
- ValueKinds.ArgumentsOrNull,
+ unionOfKinds([
+ ValueKinds.ArgumentsOrNull,
+ ValueKinds.ParserRecovery,
+ ]),
ValueKinds.TypeArgumentsOrNull,
unionOfKinds([
ValueKinds.Expression,
@@ -1692,12 +1705,12 @@
])
]));
debugEvent("Send");
- Arguments? arguments = pop() as Arguments?;
+ Object? arguments = pop();
List<UnresolvedType>? typeArguments = pop() as List<UnresolvedType>?;
Object receiver = pop()!;
// Delay adding [typeArguments] to [forest] for type aliases: They
// must be unaliased to the type arguments of the denoted type.
- bool isInForest = arguments != null &&
+ bool isInForest = arguments is Arguments &&
typeArguments != null &&
(receiver is! TypeUseGenerator ||
(receiver is TypeUseGenerator &&
@@ -1711,22 +1724,23 @@
(receiver is TypeUseGenerator &&
receiver.declaration is TypeAliasBuilder));
}
- if (receiver is Identifier) {
+ if (receiver is ParserRecovery || arguments is ParserRecovery) {
+ push(new ParserErrorGenerator(
+ this, beginToken, fasta.messageSyntheticToken));
+ } else if (receiver is Identifier) {
Name name = new Name(receiver.name, libraryBuilder.nameOrigin);
if (arguments == null) {
push(new IncompletePropertyAccessGenerator(this, beginToken, name));
} else {
push(new SendAccessGenerator(
- this, beginToken, name, typeArguments, arguments,
+ this, beginToken, name, typeArguments, arguments as Arguments,
isTypeArgumentsInForest: isInForest));
}
- } else if (receiver is ParserRecovery) {
- push(new ParserErrorGenerator(
- this, beginToken, fasta.messageSyntheticToken));
} else if (arguments == null) {
push(receiver);
} else {
- push(finishSend(receiver, typeArguments, arguments, beginToken.charOffset,
+ push(finishSend(receiver, typeArguments, arguments as Arguments,
+ beginToken.charOffset,
isTypeArgumentsInForest: isInForest));
}
assert(checkState(beginToken, [
@@ -2674,7 +2688,7 @@
if (!libraryBuilder.isNonNullableByDefault) {
reportNonNullableModifierError(lateToken);
}
- UnresolvedType type = pop() as UnresolvedType;
+ UnresolvedType? type = pop() as UnresolvedType?;
int modifiers = (lateToken != null ? lateMask : 0) |
Modifier.validateVarFinalOrConst(varFinalOrConst?.lexeme);
_enterLocalState(inLateLocalInitializer: lateToken != null);
@@ -4949,7 +4963,8 @@
@override
void endTypeArguments(int count, Token beginToken, Token endToken) {
debugEvent("TypeArguments");
- push(const FixedNullableList<UnresolvedType>().pop(stack, count) ??
+ push(const FixedNullableList<UnresolvedType>()
+ .popNonNullable(stack, count, dummyUnresolvedType) ??
NullValue.TypeArguments);
}
@@ -4996,10 +5011,28 @@
@override
void handleNamedArgument(Token colon) {
debugEvent("NamedArgument");
+ assert(checkState(colon, [
+ unionOfKinds([
+ ValueKinds.Expression,
+ ValueKinds.Generator,
+ ]),
+ unionOfKinds([
+ ValueKinds.Identifier,
+ ValueKinds.ParserRecovery,
+ ])
+ ]));
Expression value = popForValue();
- Identifier identifier = pop() as Identifier;
- push(new NamedExpression(identifier.name, value)
- ..fileOffset = identifier.charOffset);
+ Object? identifier = pop();
+ if (identifier is Identifier) {
+ push(new NamedExpression(identifier.name, value)
+ ..fileOffset = identifier.charOffset);
+ } else {
+ assert(
+ identifier is ParserRecovery,
+ "Unexpected argument name: "
+ "${identifier} (${identifier.runtimeType})");
+ push(identifier);
+ }
}
@override
@@ -6550,9 +6583,7 @@
arguments))
..fileOffset = receiver.fileOffset;
} else {
- MethodInvocation node =
- forest.createMethodInvocation(offset, receiver, name, arguments);
- return node;
+ return forest.createMethodInvocation(offset, receiver, name, arguments);
}
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
index a3f7c13..5bc55d2 100644
--- a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
@@ -20,6 +20,7 @@
import 'dart:io' as io;
+import 'package:front_end/src/fasta/kernel/constructor_tearoff_lowering.dart';
import 'package:kernel/ast.dart';
import 'package:kernel/class_hierarchy.dart';
import 'package:kernel/clone.dart';
@@ -40,6 +41,8 @@
messageConstEvalCircularity,
messageConstEvalContext,
messageConstEvalExtension,
+ messageConstEvalExternalConstructor,
+ messageConstEvalExternalFactory,
messageConstEvalFailedAssertion,
messageConstEvalNotListOrSetInSpread,
messageConstEvalNotMapInSpread,
@@ -453,8 +456,7 @@
transformTypeParameterList(node.typeParameters, node);
transformConstructorList(node.constructors, node);
transformProcedureList(node.procedures, node);
- transformRedirectingFactoryConstructorList(
- node.redirectingFactoryConstructors, node);
+ transformRedirectingFactoryList(node.redirectingFactories, node);
});
_staticTypeContext = oldStaticTypeContext;
return node;
@@ -511,17 +513,15 @@
}
@override
- RedirectingFactoryConstructor visitRedirectingFactoryConstructor(
- RedirectingFactoryConstructor node, TreeNode? removalSentinel) {
+ RedirectingFactory visitRedirectingFactory(
+ RedirectingFactory node, TreeNode? removalSentinel) {
// Currently unreachable as the compiler doesn't produce
// RedirectingFactoryConstructor.
StaticTypeContext? oldStaticTypeContext = _staticTypeContext;
_staticTypeContext = new StaticTypeContext(node, typeEnvironment);
constantEvaluator.withNewEnvironment(() {
transformAnnotations(node.annotations, node);
- transformTypeParameterList(node.typeParameters, node);
- transformVariableDeclarationList(node.positionalParameters, node);
- transformVariableDeclarationList(node.namedParameters, node);
+ node.function = transform(node.function)..parent = node;
});
_staticTypeContext = oldStaticTypeContext;
return node;
@@ -701,21 +701,63 @@
@override
TreeNode visitStaticTearOff(StaticTearOff node, TreeNode? removalSentinel) {
- final Member target = node.target;
- if (target is Procedure && target.kind == ProcedureKind.Method) {
- return evaluateAndTransformWithContext(node, node);
- }
- return super.visitStaticTearOff(node, removalSentinel);
+ return evaluateAndTransformWithContext(node, node);
+ }
+
+ @override
+ TreeNode visitConstructorTearOff(
+ ConstructorTearOff node, TreeNode? removalSentinel) {
+ return evaluateAndTransformWithContext(node, node);
+ }
+
+ @override
+ TreeNode visitRedirectingFactoryTearOff(
+ RedirectingFactoryTearOff node, TreeNode? removalSentinel) {
+ return evaluateAndTransformWithContext(node, node);
+ }
+
+ @override
+ TreeNode visitTypedefTearOff(TypedefTearOff node, TreeNode? removalSentinel) {
+ return evaluateAndTransformWithContext(node, node);
}
@override
TreeNode visitInstantiation(Instantiation node, TreeNode? removalSentinel) {
Instantiation result =
super.visitInstantiation(node, removalSentinel) as Instantiation;
- if (enableConstructorTearOff &&
- result.expression is ConstantExpression &&
- result.typeArguments.every(isInstantiated)) {
- return evaluateAndTransformWithContext(node, result);
+ Expression expression = result.expression;
+ if (enableConstructorTearOff && expression is ConstantExpression) {
+ if (result.typeArguments.every(isInstantiated)) {
+ return evaluateAndTransformWithContext(node, result);
+ } else {
+ Constant constant = expression.constant;
+ if (constant is TypedefTearOffConstant) {
+ Substitution substitution =
+ Substitution.fromPairs(constant.parameters, node.typeArguments);
+ return new Instantiation(
+ new ConstantExpression(constant.tearOffConstant,
+ constant.tearOffConstant.getType(_staticTypeContext!))
+ ..fileOffset = expression.fileOffset,
+ constant.types.map(substitution.substituteType).toList());
+ } else {
+ LoweredTypedefTearOff? loweredTypedefTearOff =
+ LoweredTypedefTearOff.fromConstant(constant);
+ if (loweredTypedefTearOff != null) {
+ Constant tearOffConstant = constantEvaluator
+ .canonicalize(loweredTypedefTearOff.targetTearOffConstant);
+ Substitution substitution = Substitution.fromPairs(
+ loweredTypedefTearOff.typedefTearOff.function.typeParameters,
+ node.typeArguments);
+ return new Instantiation(
+ new ConstantExpression(tearOffConstant,
+ tearOffConstant.getType(_staticTypeContext!))
+ ..fileOffset = expression.fileOffset,
+ loweredTypedefTearOff.typeArguments
+ .map(substitution.substituteType)
+ .toList());
+ }
+ }
+ }
}
return node;
}
@@ -933,7 +975,7 @@
: numberSemantics = backend.numberSemantics,
coreTypes = typeEnvironment.coreTypes,
canonicalizationCache = <Constant, Constant>{},
- nodeCache = <Node, Constant>{},
+ nodeCache = <Node, Constant?>{},
env = new EvaluationEnvironment() {
if (environmentDefines == null && !backend.supportsUnevaluatedConstants) {
throw new ArgumentError(
@@ -1250,7 +1292,7 @@
// environment.
// For const functions, recompute getters instead of using the cached
// value.
- bool isGetter = node is InstanceGet || node is PropertyGet;
+ bool isGetter = node is InstanceGet;
if (nodeCache.containsKey(node) && !(enableConstFunctions && isGetter)) {
Constant? cachedResult = nodeCache[node];
if (cachedResult == null) {
@@ -1273,8 +1315,7 @@
} else {
bool sentinelInserted = false;
if (nodeCache.containsKey(node)) {
- bool isRecursiveFunctionCall = node is MethodInvocation ||
- node is InstanceInvocation ||
+ bool isRecursiveFunctionCall = node is InstanceInvocation ||
node is FunctionInvocation ||
node is LocalFunctionInvocation ||
node is StaticInvocation;
@@ -1612,6 +1653,8 @@
node,
'Constructor "$node" has non-trivial body '
'"${constructor.function.body.runtimeType}".');
+ } else if (constructor.isExternal) {
+ return createErrorConstant(node, messageConstEvalExternalConstructor);
}
return null;
}
@@ -2476,52 +2519,6 @@
}
@override
- Constant visitMethodInvocation(MethodInvocation node) {
- // We have no support for generic method invocation at the moment.
- if (node.arguments.types.isNotEmpty && !enableConstFunctions) {
- return createInvalidExpressionConstant(node, "generic method invocation");
- }
-
- // We have no support for method invocation with named arguments at the
- // moment.
- if (node.arguments.named.isNotEmpty && !enableConstFunctions) {
- return createInvalidExpressionConstant(
- node, "method invocation with named arguments");
- }
-
- final Constant receiver = _evaluateSubexpression(node.receiver);
- if (receiver is AbortConstant) return receiver;
-
- final List<Constant>? positionalArguments =
- _evaluatePositionalArguments(node.arguments);
-
- if (positionalArguments == null) {
- AbortConstant error = _gotError!;
- _gotError = null;
- return error;
- }
- assert(_gotError == null);
- // ignore: unnecessary_null_comparison
- assert(positionalArguments != null);
-
- if (shouldBeUnevaluated) {
- return unevaluated(
- node,
- new MethodInvocation(
- extract(receiver),
- node.name,
- unevaluatedArguments(
- positionalArguments, {}, node.arguments.types),
- node.interfaceTarget)
- ..fileOffset = node.fileOffset
- ..flags = node.flags);
- }
-
- return _handleInvocation(node, node.name, receiver, positionalArguments,
- arguments: node.arguments);
- }
-
- @override
Constant visitLogicalExpression(LogicalExpression node) {
final Constant left = _evaluateSubexpression(node.left);
if (left is AbortConstant) return left;
@@ -2750,87 +2747,6 @@
}
@override
- Constant visitPropertyGet(PropertyGet node) {
- if (node.receiver is ThisExpression) {
- // Probably unreachable unless trying to evaluate non-const stuff as
- // const.
- // Access "this" during instance creation.
- if (instanceBuilder == null) {
- return createErrorConstant(node, messageNotAConstantExpression);
- }
-
- for (final MapEntry<Field, Constant> entry
- in instanceBuilder!.fields.entries) {
- final Field field = entry.key;
- if (field.name == node.name) {
- return entry.value;
- }
- }
-
- // Meant as a "stable backstop for situations where Fasta fails to
- // rewrite various erroneous constructs into invalid expressions".
- // Probably unreachable.
- return createInvalidExpressionConstant(node,
- 'Could not evaluate field get ${node.name} on incomplete instance');
- }
-
- final Constant receiver = _evaluateSubexpression(node.receiver);
- if (receiver is AbortConstant) return receiver;
- if (receiver is StringConstant && node.name.text == 'length') {
- return canonicalize(intFolder.makeIntConstant(receiver.value.length));
- } else if (shouldBeUnevaluated) {
- return unevaluated(node,
- new PropertyGet(extract(receiver), node.name, node.interfaceTarget));
- } else if (receiver is NullConstant) {
- return createErrorConstant(node, messageConstEvalNullValue);
- } else if (receiver is ListConstant && enableConstFunctions) {
- switch (node.name.text) {
- case 'first':
- if (receiver.entries.isEmpty) {
- return new _AbortDueToThrowConstant(
- node, new StateError('No element'));
- }
- return receiver.entries.first;
- case 'isEmpty':
- return new BoolConstant(receiver.entries.isEmpty);
- case 'isNotEmpty':
- return new BoolConstant(receiver.entries.isNotEmpty);
- // TODO(kallentu): case 'iterator'
- case 'last':
- if (receiver.entries.isEmpty) {
- return new _AbortDueToThrowConstant(
- node, new StateError('No element'));
- }
- return receiver.entries.last;
- case 'length':
- return new IntConstant(receiver.entries.length);
- // TODO(kallentu): case 'reversed'
- case 'single':
- if (receiver.entries.isEmpty) {
- return new _AbortDueToThrowConstant(
- node, new StateError('No element'));
- } else if (receiver.entries.length > 1) {
- return new _AbortDueToThrowConstant(
- node, new StateError('Too many elements'));
- }
- return receiver.entries.single;
- }
- } else if (receiver is InstanceConstant && enableConstFunctions) {
- for (final MapEntry<Reference, Constant> entry
- in receiver.fieldValues.entries) {
- final Field field = entry.key.asField;
- if (field.name == node.name) {
- return entry.value;
- }
- }
- }
- return createErrorConstant(
- node,
- templateConstEvalInvalidPropertyGet.withArguments(
- node.name.text, receiver, isNonNullableByDefault));
- }
-
- @override
Constant visitLet(Let node) {
Constant value = _evaluateSubexpression(node.variable.initializer!);
if (value is AbortConstant) return value;
@@ -2931,21 +2847,7 @@
@override
Constant visitStaticTearOff(StaticTearOff node) {
- return withNewEnvironment(() {
- final Member target = node.target;
- if (target is Procedure) {
- if (target.kind == ProcedureKind.Method) {
- return canonicalize(new StaticTearOffConstant(target));
- }
- return createErrorConstant(
- node,
- templateConstEvalInvalidStaticInvocation
- .withArguments(target.name.text));
- } else {
- return createInvalidExpressionConstant(
- node, 'No support for ${target.runtimeType} in a static tear-off.');
- }
- });
+ return canonicalize(new StaticTearOffConstant(node.target));
}
@override
@@ -2954,7 +2856,7 @@
for (int i = 0; i < node.expressions.length; i++) {
Constant constant = _evaluateSubexpression(node.expressions[i]);
if (constant is AbortConstant) return constant;
- if (constant is PrimitiveConstant<Object>) {
+ if (constant is PrimitiveConstant) {
String value;
if (constant is DoubleConstant && intFolder.isInt(constant)) {
value = new BigInt.from(constant.value).toString();
@@ -3000,12 +2902,7 @@
Constant _getFromEnvironmentDefaultValue(Procedure target) {
VariableDeclaration variable = target.function.namedParameters
.singleWhere((v) => v.name == 'defaultValue');
- return variable.initializer != null
- ? _evaluateExpressionInContext(target, variable.initializer!)
- :
- // Not reachable unless a defaultValue in fromEnvironment in dart:core
- // becomes null.
- nullConstant;
+ return _evaluateExpressionInContext(target, variable.initializer!);
}
Constant _handleFromEnvironment(
@@ -3118,30 +3015,33 @@
isConst: true));
}
if (target.kind == ProcedureKind.Factory) {
- if (target.isConst &&
- target.enclosingLibrary == coreTypes.coreLibrary &&
- positionals.length == 1 &&
- (target.name.text == "fromEnvironment" ||
- target.name.text == "hasEnvironment")) {
- if (environmentDefines != null) {
- // Evaluate environment constant.
- Constant name = positionals.single;
- if (name is StringConstant) {
- if (target.name.text == "fromEnvironment") {
- return _handleFromEnvironment(target, name, named);
- } else {
- return _handleHasEnvironment(name);
+ if (target.isConst) {
+ if (target.enclosingLibrary == coreTypes.coreLibrary &&
+ positionals.length == 1 &&
+ (target.name.text == "fromEnvironment" ||
+ target.name.text == "hasEnvironment")) {
+ if (environmentDefines != null) {
+ // Evaluate environment constant.
+ Constant name = positionals.single;
+ if (name is StringConstant) {
+ if (target.name.text == "fromEnvironment") {
+ return _handleFromEnvironment(target, name, named);
+ } else {
+ return _handleHasEnvironment(name);
+ }
+ } else if (name is NullConstant) {
+ return createErrorConstant(node, messageConstEvalNullValue);
}
- } else if (name is NullConstant) {
- return createErrorConstant(node, messageConstEvalNullValue);
+ } else {
+ // Leave environment constant unevaluated.
+ return unevaluated(
+ node,
+ new StaticInvocation(target,
+ unevaluatedArguments(positionals, named, arguments.types),
+ isConst: true));
}
- } else {
- // Leave environment constant unevaluated.
- return unevaluated(
- node,
- new StaticInvocation(target,
- unevaluatedArguments(positionals, named, arguments.types),
- isConst: true));
+ } else if (target.isExternal) {
+ return createErrorConstant(node, messageConstEvalExternalFactory);
}
}
} else if (target.name.text == 'identical') {
@@ -3393,7 +3293,7 @@
@override
Constant visitInstantiation(Instantiation node) {
- final Constant constant = _evaluateSubexpression(node.expression);
+ Constant constant = _evaluateSubexpression(node.expression);
if (constant is AbortConstant) return constant;
if (shouldBeUnevaluated) {
return unevaluated(
@@ -3401,41 +3301,58 @@
new Instantiation(extract(constant),
node.typeArguments.map((t) => env.substituteType(t)).toList()));
}
- if (constant is StaticTearOffConstant) {
- Member constantMember = constant.procedure;
- if (constantMember is Procedure) {
- if (node.typeArguments.length ==
- constantMember.function.typeParameters.length) {
- List<DartType>? types = _evaluateDartTypes(node, node.typeArguments);
- if (types == null) {
- AbortConstant error = _gotError!;
- _gotError = null;
- return error;
- }
- assert(_gotError == null);
- // ignore: unnecessary_null_comparison
- assert(types != null);
-
- final List<DartType> typeArguments = convertTypes(types);
- return canonicalize(
- new InstantiationConstant(constant, typeArguments));
- } else {
- // Probably unreachable.
- return createInvalidExpressionConstant(
- node,
- 'The number of type arguments supplied in the partial '
- 'instantiation does not match the number of type arguments '
- 'of the $constant.');
+ List<TypeParameter>? typeParameters;
+ if (constant is TearOffConstant) {
+ Member target = constant.target;
+ if (target is Procedure) {
+ typeParameters = target.function.typeParameters;
+ } else if (target is Constructor) {
+ typeParameters = target.enclosingClass.typeParameters;
+ }
+ } else if (constant is TypedefTearOffConstant) {
+ typeParameters = constant.parameters;
+ }
+ if (typeParameters != null) {
+ if (node.typeArguments.length == typeParameters.length) {
+ List<DartType>? types = _evaluateDartTypes(node, node.typeArguments);
+ if (types == null) {
+ AbortConstant error = _gotError!;
+ _gotError = null;
+ return error;
}
- } else if (constantMember is Constructor) {
- // TODO(dmitryas): Add support for instantiated constructor tear-offs.
- return defaultExpression(node);
+ assert(_gotError == null);
+ // ignore: unnecessary_null_comparison
+ assert(types != null);
+
+ List<DartType> typeArguments = convertTypes(types);
+ if (constant is TypedefTearOffConstant) {
+ Substitution substitution =
+ Substitution.fromPairs(constant.parameters, typeArguments);
+ typeArguments =
+ constant.types.map(substitution.substituteType).toList();
+ constant = constant.tearOffConstant;
+ } else {
+ LoweredTypedefTearOff? loweredTypedefTearOff =
+ LoweredTypedefTearOff.fromConstant(constant);
+ if (loweredTypedefTearOff != null) {
+ constant =
+ canonicalize(loweredTypedefTearOff.targetTearOffConstant);
+ Substitution substitution = Substitution.fromPairs(
+ loweredTypedefTearOff.typedefTearOff.function.typeParameters,
+ node.typeArguments);
+ typeArguments = loweredTypedefTearOff.typeArguments
+ .map(substitution.substituteType)
+ .toList();
+ }
+ }
+ return canonicalize(new InstantiationConstant(constant, typeArguments));
} else {
// Probably unreachable.
return createInvalidExpressionConstant(
node,
- "Unsupported kind of a torn off member: "
- "'${constantMember.runtimeType}'.");
+ 'The number of type arguments supplied in the partial '
+ 'instantiation does not match the number of type arguments '
+ 'of the $constant.');
}
}
// The inner expression in an instantiation can never be null, since
@@ -3447,12 +3364,33 @@
@override
Constant visitConstructorTearOff(ConstructorTearOff node) {
- return defaultExpression(node);
+ return canonicalize(new ConstructorTearOffConstant(node.target));
+ }
+
+ @override
+ Constant visitRedirectingFactoryTearOff(RedirectingFactoryTearOff node) {
+ return canonicalize(new RedirectingFactoryTearOffConstant(node.target));
}
@override
Constant visitTypedefTearOff(TypedefTearOff node) {
- return defaultExpression(node);
+ final Constant constant = _evaluateSubexpression(node.expression);
+ if (constant is TearOffConstant) {
+ FreshTypeParameters freshTypeParameters =
+ getFreshTypeParameters(node.typeParameters);
+ List<TypeParameter> typeParameters =
+ freshTypeParameters.freshTypeParameters;
+ List<DartType> typeArguments = new List<DartType>.generate(
+ node.typeArguments.length,
+ (int i) => freshTypeParameters.substitute(node.typeArguments[i]),
+ growable: false);
+ return canonicalize(
+ new TypedefTearOffConstant(typeParameters, constant, typeArguments));
+ } else {
+ // Probably unreachable.
+ return createInvalidExpressionConstant(
+ node, "Unexpected typedef tearoff target: ${constant}.");
+ }
}
@override
@@ -3784,9 +3722,6 @@
Constant visitLoadLibrary(LoadLibrary node) => defaultExpression(node);
@override
- Constant visitPropertySet(PropertySet node) => defaultExpression(node);
-
- @override
Constant visitRethrow(Rethrow node) => defaultExpression(node);
@override
@@ -4265,11 +4200,21 @@
}
@override
+ R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) {
+ throw new UnimplementedError();
+ }
+
+ @override
R acceptReference<R>(Visitor<R> v) {
throw new UnimplementedError();
}
@override
+ R acceptReference1<R, A>(Visitor1<R, A> v, A arg) {
+ throw new UnimplementedError();
+ }
+
+ @override
Expression asExpression() {
throw new UnimplementedError();
}
@@ -4325,11 +4270,21 @@
}
@override
+ R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) {
+ throw new UnimplementedError();
+ }
+
+ @override
R acceptReference<R>(Visitor<R> v) {
throw new UnimplementedError();
}
@override
+ R acceptReference1<R, A>(Visitor1<R, A> v, A arg) {
+ throw new UnimplementedError();
+ }
+
+ @override
Expression asExpression() {
throw new UnimplementedError();
}
@@ -4382,11 +4337,21 @@
}
@override
+ R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) {
+ throw new UnimplementedError();
+ }
+
+ @override
R acceptReference<R>(Visitor<R> v) {
throw new UnimplementedError();
}
@override
+ R acceptReference1<R, A>(Visitor1<R, A> v, A arg) {
+ throw new UnimplementedError();
+ }
+
+ @override
Expression asExpression() {
throw new UnimplementedError();
}
@@ -4439,11 +4404,21 @@
}
@override
+ R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) {
+ throw new UnimplementedError();
+ }
+
+ @override
R acceptReference<R>(Visitor<R> v) {
throw new UnimplementedError();
}
@override
+ R acceptReference1<R, A>(Visitor1<R, A> v, A arg) {
+ throw new UnimplementedError();
+ }
+
+ @override
Expression asExpression() {
throw new UnimplementedError();
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/constructor_tearoff_lowering.dart b/pkg/front_end/lib/src/fasta/kernel/constructor_tearoff_lowering.dart
index 33aa5d1..ada23ac 100644
--- a/pkg/front_end/lib/src/fasta/kernel/constructor_tearoff_lowering.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/constructor_tearoff_lowering.dart
@@ -2,83 +2,323 @@
// 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.
-import 'package:front_end/src/fasta/kernel/kernel_api.dart';
import 'package:kernel/ast.dart';
import 'package:kernel/type_algebra.dart';
import '../builder/member_builder.dart';
import '../source/source_library_builder.dart';
+import 'kernel_api.dart';
+import 'kernel_helper.dart';
-/// Creates the synthesized name to use for the lowering of a generative
-/// constructor by the given [constructorName] in [library].
-Name constructorTearOffName(String constructorName, Library library) {
+const String _tearOffNamePrefix = '_#';
+const String _tearOffNameSuffix = '#tearOff';
+
+/// Creates the synthesized name to use for the lowering of the tear off of a
+/// constructor or factory by the given [name] in [library].
+Name constructorTearOffName(String name, Library library) {
return new Name(
- '_#${constructorName.isEmpty ? 'new' : constructorName}#tearOff',
+ '$_tearOffNamePrefix'
+ '${name.isEmpty ? 'new' : name}'
+ '$_tearOffNameSuffix',
library);
}
+/// Creates the synthesized name to use for the lowering of the tear off of a
+/// constructor or factory by the given [constructorName] in [library].
+Name typedefTearOffName(
+ String typedefName, String constructorName, Library library) {
+ return new Name(
+ '$_tearOffNamePrefix'
+ '$typedefName#'
+ '${constructorName.isEmpty ? 'new' : constructorName}'
+ '$_tearOffNameSuffix',
+ library);
+}
+
+/// Returns the name of the corresponding constructor or factory if [name] is
+/// the synthesized name of a lowering of the tear off of a constructor or
+/// factory. Returns `null` otherwise.
+String? extractConstructorNameFromTearOff(Name name) {
+ if (name.text.startsWith(_tearOffNamePrefix) &&
+ name.text.endsWith(_tearOffNameSuffix) &&
+ name.text.length >
+ _tearOffNamePrefix.length + _tearOffNameSuffix.length) {
+ String text =
+ name.text.substring(0, name.text.length - _tearOffNameSuffix.length);
+ text = text.substring(_tearOffNamePrefix.length);
+ if (text.contains('#')) {
+ return null;
+ }
+ return text == 'new' ? '' : text;
+ }
+ return null;
+}
+
+/// If [name] is the synthesized name of a lowering of a typedef tear off, a
+/// list containing the [String] name of the typedef and the [Name] name of the
+/// corresponding constructor or factory is returned. Returns `null` otherwise.
+List<Object>? extractTypedefNameFromTearOff(Name name) {
+ if (name.text.startsWith(_tearOffNamePrefix) &&
+ name.text.endsWith(_tearOffNameSuffix) &&
+ name.text.length >
+ _tearOffNamePrefix.length + _tearOffNameSuffix.length) {
+ String text =
+ name.text.substring(0, name.text.length - _tearOffNameSuffix.length);
+ text = text.substring(_tearOffNamePrefix.length);
+ int hashIndex = text.indexOf('#');
+ if (hashIndex == -1) {
+ return null;
+ }
+ String typedefName = text.substring(0, hashIndex);
+ String constructorName = text.substring(hashIndex + 1);
+ constructorName = constructorName == 'new' ? '' : constructorName;
+ return [typedefName, new Name(constructorName, name.library)];
+ }
+ return null;
+}
+
+/// Returns `true` if [procedure] is a lowered typedef tear off.
+bool isTypedefTearOffLowering(Procedure procedure) {
+ return extractTypedefNameFromTearOff(procedure.name) != null;
+}
+
/// Creates the [Procedure] for the lowering of a generative constructor of
/// the given [name] in [compilationUnit].
///
/// If constructor tear off lowering is not enabled, `null` is returned.
-Procedure? createConstructorTearOffProcedure(
- String name, SourceLibraryBuilder compilationUnit, int fileOffset,
+Procedure? createConstructorTearOffProcedure(String name,
+ SourceLibraryBuilder compilationUnit, Uri fileUri, int fileOffset,
{required bool forAbstractClassOrEnum}) {
if (!forAbstractClassOrEnum &&
compilationUnit
.loader.target.backendTarget.isConstructorTearOffLoweringEnabled) {
- return new Procedure(constructorTearOffName(name, compilationUnit.library),
- ProcedureKind.Method, new FunctionNode(null),
- fileUri: compilationUnit.fileUri, isStatic: true)
- ..startFileOffset = fileOffset
- ..fileOffset = fileOffset
- ..fileEndOffset = fileOffset
- ..isNonNullableByDefault = compilationUnit.isNonNullableByDefault;
+ return _createTearOffProcedure(
+ compilationUnit,
+ constructorTearOffName(name, compilationUnit.library),
+ fileUri,
+ fileOffset);
}
return null;
}
-/// Creates the parameters and body for [tearOff] based on [constructor].
-void buildConstructorTearOffProcedure(
- Procedure tearOff,
- Constructor constructor,
- Class enclosingClass,
- SourceLibraryBuilder libraryBuilder) {
+/// Creates the [Procedure] for the lowering of a non-redirecting factory of
+/// the given [name] in [compilationUnit].
+///
+/// If constructor tear off lowering is not enabled, `null` is returned.
+Procedure? createFactoryTearOffProcedure(String name,
+ SourceLibraryBuilder compilationUnit, Uri fileUri, int fileOffset) {
+ if (compilationUnit
+ .loader.target.backendTarget.isFactoryTearOffLoweringEnabled) {
+ return _createTearOffProcedure(
+ compilationUnit,
+ constructorTearOffName(name, compilationUnit.library),
+ fileUri,
+ fileOffset);
+ }
+ return null;
+}
+
+/// Creates the [Procedure] for the lowering of a typedef tearoff of a
+/// constructor of the given [name] in with the typedef defined in
+/// [libraryBuilder].
+Procedure createTypedefTearOffProcedure(String typedefName, String name,
+ SourceLibraryBuilder libraryBuilder, Uri fileUri, int fileOffset) {
+ return _createTearOffProcedure(
+ libraryBuilder,
+ typedefTearOffName(typedefName, name, libraryBuilder.library),
+ fileUri,
+ fileOffset);
+}
+
+/// Creates the parameters and body for [tearOff] based on [constructor] in
+/// [enclosingClass].
+void buildConstructorTearOffProcedure(Procedure tearOff, Member constructor,
+ Class enclosingClass, SourceLibraryBuilder libraryBuilder) {
+ assert(
+ constructor is Constructor ||
+ (constructor is Procedure && constructor.isFactory) ||
+ (constructor is Procedure && constructor.isStatic),
+ "Unexpected constructor tear off target $constructor "
+ "(${constructor.runtimeType}).");
+
int fileOffset = tearOff.fileOffset;
- List<TypeParameter> classTypeParameters = enclosingClass.typeParameters;
-
- List<TypeParameter> typeParameters;
- List<DartType> typeArguments;
- Substitution substitution = Substitution.empty;
- if (classTypeParameters.isNotEmpty) {
- FreshTypeParameters freshTypeParameters =
- getFreshTypeParameters(classTypeParameters);
- typeParameters = freshTypeParameters.freshTypeParameters;
- typeArguments = freshTypeParameters.freshTypeArguments;
- substitution = freshTypeParameters.substitution;
- tearOff.function.typeParameters.addAll(typeParameters);
- setParents(typeParameters, tearOff.function);
+ FunctionNode function = constructor.function!;
+ List<TypeParameter> classTypeParameters;
+ if (constructor is Constructor) {
+ // Generative constructors implicitly have the type parameters of the
+ // enclosing class.
+ classTypeParameters = enclosingClass.typeParameters;
} else {
- typeParameters = [];
- typeArguments = [];
- substitution = Substitution.empty;
+ // Factory constructors explicitly copy over the type parameters of the
+ // enclosing class.
+ classTypeParameters = function.typeParameters;
}
- List<Expression> positionalArguments = [];
+ FreshTypeParameters freshTypeParameters =
+ _createFreshTypeParameters(classTypeParameters, tearOff.function);
+
+ List<DartType> typeArguments = freshTypeParameters.freshTypeArguments;
+ Substitution substitution = freshTypeParameters.substitution;
+ _createParameters(tearOff, constructor, substitution, libraryBuilder);
+ Arguments arguments = _createArguments(tearOff, typeArguments, fileOffset);
+ _createTearOffBody(tearOff, constructor, arguments);
+ tearOff.function.fileOffset = tearOff.fileOffset;
+ tearOff.function.fileEndOffset = tearOff.fileOffset;
+ updatePrivateMemberName(tearOff, libraryBuilder);
+}
+
+/// Creates the parameters and body for [tearOff] for a typedef tearoff of
+/// [constructor] in [enclosingClass] with [typeParameters] as the typedef
+/// parameters and [typeArguments] as the arguments passed to the
+/// [enclosingClass].
+void buildTypedefTearOffProcedure(
+ Procedure tearOff,
+ Member constructor,
+ Class enclosingClass,
+ List<TypeParameter> typeParameters,
+ List<DartType> typeArguments,
+ SourceLibraryBuilder libraryBuilder) {
+ assert(
+ constructor is Constructor ||
+ (constructor is Procedure && constructor.isFactory) ||
+ (constructor is Procedure && constructor.isStatic),
+ "Unexpected constructor tear off target $constructor "
+ "(${constructor.runtimeType}).");
+
+ int fileOffset = tearOff.fileOffset;
+
+ FunctionNode function = constructor.function!;
+ List<TypeParameter> classTypeParameters;
+ if (constructor is Constructor) {
+ // Generative constructors implicitly have the type parameters of the
+ // enclosing class.
+ classTypeParameters = enclosingClass.typeParameters;
+ } else {
+ // Factory constructors explicitly copy over the type parameters of the
+ // enclosing class.
+ classTypeParameters = function.typeParameters;
+ }
+
+ FreshTypeParameters freshTypeParameters =
+ _createFreshTypeParameters(typeParameters, tearOff.function);
+
+ Substitution substitution = freshTypeParameters.substitution;
+ if (!substitution.isEmpty) {
+ if (typeArguments.isNotEmpty) {
+ // Translate [typeArgument] into the context of the synthesized procedure.
+ typeArguments = new List<DartType>.generate(typeArguments.length,
+ (int index) => substitution.substituteType(typeArguments[index]));
+ }
+ }
+ _createParameters(
+ tearOff,
+ constructor,
+ Substitution.fromPairs(classTypeParameters, typeArguments),
+ libraryBuilder);
+ Arguments arguments = _createArguments(tearOff, typeArguments, fileOffset);
+ _createTearOffBody(tearOff, constructor, arguments);
+ tearOff.function.fileOffset = tearOff.fileOffset;
+ tearOff.function.fileEndOffset = tearOff.fileOffset;
+ updatePrivateMemberName(tearOff, libraryBuilder);
+}
+
+/// Creates the parameters for the redirecting factory [tearOff] based on the
+/// [redirectingConstructor] declaration.
+FreshTypeParameters buildRedirectingFactoryTearOffProcedureParameters(
+ Procedure tearOff,
+ Procedure redirectingConstructor,
+ SourceLibraryBuilder libraryBuilder) {
+ assert(redirectingConstructor.isRedirectingFactory);
+ FunctionNode function = redirectingConstructor.function;
+ FreshTypeParameters freshTypeParameters =
+ _createFreshTypeParameters(function.typeParameters, tearOff.function);
+ Substitution substitution = freshTypeParameters.substitution;
+ _createParameters(
+ tearOff, redirectingConstructor, substitution, libraryBuilder);
+ tearOff.function.fileOffset = tearOff.fileOffset;
+ tearOff.function.fileEndOffset = tearOff.fileOffset;
+ updatePrivateMemberName(tearOff, libraryBuilder);
+ return freshTypeParameters;
+}
+
+/// Creates the body for the redirecting factory [tearOff] with the target
+/// [constructor] and [typeArguments].
+///
+/// Returns the [SynthesizedFunctionNode] object need to perform default value
+/// computation.
+SynthesizedFunctionNode buildRedirectingFactoryTearOffBody(
+ Procedure tearOff,
+ Member target,
+ List<DartType> typeArguments,
+ FreshTypeParameters freshTypeParameters) {
+ int fileOffset = tearOff.fileOffset;
+
+ if (!freshTypeParameters.substitution.isEmpty) {
+ if (typeArguments.isNotEmpty) {
+ // Translate [typeArgument] into the context of the synthesized procedure.
+ typeArguments = new List<DartType>.generate(
+ typeArguments.length,
+ (int index) => freshTypeParameters.substitution
+ .substituteType(typeArguments[index]));
+ }
+ }
+
+ Arguments arguments = _createArguments(tearOff, typeArguments, fileOffset);
+ _createTearOffBody(tearOff, target, arguments);
+ return new SynthesizedFunctionNode(
+ new Map<TypeParameter, DartType>.fromIterables(
+ target.enclosingClass!.typeParameters, typeArguments),
+ target.function!,
+ tearOff.function,
+ identicalSignatures: false);
+}
+
+/// Creates the synthesized [Procedure] node for a tear off lowering by the
+/// given [name].
+Procedure _createTearOffProcedure(SourceLibraryBuilder libraryBuilder,
+ Name name, Uri fileUri, int fileOffset) {
+ return new Procedure(name, ProcedureKind.Method, new FunctionNode(null),
+ fileUri: fileUri, isStatic: true)
+ ..startFileOffset = fileOffset
+ ..fileOffset = fileOffset
+ ..fileEndOffset = fileOffset
+ ..isNonNullableByDefault = libraryBuilder.isNonNullableByDefault;
+}
+
+/// Creates the synthesized type parameters for a tear off lowering. The type
+/// parameters are based [originalTypeParameters] and are inserted into
+/// [newFunctionNode]. The created [FreshTypeParameters] is returned.
+FreshTypeParameters _createFreshTypeParameters(
+ List<TypeParameter> originalTypeParameters, FunctionNode newFunctionNode) {
+ FreshTypeParameters freshTypeParameters;
+ if (originalTypeParameters.isNotEmpty) {
+ freshTypeParameters = getFreshTypeParameters(originalTypeParameters);
+ List<TypeParameter> typeParameters =
+ freshTypeParameters.freshTypeParameters;
+ newFunctionNode.typeParameters.addAll(typeParameters);
+ setParents(typeParameters, newFunctionNode);
+ } else {
+ freshTypeParameters = new FreshTypeParameters([], [], Substitution.empty);
+ }
+ return freshTypeParameters;
+}
+
+/// Creates the parameters for the [tearOff] lowering based of the parameters
+/// in [constructor] and using the [substitution] to compute the parameter and
+/// return types.
+void _createParameters(Procedure tearOff, Member constructor,
+ Substitution substitution, SourceLibraryBuilder libraryBuilder) {
+ FunctionNode function = constructor.function!;
for (VariableDeclaration constructorParameter
- in constructor.function.positionalParameters) {
+ in function.positionalParameters) {
VariableDeclaration tearOffParameter = new VariableDeclaration(
constructorParameter.name,
type: substitution.substituteType(constructorParameter.type))
..fileOffset = constructorParameter.fileOffset;
tearOff.function.positionalParameters.add(tearOffParameter);
- positionalArguments
- .add(new VariableGet(tearOffParameter)..fileOffset = fileOffset);
tearOffParameter.parent = tearOff.function;
}
- List<NamedExpression> namedArguments = [];
- for (VariableDeclaration constructorParameter
- in constructor.function.namedParameters) {
+ for (VariableDeclaration constructorParameter in function.namedParameters) {
VariableDeclaration tearOffParameter = new VariableDeclaration(
constructorParameter.name,
type: substitution.substituteType(constructorParameter.type),
@@ -86,81 +326,106 @@
..fileOffset = constructorParameter.fileOffset;
tearOff.function.namedParameters.add(tearOffParameter);
tearOffParameter.parent = tearOff.function;
+ }
+ tearOff.function.returnType =
+ substitution.substituteType(function.returnType);
+ tearOff.function.requiredParameterCount = function.requiredParameterCount;
+ libraryBuilder.loader.registerTypeDependency(
+ tearOff, new TypeDependency(tearOff, constructor, substitution));
+}
+
+/// Creates the [Arguments] for passing the parameters from [tearOff] to its
+/// target, using [typeArguments] as the passed type arguments.
+Arguments _createArguments(
+ Procedure tearOff, List<DartType> typeArguments, int fileOffset) {
+ List<Expression> positionalArguments = [];
+ for (VariableDeclaration tearOffParameter
+ in tearOff.function.positionalParameters) {
+ positionalArguments
+ .add(new VariableGet(tearOffParameter)..fileOffset = fileOffset);
+ }
+ List<NamedExpression> namedArguments = [];
+ for (VariableDeclaration tearOffParameter
+ in tearOff.function.namedParameters) {
namedArguments.add(new NamedExpression(tearOffParameter.name!,
new VariableGet(tearOffParameter)..fileOffset = fileOffset)
..fileOffset = fileOffset);
}
- tearOff.function.returnType =
- substitution.substituteType(constructor.function.returnType);
- tearOff.function.requiredParameterCount =
- constructor.function.requiredParameterCount;
- tearOff.function.body = new ReturnStatement(
- new ConstructorInvocation(
- constructor,
- new Arguments(positionalArguments,
- named: namedArguments, types: typeArguments)
- ..fileOffset = tearOff.fileOffset)
- ..fileOffset = tearOff.fileOffset)
+ Arguments arguments = new Arguments(positionalArguments,
+ named: namedArguments, types: typeArguments)
+ ..fileOffset = tearOff.fileOffset;
+ return arguments;
+}
+
+/// Creates the tear of body for [tearOff] which calls [target] with
+/// [arguments].
+void _createTearOffBody(Procedure tearOff, Member target, Arguments arguments) {
+ assert(target is Constructor ||
+ (target is Procedure && target.isFactory) ||
+ (target is Procedure && target.isStatic));
+ Expression constructorInvocation;
+ if (target is Constructor) {
+ constructorInvocation = new ConstructorInvocation(target, arguments)
+ ..fileOffset = tearOff.fileOffset;
+ } else {
+ constructorInvocation = new StaticInvocation(target as Procedure, arguments)
+ ..fileOffset = tearOff.fileOffset;
+ }
+ tearOff.function.body = new ReturnStatement(constructorInvocation)
..fileOffset = tearOff.fileOffset
..parent = tearOff.function;
- tearOff.function.fileOffset = tearOff.fileOffset;
- tearOff.function.fileEndOffset = tearOff.fileOffset;
- updatePrivateMemberName(tearOff, libraryBuilder);
}
-/// Copies the parameter types from [constructor] to [tearOff].
-///
-/// These might have been inferred and therefore not available when the
-/// parameters were created.
-// TODO(johnniwinther): Add tests for inferred parameter types.
-// TODO(johnniwinther): Avoid doing this when parameter types are not inferred.
-void buildConstructorTearOffOutline(
- Procedure tearOff, Constructor constructor, Class enclosingClass) {
- List<TypeParameter> classTypeParameters = enclosingClass.typeParameters;
- Substitution substitution = Substitution.empty;
- if (classTypeParameters.isNotEmpty) {
- List<DartType> typeArguments = [];
- for (TypeParameter typeParameter in tearOff.function.typeParameters) {
- typeArguments.add(new TypeParameterType(typeParameter,
- TypeParameterType.computeNullabilityFromBound(typeParameter)));
+/// Reverse engineered typedef tear off information.
+class LoweredTypedefTearOff {
+ Procedure typedefTearOff;
+ Constant targetTearOffConstant;
+ List<DartType> typeArguments;
+
+ LoweredTypedefTearOff(
+ this.typedefTearOff, this.targetTearOffConstant, this.typeArguments);
+
+ /// Reverse engineers [constant] to a [LoweredTypedefTearOff] if [constant] is
+ /// the encoding of a lowered typedef tear off.
+ // TODO(johnniwinther): Check that this works with outlines.
+ static LoweredTypedefTearOff? fromConstant(Constant constant) {
+ if (constant is StaticTearOffConstant &&
+ isTypedefTearOffLowering(constant.target)) {
+ Procedure typedefTearOff = constant.target;
+ Statement? body = typedefTearOff.function.body;
+ if (body is ReturnStatement) {
+ Expression? constructorInvocation = body.expression;
+ Member? target;
+ List<DartType>? typeArguments;
+ if (constructorInvocation is ConstructorInvocation) {
+ target = constructorInvocation.target;
+ typeArguments = constructorInvocation.arguments.types;
+ } else if (constructorInvocation is StaticInvocation) {
+ target = constructorInvocation.target;
+ typeArguments = constructorInvocation.arguments.types;
+ }
+ if (target != null) {
+ Class cls = target.enclosingClass!;
+ Name tearOffName =
+ constructorTearOffName(target.name.text, cls.enclosingLibrary);
+ for (Procedure procedure in cls.procedures) {
+ if (procedure.name == tearOffName) {
+ target = procedure;
+ break;
+ }
+ }
+ Constant tearOffConstant;
+ if (target is Constructor ||
+ target is Procedure && target.isFactory) {
+ tearOffConstant = new ConstructorTearOffConstant(target!);
+ } else {
+ tearOffConstant = new StaticTearOffConstant(target as Procedure);
+ }
+ return new LoweredTypedefTearOff(
+ typedefTearOff, tearOffConstant, typeArguments!);
+ }
+ }
}
- substitution = Substitution.fromPairs(classTypeParameters, typeArguments);
- }
- for (int i = 0; i < constructor.function.positionalParameters.length; i++) {
- VariableDeclaration tearOffParameter =
- tearOff.function.positionalParameters[i];
- VariableDeclaration constructorParameter =
- constructor.function.positionalParameters[i];
- tearOffParameter.type =
- substitution.substituteType(constructorParameter.type);
- }
- for (int i = 0; i < constructor.function.namedParameters.length; i++) {
- VariableDeclaration tearOffParameter = tearOff.function.namedParameters[i];
- VariableDeclaration constructorParameter =
- constructor.function.namedParameters[i];
- tearOffParameter.type =
- substitution.substituteType(constructorParameter.type);
- }
-}
-
-void buildConstructorTearOffDefaultValues(
- Procedure tearOff, Constructor constructor, Class enclosingClass) {
- CloneVisitorNotMembers cloner = new CloneVisitorNotMembers();
- for (int i = 0; i < constructor.function.positionalParameters.length; i++) {
- VariableDeclaration tearOffParameter =
- tearOff.function.positionalParameters[i];
- VariableDeclaration constructorParameter =
- constructor.function.positionalParameters[i];
- tearOffParameter.initializer =
- cloner.cloneOptional(constructorParameter.initializer);
- tearOffParameter.initializer?.parent = tearOffParameter;
- }
- for (int i = 0; i < constructor.function.namedParameters.length; i++) {
- VariableDeclaration tearOffParameter = tearOff.function.namedParameters[i];
- VariableDeclaration constructorParameter =
- constructor.function.namedParameters[i];
- tearOffParameter.initializer =
- cloner.cloneOptional(constructorParameter.initializer);
- tearOffParameter.initializer?.parent = tearOffParameter;
+ return null;
}
}
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 5dc3f5b..82dbe5c 100644
--- a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
@@ -11,6 +11,7 @@
import 'package:_fe_analyzer_shared/src/scanner/token.dart' show Token;
import 'package:kernel/ast.dart';
+import 'package:kernel/type_algebra.dart';
import '../builder/builder.dart';
import '../builder/class_builder.dart';
@@ -24,6 +25,7 @@
import '../builder/type_alias_builder.dart';
import '../builder/type_builder.dart';
import '../builder/type_declaration_builder.dart';
+import '../builder/type_variable_builder.dart';
import '../builder/unresolved_type.dart';
import '../constant_context.dart' show ConstantContext;
@@ -61,7 +63,8 @@
import 'constness.dart' show Constness;
-import 'expression_generator_helper.dart' show ExpressionGeneratorHelper;
+import 'expression_generator_helper.dart'
+ show ExpressionGeneratorHelper, isProperRenameForClass;
import 'forest.dart';
@@ -749,7 +752,7 @@
Expression buildSimpleRead() {
VariableDeclarationImpl variable =
_helper.createVariableDeclarationForValue(receiverExpression);
- PropertyGet read = _forest.createPropertyGet(
+ Expression read = _forest.createPropertyGet(
fileOffset,
_helper.createVariableGet(variable, receiverExpression.fileOffset,
forNullGuardedAccess: true),
@@ -762,7 +765,7 @@
Expression buildAssignment(Expression value, {bool voidContext = false}) {
VariableDeclarationImpl variable =
_helper.createVariableDeclarationForValue(receiverExpression);
- PropertySet read = _helper.forest.createPropertySet(
+ Expression read = _helper.forest.createPropertySet(
fileOffset,
_helper.createVariableGet(variable, receiverExpression.fileOffset,
forNullGuardedAccess: true),
@@ -3099,6 +3102,7 @@
TypeDeclarationBuilder? declarationBuilder = declaration;
TypeAliasBuilder? aliasBuilder;
List<TypeBuilder>? unaliasedTypeArguments;
+ bool isGenericTypedefTearOff = false;
if (declarationBuilder is TypeAliasBuilder) {
aliasBuilder = declarationBuilder;
declarationBuilder = aliasBuilder.unaliasDeclaration(null,
@@ -3117,8 +3121,6 @@
_uri);
} else {
if (declarationBuilder is DeclarationBuilder) {
- unaliasedTypeArguments =
- aliasBuilder.unaliasTypeArguments(aliasedTypeArguments);
if (aliasedTypeArguments != null) {
_helper.libraryBuilder.uncheckedTypedefTypes.add(
new UncheckedTypedefType(new TypedefType(
@@ -3129,6 +3131,23 @@
..fileUri = _uri
..offset = fileOffset);
}
+
+ // If the arguments weren't supplied, the tear off is treated as
+ // generic, and the aliased type arguments match type parameters of
+ // the type alias.
+ if (aliasedTypeArguments == null &&
+ aliasBuilder.typeVariablesCount != 0) {
+ isGenericTypedefTearOff = true;
+ aliasedTypeArguments = <TypeBuilder>[];
+ for (TypeVariableBuilder typeVariable
+ in aliasBuilder.typeVariables!) {
+ aliasedTypeArguments.add(new NamedTypeBuilder(typeVariable.name,
+ const NullabilityBuilder.omitted(), null, _uri, fileOffset)
+ ..bind(typeVariable));
+ }
+ }
+ unaliasedTypeArguments =
+ aliasBuilder.unaliasTypeArguments(aliasedTypeArguments);
}
}
}
@@ -3162,8 +3181,13 @@
tearOffExpression = _helper.forest
.createConstructorTearOff(token.charOffset, tearOff);
} else if (tearOff is Procedure) {
- tearOffExpression =
- _helper.forest.createStaticTearOff(token.charOffset, tearOff);
+ if (tearOff.isRedirectingFactory) {
+ tearOffExpression = _helper.forest
+ .createRedirectingFactoryTearOff(token.charOffset, tearOff);
+ } else {
+ tearOffExpression = _helper.forest
+ .createStaticTearOff(token.charOffset, tearOff);
+ }
} else if (tearOff != null) {
unhandled("${tearOff.runtimeType}", "buildPropertyAccess",
operatorOffset, _helper.uri);
@@ -3171,16 +3195,64 @@
if (tearOffExpression != null) {
List<DartType>? builtTypeArguments;
if (unaliasedTypeArguments != null) {
- builtTypeArguments = declarationBuilder.buildTypeArguments(
- _helper.libraryBuilder, unaliasedTypeArguments);
+ if (unaliasedTypeArguments.length !=
+ declarationBuilder.typeVariablesCount) {
+ // The type arguments are either aren't provided or mismatch
+ // in number with the type variables of the RHS declaration.
+ // We substitute them with the default types here: in the
+ // first case that would be exactly what type inference fills
+ // in for the RHS, and in the second case it's a reasonable
+ // fallback, as the error is reported during a check on the
+ // typedef.
+ builtTypeArguments = <DartType>[];
+ for (TypeParameter typeParameter
+ in declarationBuilder.cls.typeParameters) {
+ builtTypeArguments.add(typeParameter.defaultType);
+ }
+ } else {
+ builtTypeArguments = declarationBuilder.buildTypeArguments(
+ _helper.libraryBuilder, unaliasedTypeArguments);
+ }
} else if (typeArguments != null) {
builtTypeArguments =
_helper.buildDartTypeArguments(typeArguments);
}
- return builtTypeArguments != null && builtTypeArguments.isNotEmpty
- ? _helper.forest.createInstantiation(
- token.charOffset, tearOffExpression, builtTypeArguments)
- : tearOffExpression;
+ if (isGenericTypedefTearOff) {
+ if (isProperRenameForClass(
+ _helper.typeEnvironment, aliasBuilder!.typedef)) {
+ return tearOffExpression;
+ }
+ Procedure? tearOffLowering =
+ aliasBuilder.findConstructorOrFactory(
+ name.text, nameOffset, _uri, _helper.libraryBuilder);
+ if (tearOffLowering != null) {
+ return _helper.forest
+ .createStaticTearOff(token.charOffset, tearOffLowering);
+ }
+ FreshTypeParameters freshTypeParameters =
+ getFreshTypeParameters(aliasBuilder.typedef.typeParameters);
+ List<DartType>? substitutedTypeArguments;
+ if (builtTypeArguments != null) {
+ substitutedTypeArguments = <DartType>[];
+ for (DartType builtTypeArgument in builtTypeArguments) {
+ substitutedTypeArguments
+ .add(freshTypeParameters.substitute(builtTypeArgument));
+ }
+ }
+
+ tearOffExpression = _helper.forest.createTypedefTearOff(
+ token.charOffset,
+ freshTypeParameters.freshTypeParameters,
+ tearOffExpression,
+ substitutedTypeArguments ?? const <DartType>[]);
+ } else {
+ if (builtTypeArguments != null &&
+ builtTypeArguments.isNotEmpty) {
+ tearOffExpression = _helper.forest.createInstantiation(
+ token.charOffset, tearOffExpression, builtTypeArguments);
+ }
+ }
+ return tearOffExpression;
}
}
generator = new UnresolvedNameGenerator(_helper, send.token, name);
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 88a1430..c19553b 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
@@ -5,6 +5,8 @@
library fasta.expression_generator_helper;
import 'package:_fe_analyzer_shared/src/scanner/token.dart' show Token;
+import 'package:kernel/type_algebra.dart';
+import 'package:kernel/type_environment.dart';
import '../builder/builder.dart';
import '../builder/formal_parameter_builder.dart';
@@ -30,12 +32,15 @@
Expression,
FunctionNode,
Initializer,
+ InterfaceType,
Member,
Name,
Procedure,
StaticGet,
TreeNode,
TypeParameter,
+ TypeParameterType,
+ Typedef,
VariableDeclaration;
abstract class ExpressionGeneratorHelper implements InferenceHelper {
@@ -176,4 +181,45 @@
///
/// This is needed for type promotion.
void registerVariableAssignment(VariableDeclaration variable);
+
+ TypeEnvironment get typeEnvironment;
+}
+
+/// Checks that a generic [typedef] for a generic class.
+bool isProperRenameForClass(TypeEnvironment typeEnvironment, Typedef typedef) {
+ DartType? rhsType = typedef.type;
+ if (rhsType is! InterfaceType) {
+ return false;
+ }
+
+ List<TypeParameter> fromParameters = typedef.typeParameters;
+ List<TypeParameter> toParameters = rhsType.classNode.typeParameters;
+ List<DartType> typeArguments = rhsType.typeArguments;
+ if (fromParameters.length != typeArguments.length) {
+ return false;
+ }
+ for (int i = 0; i < fromParameters.length; ++i) {
+ if (typeArguments[i] !=
+ new TypeParameterType.withDefaultNullabilityForLibrary(
+ fromParameters[i], typedef.enclosingLibrary)) {
+ return false;
+ }
+ }
+
+ Map<TypeParameter, DartType> substitutionMap = {};
+ for (int i = 0; i < fromParameters.length; ++i) {
+ substitutionMap[fromParameters[i]] = new TypeParameterType.forAlphaRenaming(
+ fromParameters[i], toParameters[i]);
+ }
+ Substitution substitution = Substitution.fromMap(substitutionMap);
+ for (int i = 0; i < fromParameters.length; ++i) {
+ if (!typeEnvironment.areMutualSubtypes(
+ toParameters[i].bound,
+ substitution.substituteType(fromParameters[i].bound),
+ SubtypeCheckMode.withNullabilities)) {
+ return false;
+ }
+ }
+
+ return true;
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/forest.dart b/pkg/front_end/lib/src/fasta/kernel/forest.dart
index 0a6909a..fa8be39 100644
--- a/pkg/front_end/lib/src/fasta/kernel/forest.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/forest.dart
@@ -722,7 +722,7 @@
..fileOffset = fileOffset;
}
- MethodInvocation createMethodInvocation(
+ Expression createMethodInvocation(
int fileOffset, Expression expression, Name name, Arguments arguments) {
// ignore: unnecessary_null_comparison
assert(fileOffset != null);
@@ -758,19 +758,18 @@
return new NullCheck(expression)..fileOffset = fileOffset;
}
- PropertyGet createPropertyGet(
- int fileOffset, Expression receiver, Name name) {
+ Expression createPropertyGet(int fileOffset, Expression receiver, Name name) {
// ignore: unnecessary_null_comparison
assert(fileOffset != null);
return new PropertyGet(receiver, name)..fileOffset = fileOffset;
}
- PropertySet createPropertySet(
+ Expression createPropertySet(
int fileOffset, Expression receiver, Name name, Expression value,
{required bool forEffect, bool readOnlyReceiver: false}) {
// ignore: unnecessary_null_comparison
assert(fileOffset != null);
- return new PropertySetImpl(receiver, name, value,
+ return new PropertySet(receiver, name, value,
forEffect: forEffect, readOnlyReceiver: readOnlyReceiver)
..fileOffset = fileOffset;
}
@@ -836,9 +835,17 @@
StaticTearOff createStaticTearOff(int fileOffset, Procedure procedure) {
// ignore: unnecessary_null_comparison
assert(fileOffset != null);
+ assert(!procedure.isRedirectingFactory);
return new StaticTearOff(procedure)..fileOffset = fileOffset;
}
+ RedirectingFactoryTearOff createRedirectingFactoryTearOff(
+ int fileOffset, Procedure procedure) {
+ // ignore: unnecessary_null_comparison
+ assert(fileOffset != null);
+ return new RedirectingFactoryTearOff(procedure)..fileOffset = fileOffset;
+ }
+
Instantiation createInstantiation(
int fileOffset, Expression expression, List<DartType> typeArguments) {
// ignore: unnecessary_null_comparison
@@ -846,6 +853,17 @@
return new Instantiation(expression, typeArguments)
..fileOffset = fileOffset;
}
+
+ TypedefTearOff createTypedefTearOff(
+ int fileOffset,
+ List<TypeParameter> typeParameters,
+ Expression expression,
+ List<DartType> typeArguments) {
+ // ignore: unnecessary_null_comparison
+ assert(fileOffset != null);
+ return new TypedefTearOff(typeParameters, expression, typeArguments)
+ ..fileOffset = fileOffset;
+ }
}
class _VariablesDeclaration extends Statement {
diff --git a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
index d87c8f9..e820080 100644
--- a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
@@ -7,7 +7,7 @@
import 'package:front_end/src/api_prototype/lowering_predicates.dart';
import 'package:kernel/ast.dart';
import 'package:kernel/src/legacy_erasure.dart';
-import 'package:kernel/type_algebra.dart' show Substitution;
+import 'package:kernel/type_algebra.dart';
import 'package:kernel/type_environment.dart';
import '../../base/instrumentation.dart'
@@ -191,6 +191,7 @@
@override
ExpressionInferenceResult visitStaticTearOff(
StaticTearOff node, DartType typeContext) {
+ inferrer.ensureMemberType(node.target);
DartType type =
node.target.function.computeFunctionType(inferrer.library.nonNullable);
return inferrer.instantiateTearOff(type, typeContext, node);
@@ -217,15 +218,53 @@
@override
ExpressionInferenceResult visitConstructorTearOff(
ConstructorTearOff node, DartType typeContext) {
- DartType type = node.constructor.function
- .computeFunctionType(inferrer.library.nonNullable);
+ inferrer.ensureMemberType(node.target);
+ DartType type =
+ node.target.function!.computeFunctionType(inferrer.library.nonNullable);
+ return inferrer.instantiateTearOff(type, typeContext, node);
+ }
+
+ @override
+ ExpressionInferenceResult visitRedirectingFactoryTearOff(
+ RedirectingFactoryTearOff node, DartType typeContext) {
+ DartType type =
+ node.target.function.computeFunctionType(inferrer.library.nonNullable);
return inferrer.instantiateTearOff(type, typeContext, node);
}
@override
ExpressionInferenceResult visitTypedefTearOff(
TypedefTearOff node, DartType typeContext) {
- return _unhandledExpression(node, typeContext);
+ ExpressionInferenceResult expressionResult = inferrer.inferExpression(
+ node.expression, const UnknownType(), true,
+ isVoidAllowed: true);
+ node.expression = expressionResult.expression..parent = node;
+ assert(
+ expressionResult.inferredType is FunctionType,
+ "Expected a FunctionType from tearing off a constructor from "
+ "a typedef, but got '${expressionResult.inferredType.runtimeType}'.");
+ FunctionType expressionType = expressionResult.inferredType as FunctionType;
+
+ assert(expressionType.typeParameters.length == node.typeArguments.length);
+ Substitution substitution = Substitution.fromPairs(
+ expressionType.typeParameters, node.typeArguments);
+ FunctionType resultType = substitution
+ .substituteType(expressionType.withoutTypeParameters) as FunctionType;
+ FreshTypeParameters freshTypeParameters =
+ getFreshTypeParameters(node.typeParameters);
+ resultType = freshTypeParameters.substitute(resultType) as FunctionType;
+ resultType = new FunctionType(resultType.positionalParameters,
+ resultType.returnType, resultType.declaredNullability,
+ namedParameters: resultType.namedParameters,
+ typeParameters: freshTypeParameters.freshTypeParameters,
+ requiredParameterCount: resultType.requiredParameterCount,
+ typedefType: null);
+ ExpressionInferenceResult inferredResult =
+ inferrer.instantiateTearOff(resultType, typeContext, node);
+ Expression ensuredResultExpression =
+ inferrer.ensureAssignableResult(typeContext, inferredResult);
+ return new ExpressionInferenceResult(
+ inferredResult.inferredType, ensuredResultExpression);
}
@override
@@ -283,7 +322,7 @@
}
@override
- void visitInvalidInitializer(Initializer node) {
+ void visitInvalidInitializer(InvalidInitializer node) {
_unhandledInitializer(node);
}
@@ -2039,7 +2078,7 @@
DartType inferredKeyType,
DartType inferredValueType,
DartType spreadContext,
- List<DartType?> actualTypes,
+ List<DartType> actualTypes,
List<DartType> actualTypesForSet,
Map<TreeNode, DartType> inferredSpreadTypes,
Map<Expression, DartType> inferredConditionTypes,
@@ -2057,8 +2096,8 @@
DartType spreadType = spreadResult.inferredType;
inferredSpreadTypes[entry.expression] = spreadType;
int length = actualTypes.length;
- actualTypes.add(null);
- actualTypes.add(null);
+ actualTypes.add(noInferredType);
+ actualTypes.add(noInferredType);
storeSpreadMapEntryElementTypes(
spreadType, entry.isNullAware, actualTypes, length);
DartType? actualKeyType = actualTypes[length];
@@ -2069,7 +2108,7 @@
MapLiteralEntry replacement = entry;
if (typeChecksNeeded) {
- if (actualKeyType == null) {
+ if (actualKeyType == noInferredType) {
if (inferrer.coreTypes.isNull(spreadTypeBound) &&
!entry.isNullAware) {
replacement = new MapLiteralEntry(
@@ -2165,7 +2204,7 @@
1);
}
}
- if (!inferrer.isAssignable(inferredValueType, actualValueType!)) {
+ if (!inferrer.isAssignable(inferredValueType, actualValueType)) {
if (inferrer.isNonNullableByDefault) {
IsSubtypeOf subtypeCheckResult = inferrer.typeSchemaEnvironment
.performNullabilityAwareSubtypeCheck(
@@ -2234,7 +2273,7 @@
}
// Use 'dynamic' for error recovery.
- if (actualKeyType == null) {
+ if (actualKeyType == noInferredType) {
actualKeyType = actualTypes[length] = const DynamicType();
actualValueType = actualTypes[length + 1] = const DynamicType();
}
@@ -2248,7 +2287,7 @@
entry.entryType = new InterfaceType(
mapEntryClass!,
inferrer.library.nonNullable,
- <DartType>[actualKeyType, actualValueType!]);
+ <DartType>[actualKeyType, actualValueType]);
bool isMap = inferrer.typeSchemaEnvironment.isSubtypeOf(
spreadType,
@@ -2315,10 +2354,10 @@
typeChecksNeeded);
int length = actualTypes.length;
actualTypes[length - 2] = inferrer.typeSchemaEnvironment
- .getStandardUpperBound(actualKeyType!, actualTypes[length - 2]!,
+ .getStandardUpperBound(actualKeyType, actualTypes[length - 2],
inferrer.library.library);
actualTypes[length - 1] = inferrer.typeSchemaEnvironment
- .getStandardUpperBound(actualValueType!, actualTypes[length - 1]!,
+ .getStandardUpperBound(actualValueType, actualTypes[length - 1],
inferrer.library.library);
int lengthForSet = actualTypesForSet.length;
actualTypesForSet[lengthForSet - 1] = inferrer.typeSchemaEnvironment
@@ -2583,7 +2622,7 @@
inferredConditionTypes = new Map<Expression, DartType>.identity();
}
if (inferenceNeeded) {
- inferredTypes = [const UnknownType(), const UnknownType()];
+ inferredTypes = [noInferredType, noInferredType];
inferrer.typeSchemaEnvironment.inferGenericFunctionOrType(
mapType,
mapClass.typeParameters,
@@ -2662,7 +2701,7 @@
formalTypesForSet.add(setType.typeArguments[0]);
}
- List<DartType> inferredTypesForSet = <DartType>[const UnknownType()];
+ List<DartType> inferredTypesForSet = <DartType>[noInferredType];
inferrer.typeSchemaEnvironment.inferGenericFunctionOrType(
setType,
inferrer.coreTypes.setClass.typeParameters,
@@ -2767,7 +2806,6 @@
return new ExpressionInferenceResult(inferredType, node);
}
- @override
ExpressionInferenceResult visitMethodInvocation(
MethodInvocation node, DartType typeContext) {
assert(node.name != unaryMinusName);
@@ -3987,24 +4025,20 @@
right, const UnknownType(), typeNeeded,
isVoidAllowed: false);
- if (inferrer.useNewMethodInvocationEncoding) {
- if (_isNull(right)) {
- equals = new EqualsNull(left)..fileOffset = fileOffset;
- } else if (_isNull(left)) {
- equals = new EqualsNull(rightResult.expression)
- ..fileOffset = fileOffset;
+ if (_isNull(right)) {
+ equals = new EqualsNull(left)..fileOffset = fileOffset;
+ } else if (_isNull(left)) {
+ equals = new EqualsNull(rightResult.expression)..fileOffset = fileOffset;
+ }
+ if (equals != null) {
+ if (isNot) {
+ equals = new Not(equals)..fileOffset = fileOffset;
}
- if (equals != null) {
- if (isNot) {
- equals = new Not(equals)..fileOffset = fileOffset;
- }
- inferrer.flowAnalysis.equalityOp_end(
- equals, rightResult.expression, rightResult.inferredType,
- notEqual: isNot);
- return new ExpressionInferenceResult(
- inferrer.coreTypes.boolRawType(inferrer.library.nonNullable),
- equals);
- }
+ inferrer.flowAnalysis.equalityOp_end(
+ equals, rightResult.expression, rightResult.inferredType,
+ notEqual: isNot);
+ return new ExpressionInferenceResult(
+ inferrer.coreTypes.boolRawType(inferrer.library.nonNullable), equals);
}
ObjectAccessTarget equalsTarget = inferrer.findInterfaceMember(
@@ -4038,47 +4072,33 @@
nullabilityNullTypeErrorTemplate:
templateArgumentTypeNotAssignableNullabilityNullType);
- if (inferrer.useNewMethodInvocationEncoding) {
- if (equalsTarget.isInstanceMember || equalsTarget.isObjectMember) {
- FunctionType functionType =
- inferrer.getFunctionType(equalsTarget, leftType);
- equals = new EqualsCall(left, right,
- functionType: functionType,
- interfaceTarget: equalsTarget.member as Procedure)
- ..fileOffset = fileOffset;
- if (isNot) {
- equals = new Not(equals)..fileOffset = fileOffset;
- }
- } else {
- assert(equalsTarget.isNever);
- FunctionType functionType = new FunctionType([const DynamicType()],
- const NeverType.nonNullable(), inferrer.library.nonNullable);
- // Ensure operator == member even for `Never`.
- Member target = inferrer
- .findInterfaceMember(const DynamicType(), equalsName, -1,
- instrumented: false)
- .member!;
- equals = new EqualsCall(left, right,
- functionType: functionType, interfaceTarget: target as Procedure)
- ..fileOffset = fileOffset;
- if (isNot) {
- equals = new Not(equals)..fileOffset = fileOffset;
- }
+ if (equalsTarget.isInstanceMember || equalsTarget.isObjectMember) {
+ FunctionType functionType =
+ inferrer.getFunctionType(equalsTarget, leftType);
+ equals = new EqualsCall(left, right,
+ functionType: functionType,
+ interfaceTarget: equalsTarget.member as Procedure)
+ ..fileOffset = fileOffset;
+ if (isNot) {
+ equals = new Not(equals)..fileOffset = fileOffset;
}
} else {
- equals = new MethodInvocation(
- left,
- equalsName,
- new Arguments(<Expression>[
- right,
- ])
- ..fileOffset = fileOffset,
- equalsTarget.member)
+ assert(equalsTarget.isNever);
+ FunctionType functionType = new FunctionType([const DynamicType()],
+ const NeverType.nonNullable(), inferrer.library.nonNullable);
+ // Ensure operator == member even for `Never`.
+ Member target = inferrer
+ .findInterfaceMember(const DynamicType(), equalsName, -1,
+ instrumented: false)
+ .member!;
+ equals = new EqualsCall(left, right,
+ functionType: functionType, interfaceTarget: target as Procedure)
..fileOffset = fileOffset;
if (isNot) {
equals = new Not(equals)..fileOffset = fileOffset;
}
}
+
inferrer.flowAnalysis.equalityOp_end(
equals, right, rightResult.inferredType,
notEqual: isNot);
@@ -4179,75 +4199,39 @@
..fileOffset = fileOffset;
break;
case ObjectAccessTargetKind.invalid:
- if (inferrer.useNewMethodInvocationEncoding) {
- binary = new DynamicInvocation(
- DynamicAccessKind.Invalid,
- left,
- binaryName,
- new Arguments(<Expression>[
- right,
- ])
- ..fileOffset = fileOffset)
- ..fileOffset = fileOffset;
- } else {
- binary = new MethodInvocation(
- left,
- binaryName,
- new Arguments(<Expression>[
- right,
- ])
- ..fileOffset = fileOffset,
- binaryTarget.member)
- ..fileOffset = fileOffset;
- }
+ binary = new DynamicInvocation(
+ DynamicAccessKind.Invalid,
+ left,
+ binaryName,
+ new Arguments(<Expression>[
+ right,
+ ])
+ ..fileOffset = fileOffset)
+ ..fileOffset = fileOffset;
break;
case ObjectAccessTargetKind.callFunction:
case ObjectAccessTargetKind.nullableCallFunction:
case ObjectAccessTargetKind.dynamic:
- if (inferrer.useNewMethodInvocationEncoding) {
- binary = new DynamicInvocation(
- DynamicAccessKind.Dynamic,
- left,
- binaryName,
- new Arguments(<Expression>[
- right,
- ])
- ..fileOffset = fileOffset)
- ..fileOffset = fileOffset;
- } else {
- binary = new MethodInvocation(
- left,
- binaryName,
- new Arguments(<Expression>[
- right,
- ])
- ..fileOffset = fileOffset,
- binaryTarget.member)
- ..fileOffset = fileOffset;
- }
+ binary = new DynamicInvocation(
+ DynamicAccessKind.Dynamic,
+ left,
+ binaryName,
+ new Arguments(<Expression>[
+ right,
+ ])
+ ..fileOffset = fileOffset)
+ ..fileOffset = fileOffset;
break;
case ObjectAccessTargetKind.never:
- if (inferrer.useNewMethodInvocationEncoding) {
- binary = new DynamicInvocation(
- DynamicAccessKind.Never,
- left,
- binaryName,
- new Arguments(<Expression>[
- right,
- ])
- ..fileOffset = fileOffset)
- ..fileOffset = fileOffset;
- } else {
- binary = new MethodInvocation(
- left,
- binaryName,
- new Arguments(<Expression>[
- right,
- ])
- ..fileOffset = fileOffset,
- binaryTarget.member)
- ..fileOffset = fileOffset;
- }
+ binary = new DynamicInvocation(
+ DynamicAccessKind.Never,
+ left,
+ binaryName,
+ new Arguments(<Expression>[
+ right,
+ ])
+ ..fileOffset = fileOffset)
+ ..fileOffset = fileOffset;
break;
case ObjectAccessTargetKind.instanceMember:
case ObjectAccessTargetKind.objectMember:
@@ -4262,30 +4246,18 @@
new InstrumentationValueForMember(binaryTarget.member!));
}
- if (inferrer.useNewMethodInvocationEncoding) {
- binary = new InstanceInvocation(
- InstanceAccessKind.Instance,
- left,
- binaryName,
- new Arguments(<Expression>[
- right,
- ])
- ..fileOffset = fileOffset,
- functionType: new FunctionType(
- [rightType], binaryType, inferrer.library.nonNullable),
- interfaceTarget: binaryTarget.member as Procedure)
- ..fileOffset = fileOffset;
- } else {
- binary = new MethodInvocation(
- left,
- binaryName,
- new Arguments(<Expression>[
- right,
- ])
- ..fileOffset = fileOffset,
- binaryTarget.member)
- ..fileOffset = fileOffset;
- }
+ binary = new InstanceInvocation(
+ InstanceAccessKind.Instance,
+ left,
+ binaryName,
+ new Arguments(<Expression>[
+ right,
+ ])
+ ..fileOffset = fileOffset,
+ functionType: new FunctionType(
+ [rightType], binaryType, inferrer.library.nonNullable),
+ interfaceTarget: binaryTarget.member as Procedure)
+ ..fileOffset = fileOffset;
if (binaryCheckKind ==
MethodContravarianceCheckKind.checkMethodReturn) {
@@ -4367,48 +4339,21 @@
..fileOffset = fileOffset;
break;
case ObjectAccessTargetKind.invalid:
- if (inferrer.useNewMethodInvocationEncoding) {
- unary = new DynamicInvocation(DynamicAccessKind.Invalid, expression,
- unaryName, new Arguments(<Expression>[])..fileOffset = fileOffset)
- ..fileOffset = fileOffset;
- } else {
- unary = new MethodInvocation(
- expression,
- unaryName,
- new Arguments(<Expression>[])..fileOffset = fileOffset,
- unaryTarget.member)
- ..fileOffset = fileOffset;
- }
+ unary = new DynamicInvocation(DynamicAccessKind.Invalid, expression,
+ unaryName, new Arguments(<Expression>[])..fileOffset = fileOffset)
+ ..fileOffset = fileOffset;
break;
case ObjectAccessTargetKind.never:
- if (inferrer.useNewMethodInvocationEncoding) {
- unary = new DynamicInvocation(DynamicAccessKind.Never, expression,
- unaryName, new Arguments(<Expression>[])..fileOffset = fileOffset)
- ..fileOffset = fileOffset;
- } else {
- unary = new MethodInvocation(
- expression,
- unaryName,
- new Arguments(<Expression>[])..fileOffset = fileOffset,
- unaryTarget.member)
- ..fileOffset = fileOffset;
- }
+ unary = new DynamicInvocation(DynamicAccessKind.Never, expression,
+ unaryName, new Arguments(<Expression>[])..fileOffset = fileOffset)
+ ..fileOffset = fileOffset;
break;
case ObjectAccessTargetKind.callFunction:
case ObjectAccessTargetKind.nullableCallFunction:
case ObjectAccessTargetKind.dynamic:
- if (inferrer.useNewMethodInvocationEncoding) {
- unary = new DynamicInvocation(DynamicAccessKind.Dynamic, expression,
- unaryName, new Arguments(<Expression>[])..fileOffset = fileOffset)
- ..fileOffset = fileOffset;
- } else {
- unary = new MethodInvocation(
- expression,
- unaryName,
- new Arguments(<Expression>[])..fileOffset = fileOffset,
- unaryTarget.member)
- ..fileOffset = fileOffset;
- }
+ unary = new DynamicInvocation(DynamicAccessKind.Dynamic, expression,
+ unaryName, new Arguments(<Expression>[])..fileOffset = fileOffset)
+ ..fileOffset = fileOffset;
break;
case ObjectAccessTargetKind.instanceMember:
case ObjectAccessTargetKind.objectMember:
@@ -4423,24 +4368,12 @@
new InstrumentationValueForMember(unaryTarget.member!));
}
- if (inferrer.useNewMethodInvocationEncoding) {
- unary = new InstanceInvocation(
- InstanceAccessKind.Instance,
- expression,
- unaryName,
- new Arguments(<Expression>[])..fileOffset = fileOffset,
- functionType: new FunctionType(
- <DartType>[], unaryType, inferrer.library.nonNullable),
- interfaceTarget: unaryTarget.member as Procedure)
- ..fileOffset = fileOffset;
- } else {
- unary = new MethodInvocation(
- expression,
- unaryName,
- new Arguments(<Expression>[])..fileOffset = fileOffset,
- unaryTarget.member)
- ..fileOffset = fileOffset;
- }
+ unary = new InstanceInvocation(InstanceAccessKind.Instance, expression,
+ unaryName, new Arguments(<Expression>[])..fileOffset = fileOffset,
+ functionType: new FunctionType(
+ <DartType>[], unaryType, inferrer.library.nonNullable),
+ interfaceTarget: unaryTarget.member as Procedure)
+ ..fileOffset = fileOffset;
if (unaryCheckKind == MethodContravarianceCheckKind.checkMethodReturn) {
if (inferrer.instrumentation != null) {
@@ -4519,117 +4452,69 @@
..fileOffset = fileOffset;
break;
case ObjectAccessTargetKind.invalid:
- if (inferrer.useNewMethodInvocationEncoding) {
- read = new DynamicInvocation(
- DynamicAccessKind.Invalid,
- readReceiver,
- indexGetName,
- new Arguments(<Expression>[
- readIndex,
- ])
- ..fileOffset = fileOffset)
- ..fileOffset = fileOffset;
- } else {
- read = new MethodInvocation(
- readReceiver,
- indexGetName,
- new Arguments(<Expression>[
- readIndex,
- ])
- ..fileOffset = fileOffset,
- readTarget.member)
- ..fileOffset = fileOffset;
- }
+ read = new DynamicInvocation(
+ DynamicAccessKind.Invalid,
+ readReceiver,
+ indexGetName,
+ new Arguments(<Expression>[
+ readIndex,
+ ])
+ ..fileOffset = fileOffset)
+ ..fileOffset = fileOffset;
break;
case ObjectAccessTargetKind.never:
- if (inferrer.useNewMethodInvocationEncoding) {
- read = new DynamicInvocation(
- DynamicAccessKind.Never,
- readReceiver,
- indexGetName,
- new Arguments(<Expression>[
- readIndex,
- ])
- ..fileOffset = fileOffset)
- ..fileOffset = fileOffset;
- } else {
- read = new MethodInvocation(
- readReceiver,
- indexGetName,
- new Arguments(<Expression>[
- readIndex,
- ])
- ..fileOffset = fileOffset,
- readTarget.member)
- ..fileOffset = fileOffset;
- }
+ read = new DynamicInvocation(
+ DynamicAccessKind.Never,
+ readReceiver,
+ indexGetName,
+ new Arguments(<Expression>[
+ readIndex,
+ ])
+ ..fileOffset = fileOffset)
+ ..fileOffset = fileOffset;
break;
case ObjectAccessTargetKind.callFunction:
case ObjectAccessTargetKind.nullableCallFunction:
case ObjectAccessTargetKind.dynamic:
- if (inferrer.useNewMethodInvocationEncoding) {
- read = new DynamicInvocation(
- DynamicAccessKind.Dynamic,
- readReceiver,
- indexGetName,
- new Arguments(<Expression>[
- readIndex,
- ])
- ..fileOffset = fileOffset)
- ..fileOffset = fileOffset;
- } else {
- read = new MethodInvocation(
- readReceiver,
- indexGetName,
- new Arguments(<Expression>[
- readIndex,
- ])
- ..fileOffset = fileOffset,
- readTarget.member)
- ..fileOffset = fileOffset;
- }
+ read = new DynamicInvocation(
+ DynamicAccessKind.Dynamic,
+ readReceiver,
+ indexGetName,
+ new Arguments(<Expression>[
+ readIndex,
+ ])
+ ..fileOffset = fileOffset)
+ ..fileOffset = fileOffset;
break;
case ObjectAccessTargetKind.instanceMember:
case ObjectAccessTargetKind.objectMember:
case ObjectAccessTargetKind.nullableInstanceMember:
- if (inferrer.useNewMethodInvocationEncoding) {
- InstanceAccessKind kind;
- switch (readTarget.kind) {
- case ObjectAccessTargetKind.instanceMember:
- kind = InstanceAccessKind.Instance;
- break;
- case ObjectAccessTargetKind.nullableInstanceMember:
- kind = InstanceAccessKind.Nullable;
- break;
- case ObjectAccessTargetKind.objectMember:
- kind = InstanceAccessKind.Object;
- break;
- default:
- throw new UnsupportedError('Unexpected target kind $readTarget');
- }
- read = new InstanceInvocation(
- kind,
- readReceiver,
- indexGetName,
- new Arguments(<Expression>[
- readIndex,
- ])
- ..fileOffset = fileOffset,
- functionType: new FunctionType(
- [indexType], readType, inferrer.library.nonNullable),
- interfaceTarget: readTarget.member as Procedure)
- ..fileOffset = fileOffset;
- } else {
- read = new MethodInvocation(
- readReceiver,
- indexGetName,
- new Arguments(<Expression>[
- readIndex,
- ])
- ..fileOffset = fileOffset,
- readTarget.member)
- ..fileOffset = fileOffset;
+ InstanceAccessKind kind;
+ switch (readTarget.kind) {
+ case ObjectAccessTargetKind.instanceMember:
+ kind = InstanceAccessKind.Instance;
+ break;
+ case ObjectAccessTargetKind.nullableInstanceMember:
+ kind = InstanceAccessKind.Nullable;
+ break;
+ case ObjectAccessTargetKind.objectMember:
+ kind = InstanceAccessKind.Object;
+ break;
+ default:
+ throw new UnsupportedError('Unexpected target kind $readTarget');
}
+ read = new InstanceInvocation(
+ kind,
+ readReceiver,
+ indexGetName,
+ new Arguments(<Expression>[
+ readIndex,
+ ])
+ ..fileOffset = fileOffset,
+ functionType: new FunctionType(
+ [indexType], readType, inferrer.library.nonNullable),
+ interfaceTarget: readTarget.member as Procedure)
+ ..fileOffset = fileOffset;
if (readCheckKind == MethodContravarianceCheckKind.checkMethodReturn) {
if (inferrer.instrumentation != null) {
inferrer.instrumentation!.record(
@@ -4702,102 +4587,54 @@
..fileOffset = fileOffset;
break;
case ObjectAccessTargetKind.invalid:
- if (inferrer.useNewMethodInvocationEncoding) {
- write = new DynamicInvocation(
- DynamicAccessKind.Invalid,
- receiver,
- indexSetName,
- new Arguments(<Expression>[index, value])
- ..fileOffset = fileOffset)
- ..fileOffset = fileOffset;
- } else {
- write = new MethodInvocation(
- receiver,
- indexSetName,
- new Arguments(<Expression>[index, value])
- ..fileOffset = fileOffset,
- writeTarget.member)
- ..fileOffset = fileOffset;
- }
+ write = new DynamicInvocation(
+ DynamicAccessKind.Invalid,
+ receiver,
+ indexSetName,
+ new Arguments(<Expression>[index, value])..fileOffset = fileOffset)
+ ..fileOffset = fileOffset;
break;
case ObjectAccessTargetKind.never:
- if (inferrer.useNewMethodInvocationEncoding) {
- write = new DynamicInvocation(
- DynamicAccessKind.Never,
- receiver,
- indexSetName,
- new Arguments(<Expression>[index, value])
- ..fileOffset = fileOffset)
- ..fileOffset = fileOffset;
- } else {
- write = new MethodInvocation(
- receiver,
- indexSetName,
- new Arguments(<Expression>[index, value])
- ..fileOffset = fileOffset,
- writeTarget.member)
- ..fileOffset = fileOffset;
- }
+ write = new DynamicInvocation(
+ DynamicAccessKind.Never,
+ receiver,
+ indexSetName,
+ new Arguments(<Expression>[index, value])..fileOffset = fileOffset)
+ ..fileOffset = fileOffset;
break;
case ObjectAccessTargetKind.callFunction:
case ObjectAccessTargetKind.nullableCallFunction:
case ObjectAccessTargetKind.dynamic:
- if (inferrer.useNewMethodInvocationEncoding) {
- write = new DynamicInvocation(
- DynamicAccessKind.Dynamic,
- receiver,
- indexSetName,
- new Arguments(<Expression>[index, value])
- ..fileOffset = fileOffset)
- ..fileOffset = fileOffset;
- break;
- } else {
- write = new MethodInvocation(
- receiver,
- indexSetName,
- new Arguments(<Expression>[index, value])
- ..fileOffset = fileOffset,
- writeTarget.member)
- ..fileOffset = fileOffset;
- break;
- }
+ write = new DynamicInvocation(
+ DynamicAccessKind.Dynamic,
+ receiver,
+ indexSetName,
+ new Arguments(<Expression>[index, value])..fileOffset = fileOffset)
+ ..fileOffset = fileOffset;
+ break;
case ObjectAccessTargetKind.instanceMember:
case ObjectAccessTargetKind.objectMember:
case ObjectAccessTargetKind.nullableInstanceMember:
- if (inferrer.useNewMethodInvocationEncoding) {
- InstanceAccessKind kind;
- switch (writeTarget.kind) {
- case ObjectAccessTargetKind.instanceMember:
- kind = InstanceAccessKind.Instance;
- break;
- case ObjectAccessTargetKind.nullableInstanceMember:
- kind = InstanceAccessKind.Nullable;
- break;
- case ObjectAccessTargetKind.objectMember:
- kind = InstanceAccessKind.Object;
- break;
- default:
- throw new UnsupportedError('Unexpected target kind $writeTarget');
- }
- write = new InstanceInvocation(
- kind,
- receiver,
- indexSetName,
- new Arguments(<Expression>[index, value])
- ..fileOffset = fileOffset,
- functionType: new FunctionType([indexType, valueType],
- const VoidType(), inferrer.library.nonNullable),
- interfaceTarget: writeTarget.member as Procedure)
- ..fileOffset = fileOffset;
- } else {
- write = new MethodInvocation(
- receiver,
- indexSetName,
- new Arguments(<Expression>[index, value])
- ..fileOffset = fileOffset,
- writeTarget.member)
- ..fileOffset = fileOffset;
+ InstanceAccessKind kind;
+ switch (writeTarget.kind) {
+ case ObjectAccessTargetKind.instanceMember:
+ kind = InstanceAccessKind.Instance;
+ break;
+ case ObjectAccessTargetKind.nullableInstanceMember:
+ kind = InstanceAccessKind.Nullable;
+ break;
+ case ObjectAccessTargetKind.objectMember:
+ kind = InstanceAccessKind.Object;
+ break;
+ default:
+ throw new UnsupportedError('Unexpected target kind $writeTarget');
}
+ write = new InstanceInvocation(kind, receiver, indexSetName,
+ new Arguments(<Expression>[index, value])..fileOffset = fileOffset,
+ functionType: new FunctionType([indexType, valueType],
+ const VoidType(), inferrer.library.nonNullable),
+ interfaceTarget: writeTarget.member as Procedure)
+ ..fileOffset = fileOffset;
break;
}
if (!inferrer.isTopLevel && writeTarget.isNullable) {
@@ -4877,42 +4714,20 @@
}
break;
case ObjectAccessTargetKind.never:
- if (inferrer.useNewMethodInvocationEncoding) {
- read = new DynamicGet(DynamicAccessKind.Never, receiver, propertyName)
- ..fileOffset = fileOffset;
- } else {
- read = new PropertyGet(receiver, propertyName, readTarget.member)
- ..fileOffset = fileOffset;
- }
+ read = new DynamicGet(DynamicAccessKind.Never, receiver, propertyName)
+ ..fileOffset = fileOffset;
break;
case ObjectAccessTargetKind.dynamic:
- if (inferrer.useNewMethodInvocationEncoding) {
- read =
- new DynamicGet(DynamicAccessKind.Dynamic, receiver, propertyName)
- ..fileOffset = fileOffset;
- } else {
- read = new PropertyGet(receiver, propertyName, readTarget.member)
- ..fileOffset = fileOffset;
- }
+ read = new DynamicGet(DynamicAccessKind.Dynamic, receiver, propertyName)
+ ..fileOffset = fileOffset;
break;
case ObjectAccessTargetKind.invalid:
- if (inferrer.useNewMethodInvocationEncoding) {
- read =
- new DynamicGet(DynamicAccessKind.Invalid, receiver, propertyName)
- ..fileOffset = fileOffset;
- } else {
- read = new PropertyGet(receiver, propertyName, readTarget.member)
- ..fileOffset = fileOffset;
- }
+ read = new DynamicGet(DynamicAccessKind.Invalid, receiver, propertyName)
+ ..fileOffset = fileOffset;
break;
case ObjectAccessTargetKind.callFunction:
case ObjectAccessTargetKind.nullableCallFunction:
- if (inferrer.useNewMethodInvocationEncoding) {
- read = new FunctionTearOff(receiver)..fileOffset = fileOffset;
- } else {
- read = new PropertyGet(receiver, propertyName, readTarget.member)
- ..fileOffset = fileOffset;
- }
+ read = new FunctionTearOff(receiver)..fileOffset = fileOffset;
break;
case ObjectAccessTargetKind.instanceMember:
case ObjectAccessTargetKind.objectMember:
@@ -4924,32 +4739,28 @@
inferrer.instrumentation!.record(inferrer.uriForInstrumentation,
fileOffset, 'target', new InstrumentationValueForMember(member));
}
- if (inferrer.useNewMethodInvocationEncoding) {
- InstanceAccessKind kind;
- switch (readTarget.kind) {
- case ObjectAccessTargetKind.instanceMember:
- kind = InstanceAccessKind.Instance;
- break;
- case ObjectAccessTargetKind.nullableInstanceMember:
- kind = InstanceAccessKind.Nullable;
- break;
- case ObjectAccessTargetKind.objectMember:
- kind = InstanceAccessKind.Object;
- break;
- default:
- throw new UnsupportedError('Unexpected target kind $readTarget');
- }
- if (member is Procedure && member.kind == ProcedureKind.Method) {
- read = new InstanceTearOff(kind, receiver, propertyName,
- interfaceTarget: member, resultType: readType)
- ..fileOffset = fileOffset;
- } else {
- read = new InstanceGet(kind, receiver, propertyName,
- interfaceTarget: member, resultType: readType)
- ..fileOffset = fileOffset;
- }
+
+ InstanceAccessKind kind;
+ switch (readTarget.kind) {
+ case ObjectAccessTargetKind.instanceMember:
+ kind = InstanceAccessKind.Instance;
+ break;
+ case ObjectAccessTargetKind.nullableInstanceMember:
+ kind = InstanceAccessKind.Nullable;
+ break;
+ case ObjectAccessTargetKind.objectMember:
+ kind = InstanceAccessKind.Object;
+ break;
+ default:
+ throw new UnsupportedError('Unexpected target kind $readTarget');
+ }
+ if (member is Procedure && member.kind == ProcedureKind.Method) {
+ read = new InstanceTearOff(kind, receiver, propertyName,
+ interfaceTarget: member, resultType: readType)
+ ..fileOffset = fileOffset;
} else {
- read = new PropertyGet(receiver, propertyName, readTarget.member)
+ read = new InstanceGet(kind, receiver, propertyName,
+ interfaceTarget: member, resultType: readType)
..fileOffset = fileOffset;
}
bool checkReturn = false;
@@ -5070,66 +4881,42 @@
}
break;
case ObjectAccessTargetKind.invalid:
- if (inferrer.useNewMethodInvocationEncoding) {
- write = new DynamicSet(
- DynamicAccessKind.Invalid, receiver, propertyName, value)
- ..fileOffset = fileOffset;
- } else {
- write =
- new PropertySet(receiver, propertyName, value, writeTarget.member)
- ..fileOffset = fileOffset;
- }
+ write = new DynamicSet(
+ DynamicAccessKind.Invalid, receiver, propertyName, value)
+ ..fileOffset = fileOffset;
break;
case ObjectAccessTargetKind.never:
- if (inferrer.useNewMethodInvocationEncoding) {
- write = new DynamicSet(
- DynamicAccessKind.Never, receiver, propertyName, value)
- ..fileOffset = fileOffset;
- } else {
- write =
- new PropertySet(receiver, propertyName, value, writeTarget.member)
- ..fileOffset = fileOffset;
- }
+ write = new DynamicSet(
+ DynamicAccessKind.Never, receiver, propertyName, value)
+ ..fileOffset = fileOffset;
break;
case ObjectAccessTargetKind.callFunction:
case ObjectAccessTargetKind.nullableCallFunction:
case ObjectAccessTargetKind.dynamic:
- if (inferrer.useNewMethodInvocationEncoding) {
- write = new DynamicSet(
- DynamicAccessKind.Dynamic, receiver, propertyName, value)
- ..fileOffset = fileOffset;
- } else {
- write =
- new PropertySet(receiver, propertyName, value, writeTarget.member)
- ..fileOffset = fileOffset;
- }
+ write = new DynamicSet(
+ DynamicAccessKind.Dynamic, receiver, propertyName, value)
+ ..fileOffset = fileOffset;
break;
case ObjectAccessTargetKind.instanceMember:
case ObjectAccessTargetKind.objectMember:
case ObjectAccessTargetKind.nullableInstanceMember:
- if (inferrer.useNewMethodInvocationEncoding) {
- InstanceAccessKind kind;
- switch (writeTarget.kind) {
- case ObjectAccessTargetKind.instanceMember:
- kind = InstanceAccessKind.Instance;
- break;
- case ObjectAccessTargetKind.nullableInstanceMember:
- kind = InstanceAccessKind.Nullable;
- break;
- case ObjectAccessTargetKind.objectMember:
- kind = InstanceAccessKind.Object;
- break;
- default:
- throw new UnsupportedError('Unexpected target kind $writeTarget');
- }
- write = new InstanceSet(kind, receiver, propertyName, value,
- interfaceTarget: writeTarget.member!)
- ..fileOffset = fileOffset;
- } else {
- write =
- new PropertySet(receiver, propertyName, value, writeTarget.member)
- ..fileOffset = fileOffset;
+ InstanceAccessKind kind;
+ switch (writeTarget.kind) {
+ case ObjectAccessTargetKind.instanceMember:
+ kind = InstanceAccessKind.Instance;
+ break;
+ case ObjectAccessTargetKind.nullableInstanceMember:
+ kind = InstanceAccessKind.Nullable;
+ break;
+ case ObjectAccessTargetKind.objectMember:
+ kind = InstanceAccessKind.Object;
+ break;
+ default:
+ throw new UnsupportedError('Unexpected target kind $writeTarget');
}
+ write = new InstanceSet(kind, receiver, propertyName, value,
+ interfaceTarget: writeTarget.member!)
+ ..fileOffset = fileOffset;
break;
}
if (!inferrer.isTopLevel && writeTarget.isNullable) {
@@ -5821,9 +5608,8 @@
return new ExpressionInferenceResult(inferredType, node);
}
- @override
ExpressionInferenceResult visitPropertySet(
- covariant PropertySetImpl node, DartType typeContext) {
+ PropertySet node, DartType typeContext) {
ExpressionInferenceResult receiverResult = inferrer
.inferNullAwareExpression(node.receiver, const UnknownType(), true,
isVoidAllowed: false);
@@ -5844,7 +5630,6 @@
'target',
new InstrumentationValueForMember(target.member!));
}
- node.interfaceTarget = target.member;
}
DartType writeContext = inferrer.getSetterType(target, receiverType);
ExpressionInferenceResult rhsResult = inferrer
@@ -5965,7 +5750,6 @@
inferredType, replacement, nullAwareGuards.prepend(nullAwareGuard));
}
- @override
ExpressionInferenceResult visitPropertyGet(
PropertyGet node, DartType typeContext) {
ExpressionInferenceResult result = inferrer.inferNullAwareExpression(
@@ -6167,11 +5951,8 @@
}
if (target is Procedure && target.kind == ProcedureKind.Method) {
- Expression tearOff = node;
- if (inferrer.useNewMethodInvocationEncoding) {
- tearOff = new StaticTearOff(node.target as Procedure)
- ..fileOffset = node.fileOffset;
- }
+ Expression tearOff = new StaticTearOff(node.target as Procedure)
+ ..fileOffset = node.fileOffset;
return inferrer.instantiateTearOff(type, typeContext, tearOff);
} else {
return new ExpressionInferenceResult(type, node);
@@ -6304,9 +6085,10 @@
Set<Field?>? enumFields;
if (expressionType is InterfaceType && expressionType.classNode.isEnum) {
- enumFields = expressionType.classNode.fields
- .where((Field field) => field.isConst && field.type == expressionType)
- .toSet();
+ enumFields = <Field?>{
+ ...expressionType.classNode.fields.where(
+ (Field field) => field.isConst && field.type == expressionType)
+ };
if (expressionType.isPotentiallyNullable) {
enumFields.add(null);
}
@@ -6569,18 +6351,10 @@
DartType resultType = rhsResult.inferredType;
Expression resultExpression;
if (variable.lateSetter != null) {
- if (inferrer.useNewMethodInvocationEncoding) {
- resultExpression = new LocalFunctionInvocation(variable.lateSetter!,
- new Arguments(<Expression>[rhs])..fileOffset = node.fileOffset,
- functionType: variable.lateSetter!.type as FunctionType)
- ..fileOffset = node.fileOffset;
- } else {
- resultExpression = new MethodInvocation(
- new VariableGet(variable.lateSetter!)..fileOffset = node.fileOffset,
- callName,
- new Arguments(<Expression>[rhs])..fileOffset = node.fileOffset)
- ..fileOffset = node.fileOffset;
- }
+ resultExpression = new LocalFunctionInvocation(variable.lateSetter!,
+ new Arguments(<Expression>[rhs])..fileOffset = node.fileOffset,
+ functionType: variable.lateSetter!.type as FunctionType)
+ ..fileOffset = node.fileOffset;
// Future calls to flow analysis will be using `resultExpression` to refer
// to the variable set, so instruct flow analysis to forward the
// expression information.
@@ -6714,8 +6488,7 @@
result.add(isSetVariable);
}
- Expression createVariableRead(bool useNewMethodInvocationEncoding,
- {bool needsPromotion: false}) {
+ Expression createVariableRead({bool needsPromotion: false}) {
if (needsPromotion) {
return new VariableGet(node, node.type)..fileOffset = fileOffset;
} else {
@@ -6739,11 +6512,7 @@
new FunctionNode(
node.initializer == null
? late_lowering.createGetterBodyWithoutInitializer(
- inferrer.coreTypes,
- fileOffset,
- node.name!,
- node.type,
- inferrer.useNewMethodInvocationEncoding,
+ inferrer.coreTypes, fileOffset, node.name!, node.type,
createVariableRead: createVariableRead,
createIsSetRead: createIsSetRead,
isSetEncoding: isSetEncoding,
@@ -6755,7 +6524,6 @@
node.name!,
node.type,
node.initializer!,
- inferrer.useNewMethodInvocationEncoding,
createVariableRead: createVariableRead,
createVariableWrite: createVariableWrite,
createIsSetRead: createIsSetRead,
@@ -6768,7 +6536,6 @@
node.name!,
node.type,
node.initializer!,
- inferrer.useNewMethodInvocationEncoding,
createVariableRead: createVariableRead,
createVariableWrite: createVariableWrite,
createIsSetRead: createIsSetRead,
@@ -6801,7 +6568,6 @@
node.name!,
setterParameter,
node.type,
- inferrer.useNewMethodInvocationEncoding,
shouldReturnValue: true,
createVariableRead: createVariableRead,
createVariableWrite: createVariableWrite,
@@ -6878,18 +6644,10 @@
if (variable.isLocalFunction) {
return inferrer.instantiateTearOff(resultType, typeContext, node);
} else if (variable.lateGetter != null) {
- if (inferrer.useNewMethodInvocationEncoding) {
- resultExpression = new LocalFunctionInvocation(variable.lateGetter!,
- new Arguments(<Expression>[])..fileOffset = node.fileOffset,
- functionType: variable.lateGetter!.type as FunctionType)
- ..fileOffset = node.fileOffset;
- } else {
- resultExpression = new MethodInvocation(
- new VariableGet(variable.lateGetter!)..fileOffset = node.fileOffset,
- callName,
- new Arguments(<Expression>[])..fileOffset = node.fileOffset)
- ..fileOffset = node.fileOffset;
- }
+ resultExpression = new LocalFunctionInvocation(variable.lateGetter!,
+ new Arguments(<Expression>[])..fileOffset = node.fileOffset,
+ functionType: variable.lateGetter!.type as FunctionType)
+ ..fileOffset = node.fileOffset;
// Future calls to flow analysis will be using `resultExpression` to refer
// to the variable get, so instruct flow analysis to forward the
// expression information.
@@ -7250,7 +7008,6 @@
'target',
new InstrumentationValueForMember(writeTarget.member!));
}
- propertySet.interfaceTarget = writeTarget.member;
}
_rhs = propertySet.value;
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart b/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart
index 749419c..9364065 100644
--- a/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart
@@ -422,6 +422,7 @@
IndexSet,
LoadLibraryTearOff,
LocalPostIncDec,
+ MethodInvocation,
NullAwareCompoundSet,
NullAwareExtension,
NullAwareIfNullSet,
@@ -429,7 +430,9 @@
NullAwarePropertyGet,
NullAwarePropertySet,
Parenthesized,
+ PropertyGet,
PropertyPostIncDec,
+ PropertySet,
StaticPostIncDec,
SuperIndexSet,
SuperPostIncDec,
@@ -442,16 +445,19 @@
@override
R accept<R>(ExpressionVisitor<R> visitor) {
- if (visitor is Printer || visitor is Precedence) {
- // Allow visitors needed for toString.
+ if (visitor is Printer || visitor is Precedence || visitor is Transformer) {
+ // Allow visitors needed for toString and replaceWith.
return visitor.defaultExpression(this);
}
- return unsupported("${runtimeType}.accept", -1, null);
+ return unsupported(
+ "${runtimeType}.accept on ${visitor.runtimeType}", -1, null);
}
@override
- R accept1<R, A>(ExpressionVisitor1<R, A> visitor, A arg) =>
- unsupported("${runtimeType}.accept1", -1, null);
+ R accept1<R, A>(ExpressionVisitor1<R, A> visitor, A arg) {
+ return unsupported(
+ "${runtimeType}.accept1 on ${visitor.runtimeType}", -1, null);
+ }
@override
DartType getStaticType(StaticTypeContext context) =>
@@ -1248,7 +1254,7 @@
@override
void toTextInternal(AstPrinter printer) {
Expression methodInvocation = invocation;
- if (methodInvocation is MethodInvocation) {
+ if (methodInvocation is InstanceInvocation) {
Expression receiver = methodInvocation.receiver;
if (receiver is VariableGet && receiver.variable == variable) {
// Special-case the usual use of this node.
@@ -1259,6 +1265,16 @@
printer.writeArguments(methodInvocation.arguments);
return;
}
+ } else if (methodInvocation is DynamicInvocation) {
+ Expression receiver = methodInvocation.receiver;
+ if (receiver is VariableGet && receiver.variable == variable) {
+ // Special-case the usual use of this node.
+ printer.writeExpression(variable.initializer!);
+ printer.write('?.');
+ printer.writeName(methodInvocation.name);
+ printer.writeArguments(methodInvocation.arguments);
+ return;
+ }
}
printer.write('let ');
printer.writeVariableDeclaration(variable);
@@ -1347,8 +1363,7 @@
// Special-case the usual use of this node.
printer.writeExpression(variable.initializer!);
printer.write('?.');
- printer.writeInterfaceMemberName(
- propertyGet.interfaceTargetReference, propertyGet.name);
+ printer.writeName(propertyGet.name);
return;
}
}
@@ -1433,7 +1448,7 @@
@override
void toTextInternal(AstPrinter printer) {
Expression propertySet = write;
- if (propertySet is PropertySet) {
+ if (propertySet is InstanceSet) {
Expression receiver = propertySet.receiver;
if (receiver is VariableGet && receiver.variable == variable) {
// Special-case the usual use of this node.
@@ -1445,6 +1460,17 @@
printer.writeExpression(propertySet.value);
return;
}
+ } else if (propertySet is DynamicSet) {
+ Expression receiver = propertySet.receiver;
+ if (receiver is VariableGet && receiver.variable == variable) {
+ // Special-case the usual use of this node.
+ printer.writeExpression(variable.initializer!);
+ printer.write('?.');
+ printer.writeName(propertySet.name);
+ printer.write(' = ');
+ printer.writeExpression(propertySet.value);
+ return;
+ }
}
printer.write('let ');
printer.writeVariableDeclaration(variable);
@@ -4096,29 +4122,6 @@
}
}
-/// Front end specific implementation of [PropertySet].
-class PropertySetImpl extends PropertySet {
- /// If `true` the assignment is need for its effect and not for its value.
- final bool forEffect;
-
- /// If `true` the receiver can be cloned and doesn't need a temporary variable
- /// for multiple reads.
- final bool readOnlyReceiver;
-
- PropertySetImpl(Expression receiver, Name name, Expression value,
- {required this.forEffect, required this.readOnlyReceiver})
- // ignore: unnecessary_null_comparison
- : assert(forEffect != null),
- // ignore: unnecessary_null_comparison
- assert(readOnlyReceiver != null),
- super(receiver, name, value);
-
- @override
- String toString() {
- return "PropertySetImpl(${toStringInternal()})";
- }
-}
-
/// Internal representation of a read of an extension instance member.
///
/// A read of an extension instance member `o.foo` is encoded as the
@@ -4524,3 +4527,238 @@
}
throw new UnsupportedError("Clone not supported for ${node.runtimeType}.");
}
+
+/// A dynamically bound method invocation of the form `o.foo()`.
+///
+/// This will be transformed into an [InstanceInvocation], [DynamicInvocation],
+/// [FunctionInvocation] or [StaticInvocation] (for implicit extension method
+/// invocation) after type inference.
+class MethodInvocation extends InternalExpression {
+ Expression receiver;
+
+ Name name;
+
+ Arguments arguments;
+
+ MethodInvocation(this.receiver, this.name, this.arguments)
+ // ignore: unnecessary_null_comparison
+ : assert(receiver != null),
+ // ignore: unnecessary_null_comparison
+ assert(arguments != null) {
+ receiver.parent = this;
+ arguments.parent = this;
+ }
+
+ @override
+ ExpressionInferenceResult acceptInference(
+ InferenceVisitor visitor, DartType typeContext) {
+ return visitor.visitMethodInvocation(this, typeContext);
+ }
+
+ @override
+ InternalExpressionKind get kind => InternalExpressionKind.MethodInvocation;
+
+ @override
+ void visitChildren(Visitor<dynamic> v) {
+ receiver.accept(v);
+ arguments.accept(v);
+ }
+
+ @override
+ void transformChildren(Transformer v) {
+ // ignore: unnecessary_null_comparison
+ if (receiver != null) {
+ receiver = v.transform(receiver);
+ receiver.parent = this;
+ }
+ // ignore: unnecessary_null_comparison
+ if (arguments != null) {
+ arguments = v.transform(arguments);
+ arguments.parent = this;
+ }
+ }
+
+ @override
+ void transformOrRemoveChildren(RemovingTransformer v) {
+ // ignore: unnecessary_null_comparison
+ if (receiver != null) {
+ receiver = v.transform(receiver);
+ receiver.parent = this;
+ }
+ // ignore: unnecessary_null_comparison
+ if (arguments != null) {
+ arguments = v.transform(arguments);
+ arguments.parent = this;
+ }
+ }
+
+ @override
+ String toString() {
+ return "MethodInvocation(${toStringInternal()})";
+ }
+
+ @override
+ int get precedence => Precedence.PRIMARY;
+
+ @override
+ void toTextInternal(AstPrinter printer) {
+ printer.writeExpression(receiver, minimumPrecedence: Precedence.PRIMARY);
+ printer.write('.');
+ printer.writeName(name);
+ printer.writeArguments(arguments);
+ }
+}
+
+/// A dynamically bound property read of the form `o.foo`.
+///
+/// This will be transformed into an [InstanceGet], [InstanceTearOff],
+/// [DynamicGet], [FunctionTearOff] or [StaticInvocation] (for implicit
+/// extension member access) after type inference.
+class PropertyGet extends InternalExpression {
+ Expression receiver;
+
+ Name name;
+
+ PropertyGet(this.receiver, this.name)
+ // ignore: unnecessary_null_comparison
+ : assert(receiver != null) {
+ receiver.parent = this;
+ }
+
+ @override
+ ExpressionInferenceResult acceptInference(
+ InferenceVisitor visitor, DartType typeContext) {
+ return visitor.visitPropertyGet(this, typeContext);
+ }
+
+ @override
+ InternalExpressionKind get kind => InternalExpressionKind.PropertyGet;
+
+ @override
+ void visitChildren(Visitor<dynamic> v) {
+ receiver.accept(v);
+ }
+
+ @override
+ void transformChildren(Transformer v) {
+ // ignore: unnecessary_null_comparison
+ if (receiver != null) {
+ receiver = v.transform(receiver);
+ receiver.parent = this;
+ }
+ }
+
+ @override
+ void transformOrRemoveChildren(RemovingTransformer v) {
+ // ignore: unnecessary_null_comparison
+ if (receiver != null) {
+ receiver = v.transform(receiver);
+ receiver.parent = this;
+ }
+ }
+
+ @override
+ String toString() {
+ return "PropertyGet(${toStringInternal()})";
+ }
+
+ @override
+ int get precedence => Precedence.PRIMARY;
+
+ @override
+ void toTextInternal(AstPrinter printer) {
+ printer.writeExpression(receiver, minimumPrecedence: Precedence.PRIMARY);
+ printer.write('.');
+ printer.writeName(name);
+ }
+}
+
+/// A dynamically bound property write of the form `o.foo = e`.
+///
+/// This will be transformed into an [InstanceSet], [DynamicSet], or
+/// [StaticInvocation] (for implicit extension member access) after type
+/// inference.
+class PropertySet extends InternalExpression {
+ Expression receiver;
+ Name name;
+ Expression value;
+
+ /// If `true` the assignment is need for its effect and not for its value.
+ final bool forEffect;
+
+ /// If `true` the receiver can be cloned and doesn't need a temporary variable
+ /// for multiple reads.
+ final bool readOnlyReceiver;
+
+ PropertySet(this.receiver, this.name, this.value,
+ {required this.forEffect, required this.readOnlyReceiver})
+ // ignore: unnecessary_null_comparison
+ : assert(receiver != null),
+ // ignore: unnecessary_null_comparison
+ assert(value != null),
+ // ignore: unnecessary_null_comparison
+ assert(forEffect != null),
+ // ignore: unnecessary_null_comparison
+ assert(readOnlyReceiver != null) {
+ receiver.parent = this;
+ value.parent = this;
+ }
+
+ @override
+ ExpressionInferenceResult acceptInference(
+ InferenceVisitor visitor, DartType typeContext) {
+ return visitor.visitPropertySet(this, typeContext);
+ }
+
+ @override
+ InternalExpressionKind get kind => InternalExpressionKind.PropertySet;
+
+ @override
+ void visitChildren(Visitor v) {
+ receiver.accept(v);
+ name.accept(v);
+ value.accept(v);
+ }
+
+ @override
+ void transformChildren(Transformer v) {
+ // ignore: unnecessary_null_comparison
+ if (receiver != null) {
+ receiver = v.transform(receiver);
+ receiver.parent = this;
+ }
+ // ignore: unnecessary_null_comparison
+ if (value != null) {
+ value = v.transform(value);
+ value.parent = this;
+ }
+ }
+
+ @override
+ void transformOrRemoveChildren(RemovingTransformer v) {
+ // ignore: unnecessary_null_comparison
+ if (receiver != null) {
+ receiver = v.transform(receiver);
+ receiver.parent = this;
+ }
+ // ignore: unnecessary_null_comparison
+ if (value != null) {
+ value = v.transform(value);
+ value.parent = this;
+ }
+ }
+
+ @override
+ String toString() {
+ return "PropertySet(${toStringInternal()})";
+ }
+
+ @override
+ void toTextInternal(AstPrinter printer) {
+ printer.writeExpression(receiver, minimumPrecedence: Precedence.PRIMARY);
+ printer.write('.');
+ printer.writeName(name);
+ printer.write(' = ');
+ printer.writeExpression(value);
+ }
+}
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_ast_api.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_ast_api.dart
index 775003f..7c62ddb 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_ast_api.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_ast_api.dart
@@ -48,7 +48,6 @@
MapLiteralEntry,
MapLiteral,
Member,
- MethodInvocation,
Name,
NamedExpression,
NamedType,
@@ -56,8 +55,6 @@
NullLiteral,
Procedure,
ProcedureKind,
- PropertyGet,
- PropertySet,
Rethrow,
ReturnStatement,
Statement,
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_constants.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_constants.dart
index 6868aa7..d0033fa 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_constants.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_constants.dart
@@ -46,6 +46,17 @@
@override
void reportInvalidExpression(InvalidExpression node) {
+ // TODO(johnniwinther): Improve the precision of this assertion. Do we
+ // for instance allow warnings only to have been reported in previous
+ // compilations.
+ assert(
+ // Either we have already reported an error
+ loader.hasSeenError ||
+ // or we have reported an error in a previous compilation.
+ loader.builders.values.any((builder) =>
+ builder.library.problemsAsJson?.isNotEmpty ?? false),
+ "No error reported before seeing: "
+ "${node.message}");
// Assumed to be already reported.
}
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_helper.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_helper.dart
new file mode 100644
index 0000000..71176e5
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_helper.dart
@@ -0,0 +1,120 @@
+// Copyright (c) 2016, 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.
+
+library fasta.kernel_target;
+
+import 'package:kernel/ast.dart';
+import 'package:kernel/clone.dart' show CloneVisitorNotMembers;
+import 'package:kernel/type_algebra.dart' show Substitution;
+
+/// Data for clone default values for synthesized function nodes once the
+/// original default values have been computed.
+///
+/// This is used for constructors in unnamed mixin application, which are
+/// created from the constructors in the superclass, and for tear off lowerings
+/// for redirecting factories, which are created from the effective target
+/// constructor.
+class SynthesizedFunctionNode {
+ /// Type parameter map from type parameters in scope [_original] to types
+ /// in scope of [_synthesized].
+ // TODO(johnniwinther): Is this ever needed? Should occurrence of type
+ // variable types in default values be a compile time error?
+ final Map<TypeParameter, DartType> _typeSubstitution;
+
+ /// The original function node.
+ final FunctionNode _original;
+
+ /// The synthesized function node.
+ final FunctionNode _synthesized;
+
+ /// If `true`, the [_synthesized] is guaranteed to have the same parameters in
+ /// the same order as [_original]. Otherwise [_original] is only guaranteed to
+ /// be callable from [_synthesized], meaning that is has at most the same
+ /// number of positional parameters and a, possibly reordered, subset of the
+ /// named parameters.
+ final bool identicalSignatures;
+
+ SynthesizedFunctionNode(
+ this._typeSubstitution, this._original, this._synthesized,
+ {this.identicalSignatures: true});
+
+ void cloneDefaultValues() {
+ // TODO(ahe): It is unclear if it is legal to use type variables in
+ // default values, but Fasta is currently allowing it, and the VM
+ // accepts it. If it isn't legal, the we can speed this up by using a
+ // single cloner without substitution.
+ CloneVisitorNotMembers? cloner;
+
+ void cloneInitializer(VariableDeclaration originalParameter,
+ VariableDeclaration clonedParameter) {
+ if (originalParameter.initializer != null) {
+ cloner ??=
+ new CloneVisitorNotMembers(typeSubstitution: _typeSubstitution);
+ clonedParameter.initializer = cloner!
+ .clone(originalParameter.initializer!)
+ ..parent = clonedParameter;
+ }
+ }
+
+ // For mixin application constructors, the argument count is the same, but
+ // for redirecting tear off lowerings, the argument count of the tear off
+ // can be less than that of the redirection target.
+
+ assert(_synthesized.positionalParameters.length <=
+ _original.positionalParameters.length);
+ for (int i = 0; i < _synthesized.positionalParameters.length; i++) {
+ cloneInitializer(_original.positionalParameters[i],
+ _synthesized.positionalParameters[i]);
+ }
+
+ if (identicalSignatures) {
+ assert(_synthesized.namedParameters.length ==
+ _original.namedParameters.length);
+ for (int i = 0; i < _synthesized.namedParameters.length; i++) {
+ cloneInitializer(
+ _original.namedParameters[i], _synthesized.namedParameters[i]);
+ }
+ } else if (_synthesized.namedParameters.isNotEmpty) {
+ Map<String, VariableDeclaration> originalParameters = {};
+ for (int i = 0; i < _original.namedParameters.length; i++) {
+ originalParameters[_original.namedParameters[i].name!] =
+ _original.namedParameters[i];
+ }
+ for (int i = 0; i < _synthesized.namedParameters.length; i++) {
+ cloneInitializer(
+ originalParameters[_synthesized.namedParameters[i].name!]!,
+ _synthesized.namedParameters[i]);
+ }
+ }
+ }
+}
+
+class TypeDependency {
+ final Member synthesized;
+ final Member original;
+ final Substitution substitution;
+
+ TypeDependency(this.synthesized, this.original, this.substitution);
+
+ void copyInferred() {
+ for (int i = 0; i < original.function!.positionalParameters.length; i++) {
+ VariableDeclaration synthesizedParameter =
+ synthesized.function!.positionalParameters[i];
+ VariableDeclaration constructorParameter =
+ original.function!.positionalParameters[i];
+ synthesizedParameter.type =
+ substitution.substituteType(constructorParameter.type);
+ }
+ for (int i = 0; i < original.function!.namedParameters.length; i++) {
+ VariableDeclaration synthesizedParameter =
+ synthesized.function!.namedParameters[i];
+ VariableDeclaration originalParameter =
+ original.function!.namedParameters[i];
+ synthesizedParameter.type =
+ substitution.substituteType(originalParameter.type);
+ }
+ synthesized.function!.returnType =
+ substitution.substituteType(original.function!.returnType);
+ }
+}
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 2531ba7..93fb9a8 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -6,7 +6,6 @@
import 'package:kernel/ast.dart';
import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
-import 'package:kernel/clone.dart' show CloneVisitorNotMembers;
import 'package:kernel/core_types.dart';
import 'package:kernel/reference_from_index.dart' show IndexedClass;
import 'package:kernel/target/changed_structure_notifier.dart'
@@ -82,6 +81,7 @@
transformProcedure,
ConstantCoverage;
import 'kernel_constants.dart' show KernelConstantErrorReporter;
+import 'kernel_helper.dart';
import 'verifier.dart' show verifyComponent, verifyGetStaticType;
class KernelTarget extends TargetImplementation {
@@ -139,7 +139,8 @@
final bool errorOnUnevaluatedConstant =
CompilerContext.current.options.errorOnUnevaluatedConstant;
- final List<ClonedFunctionNode> clonedFunctionNodes = <ClonedFunctionNode>[];
+ final List<SynthesizedFunctionNode> synthesizedFunctionNodes =
+ <SynthesizedFunctionNode>[];
KernelTarget(this.fileSystem, this.includeComments, DillTarget dillTarget,
UriTranslator uriTranslator)
@@ -330,13 +331,15 @@
computeCoreTypes();
loader.buildClassHierarchy(myClasses, objectClassBuilder);
loader.computeHierarchy();
+ loader.installTypedefTearOffs();
loader.performTopLevelInference(myClasses);
loader.checkSupertypes(myClasses);
loader.checkOverrides(myClasses);
loader.checkAbstractMembers(myClasses);
loader.addNoSuchMethodForwarders(myClasses);
loader.checkMixins(myClasses);
- loader.buildOutlineExpressions(loader.coreTypes);
+ loader.buildOutlineExpressions(
+ loader.coreTypes, synthesizedFunctionNodes);
loader.checkTypes();
loader.checkRedirectingFactories(myClasses);
loader.checkMainMethods();
@@ -361,7 +364,7 @@
return withCrashReporting<Component?>(() async {
ticker.logMs("Building component");
await loader.buildBodies();
- finishClonedParameters();
+ finishSynthesizedParameters();
loader.finishDeferredLoadTearoffs();
loader.finishNoSuchMethodForwarders();
List<SourceClassBuilder> myClasses = collectMyClasses();
@@ -598,7 +601,7 @@
assert(!builder.isExtension);
// TODO(askesc): Make this check light-weight in the absence of patches.
if (builder.cls.constructors.isNotEmpty) return;
- if (builder.cls.redirectingFactoryConstructors.isNotEmpty) return;
+ if (builder.cls.redirectingFactories.isNotEmpty) return;
for (Procedure proc in builder.cls.procedures) {
if (proc.isFactory) return;
}
@@ -713,7 +716,9 @@
Constructor? referenceFrom) {
VariableDeclaration copyFormal(VariableDeclaration formal) {
VariableDeclaration copy = new VariableDeclaration(formal.name,
- isFinal: formal.isFinal, isConst: formal.isConst);
+ isFinal: formal.isFinal,
+ isConst: formal.isConst,
+ type: const UnknownType());
if (formal.type is! UnknownType) {
copy.type = substitute(formal.type, substitutionMap);
} else {
@@ -757,16 +762,17 @@
returnType: makeConstructorReturnType(cls));
SuperInitializer initializer = new SuperInitializer(
constructor, new Arguments(positional, named: named));
- ClonedFunctionNode clonedFunctionNode =
- new ClonedFunctionNode(substitutionMap, constructor.function, function);
+ SynthesizedFunctionNode synthesizedFunctionNode =
+ new SynthesizedFunctionNode(
+ substitutionMap, constructor.function, function);
if (!isConst) {
// For constant constructors default values are computed and cloned part
// of the outline expression and therefore passed to the
// [SyntheticConstructorBuilder] below.
//
// For non-constant constructors default values are cloned as part of the
- // full compilation using [clonedFunctionNodes].
- clonedFunctionNodes.add(clonedFunctionNode);
+ // full compilation using [synthesizedFunctionNodes].
+ synthesizedFunctionNodes.add(synthesizedFunctionNode);
}
return new SyntheticConstructorBuilder(
classBuilder,
@@ -785,14 +791,15 @@
// cloned function nodes to ensure that the default values are computed
// and cloned for the outline.
origin: isConst ? memberBuilder : null,
- clonedFunctionNode: isConst ? clonedFunctionNode : null);
+ synthesizedFunctionNode: isConst ? synthesizedFunctionNode : null);
}
- void finishClonedParameters() {
- for (ClonedFunctionNode clonedFunctionNode in clonedFunctionNodes) {
- clonedFunctionNode.cloneDefaultValues();
+ void finishSynthesizedParameters() {
+ for (SynthesizedFunctionNode synthesizedFunctionNode
+ in synthesizedFunctionNodes) {
+ synthesizedFunctionNode.cloneDefaultValues();
}
- clonedFunctionNodes.clear();
+ synthesizedFunctionNodes.clear();
ticker.logMs("Cloned default values of formals");
}
@@ -810,7 +817,7 @@
..isNonNullableByDefault =
enclosingClass.enclosingLibrary.isNonNullableByDefault;
Procedure? constructorTearOff = createConstructorTearOffProcedure(
- '', classBuilder.library, constructor.fileOffset,
+ '', classBuilder.library, classBuilder.fileUri, constructor.fileOffset,
forAbstractClassOrEnum:
enclosingClass.isAbstract || enclosingClass.isEnum);
if (constructorTearOff != null) {
@@ -1046,8 +1053,12 @@
// To report errors on the first definition of a constructor, we need to
// iterate until that last element.
ConstructorBuilder earliest = constructorBuilder;
- while (earliest.next != null) {
- earliest = earliest.next as ConstructorBuilder;
+ Builder earliestBuilder = constructorBuilder;
+ while (earliestBuilder.next != null) {
+ earliestBuilder = earliestBuilder.next!;
+ if (earliestBuilder is ConstructorBuilder) {
+ earliest = earliestBuilder;
+ }
}
bool isRedirecting = false;
@@ -1246,9 +1257,7 @@
if (loader.target.context.options
.isExperimentEnabledGlobally(ExperimentalFlag.valueClass)) {
valueClass.transformComponent(
- component!, loader.coreTypes, loader.hierarchy, environment,
- useNewMethodInvocationEncoding:
- backendTarget.supportsNewMethodInvocationEncoding);
+ component!, loader.coreTypes, loader.hierarchy, environment);
ticker.logMs("Lowered value classes");
}
@@ -1399,7 +1408,7 @@
KernelDiagnosticReporter(this.loader);
- void report(Message message, int charOffset, int length, Uri fileUri,
+ void report(Message message, int charOffset, int length, Uri? fileUri,
{List<LocatedMessage>? context}) {
loader.addProblem(message, charOffset, noLength, fileUri, context: context);
}
@@ -1419,43 +1428,7 @@
void updateType() {
// ignore: unnecessary_null_comparison
- assert(source.type != null, "No type computed for $source.");
+ assert(source.type is! UnknownType, "No type computed for $source.");
target.type = substitute(source.type, substitutionMap);
}
}
-
-class ClonedFunctionNode {
- final Map<TypeParameter, DartType> _typeSubstitution;
- final FunctionNode _original;
- final FunctionNode _clone;
-
- ClonedFunctionNode(this._typeSubstitution, this._original, this._clone);
-
- void cloneDefaultValues() {
- // TODO(ahe): It is unclear if it is legal to use type variables in
- // default values, but Fasta is currently allowing it, and the VM
- // accepts it. If it isn't legal, the we can speed this up by using a
- // single cloner without substitution.
- CloneVisitorNotMembers? cloner;
-
- void cloneInitializer(VariableDeclaration originalParameter,
- VariableDeclaration clonedParameter) {
- if (originalParameter.initializer != null) {
- cloner ??=
- new CloneVisitorNotMembers(typeSubstitution: _typeSubstitution);
- clonedParameter.initializer = cloner!
- .clone(originalParameter.initializer!)
- ..parent = clonedParameter;
- }
- }
-
- for (int i = 0; i < _original.positionalParameters.length; i++) {
- cloneInitializer(
- _original.positionalParameters[i], _clone.positionalParameters[i]);
- }
-
- for (int i = 0; i < _original.namedParameters.length; i++) {
- cloneInitializer(_original.namedParameters[i], _clone.namedParameters[i]);
- }
- }
-}
diff --git a/pkg/front_end/lib/src/fasta/kernel/late_lowering.dart b/pkg/front_end/lib/src/fasta/kernel/late_lowering.dart
index 8a9c80c..4f1045c 100644
--- a/pkg/front_end/lib/src/fasta/kernel/late_lowering.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/late_lowering.dart
@@ -7,7 +7,6 @@
import '../../base/nnbd_mode.dart';
import '../source/source_library_builder.dart';
-import '../names.dart';
const String lateFieldPrefix = '_#';
const String lateIsSetSuffix = '#isSet';
@@ -20,15 +19,9 @@
///
/// Late final fields and locals need to detect writes during initialization and
/// therefore uses [createGetterWithInitializerWithRecheck] instead.
-Statement createGetterWithInitializer(
- CoreTypes coreTypes,
- int fileOffset,
- String name,
- DartType type,
- Expression initializer,
- bool useNewMethodInvocationEncoding,
- {required Expression createVariableRead(bool useNewMethodInvocationEncoding,
- {bool needsPromotion}),
+Statement createGetterWithInitializer(CoreTypes coreTypes, int fileOffset,
+ String name, DartType type, Expression initializer,
+ {required Expression createVariableRead({bool needsPromotion}),
required Expression createVariableWrite(Expression value),
required Expression createIsSetRead(),
required Expression createIsSetWrite(Expression value),
@@ -64,8 +57,7 @@
// If [type] is a type variable with undetermined nullability we
// need to create a read of the field that is promoted to the type
// variable type.
- createVariableRead(useNewMethodInvocationEncoding,
- needsPromotion: type.isPotentiallyNonNullable))
+ createVariableRead(needsPromotion: type.isPotentiallyNonNullable))
..fileOffset = fileOffset
])
..fileOffset = fileOffset;
@@ -74,9 +66,7 @@
//
// return let # = _#field in isSentinel(#) ? _#field = <init> : #;
VariableDeclaration variable = new VariableDeclaration.forValue(
- createVariableRead(useNewMethodInvocationEncoding,
- needsPromotion: false)
- ..fileOffset = fileOffset,
+ createVariableRead(needsPromotion: false)..fileOffset = fileOffset,
type: type.withDeclaredNullability(Nullability.nullable))
..fileOffset = fileOffset;
return new ReturnStatement(
@@ -101,46 +91,30 @@
//
// return let # = _#field in # == null ? _#field = <init> : #;
VariableDeclaration variable = new VariableDeclaration.forValue(
- createVariableRead(useNewMethodInvocationEncoding,
- needsPromotion: false)
- ..fileOffset = fileOffset,
+ createVariableRead(needsPromotion: false)..fileOffset = fileOffset,
type: type.withDeclaredNullability(Nullability.nullable))
..fileOffset = fileOffset;
- return new ReturnStatement(new Let(
- variable,
- new ConditionalExpression(
- useNewMethodInvocationEncoding
- ? (new EqualsNull(
+ return new ReturnStatement(
+ new Let(
+ variable,
+ new ConditionalExpression(
+ new EqualsNull(
new VariableGet(variable)..fileOffset = fileOffset)
- ..fileOffset = fileOffset)
- : new MethodInvocation(
- new VariableGet(variable)..fileOffset = fileOffset,
- equalsName,
- new Arguments(<Expression>[
- new NullLiteral()..fileOffset = fileOffset
- ])
- ..fileOffset = fileOffset)
- ..fileOffset = fileOffset,
- createVariableWrite(initializer)..fileOffset = fileOffset,
- new VariableGet(variable, type)..fileOffset = fileOffset,
- type)
+ ..fileOffset = fileOffset,
+ createVariableWrite(initializer)..fileOffset = fileOffset,
+ new VariableGet(variable, type)..fileOffset = fileOffset,
+ type)
+ ..fileOffset = fileOffset)
..fileOffset = fileOffset)
- ..fileOffset = fileOffset)
..fileOffset = fileOffset;
}
}
/// Creates the body for the synthesized getter used to encode the lowering
/// of a late final field or local with an initializer.
-Statement createGetterWithInitializerWithRecheck(
- CoreTypes coreTypes,
- int fileOffset,
- String name,
- DartType type,
- Expression initializer,
- bool useNewMethodInvocationEncoding,
- {required Expression createVariableRead(bool useNewMethodInvocationEncoding,
- {bool needsPromotion}),
+Statement createGetterWithInitializerWithRecheck(CoreTypes coreTypes,
+ int fileOffset, String name, DartType type, Expression initializer,
+ {required Expression createVariableRead({bool needsPromotion}),
required Expression createVariableWrite(Expression value),
required Expression createIsSetRead(),
required Expression createIsSetWrite(Expression value),
@@ -202,8 +176,7 @@
// If [type] is a type variable with undetermined nullability we
// need to create a read of the field that is promoted to the type
// variable type.
- createVariableRead(useNewMethodInvocationEncoding,
- needsPromotion: type.isPotentiallyNonNullable))
+ createVariableRead(needsPromotion: type.isPotentiallyNonNullable))
..fileOffset = fileOffset
])
..fileOffset = fileOffset;
@@ -215,43 +188,41 @@
// ? _#field = #2 : throw '...'
// : #1;
VariableDeclaration variable = new VariableDeclaration.forValue(
- createVariableRead(useNewMethodInvocationEncoding,
- needsPromotion: false)
- ..fileOffset = fileOffset,
+ createVariableRead(needsPromotion: false)..fileOffset = fileOffset,
type: type)
..fileOffset = fileOffset;
- return new ReturnStatement(new Let(
- variable,
- new ConditionalExpression(
- new StaticInvocation(
- coreTypes.isSentinelMethod,
- new Arguments(<Expression>[
- new VariableGet(variable)..fileOffset = fileOffset
- ])
- ..fileOffset = fileOffset)
- ..fileOffset = fileOffset,
- new Let(
- temp,
- new ConditionalExpression(
- new StaticInvocation(
- coreTypes.isSentinelMethod,
- new Arguments(<Expression>[
- createVariableRead(useNewMethodInvocationEncoding,
- needsPromotion: false)
- ..fileOffset = fileOffset
- ])
- ..fileOffset = fileOffset)
- ..fileOffset = fileOffset,
- createVariableWrite(
- new VariableGet(temp)..fileOffset = fileOffset)
- ..fileOffset = fileOffset,
- exception,
- type)
- ..fileOffset = fileOffset),
- new VariableGet(variable)..fileOffset = fileOffset,
- type)
+ return new ReturnStatement(
+ new Let(
+ variable,
+ new ConditionalExpression(
+ new StaticInvocation(
+ coreTypes.isSentinelMethod,
+ new Arguments(<Expression>[
+ new VariableGet(variable)..fileOffset = fileOffset
+ ])
+ ..fileOffset = fileOffset)
+ ..fileOffset = fileOffset,
+ new Let(
+ temp,
+ new ConditionalExpression(
+ new StaticInvocation(
+ coreTypes.isSentinelMethod,
+ new Arguments(<Expression>[
+ createVariableRead(needsPromotion: false)
+ ..fileOffset = fileOffset
+ ])
+ ..fileOffset = fileOffset)
+ ..fileOffset = fileOffset,
+ createVariableWrite(
+ new VariableGet(temp)..fileOffset = fileOffset)
+ ..fileOffset = fileOffset,
+ exception,
+ type)
+ ..fileOffset = fileOffset),
+ new VariableGet(variable)..fileOffset = fileOffset,
+ type)
+ ..fileOffset = fileOffset)
..fileOffset = fileOffset)
- ..fileOffset = fileOffset)
..fileOffset = fileOffset;
case IsSetEncoding.useNull:
// Generate:
@@ -261,55 +232,33 @@
// ? _#field = #2 : throw '...'
// : #1;
VariableDeclaration variable = new VariableDeclaration.forValue(
- createVariableRead(useNewMethodInvocationEncoding,
- needsPromotion: false)
- ..fileOffset = fileOffset,
+ createVariableRead(needsPromotion: false)..fileOffset = fileOffset,
type: type.withDeclaredNullability(Nullability.nullable))
..fileOffset = fileOffset;
- return new ReturnStatement(new Let(
- variable,
- new ConditionalExpression(
- useNewMethodInvocationEncoding
- ? (new EqualsNull(
+ return new ReturnStatement(
+ new Let(
+ variable,
+ new ConditionalExpression(
+ new EqualsNull(
new VariableGet(variable)..fileOffset = fileOffset)
- ..fileOffset = fileOffset)
- : new MethodInvocation(
- new VariableGet(variable)..fileOffset = fileOffset,
- equalsName,
- new Arguments(<Expression>[
- new NullLiteral()..fileOffset = fileOffset
- ])
- ..fileOffset = fileOffset)
- ..fileOffset = fileOffset,
- new Let(
- temp,
- new ConditionalExpression(
- useNewMethodInvocationEncoding
- ? (new EqualsNull(
- createVariableRead(useNewMethodInvocationEncoding,
- needsPromotion: false)
+ ..fileOffset = fileOffset,
+ new Let(
+ temp,
+ new ConditionalExpression(
+ new EqualsNull(
+ createVariableRead(needsPromotion: false)
..fileOffset = fileOffset)
- ..fileOffset = fileOffset)
- : new MethodInvocation(
- createVariableRead(useNewMethodInvocationEncoding,
- needsPromotion: false)
- ..fileOffset = fileOffset,
- equalsName,
- new Arguments(<Expression>[
- new NullLiteral()..fileOffset = fileOffset
- ])
- ..fileOffset = fileOffset)
- ..fileOffset = fileOffset,
- createVariableWrite(
- new VariableGet(temp)..fileOffset = fileOffset)
- ..fileOffset = fileOffset,
- exception,
- type)
- ..fileOffset = fileOffset),
- new VariableGet(variable, type)..fileOffset = fileOffset,
- type)
+ ..fileOffset = fileOffset,
+ createVariableWrite(
+ new VariableGet(temp)..fileOffset = fileOffset)
+ ..fileOffset = fileOffset,
+ exception,
+ type)
+ ..fileOffset = fileOffset),
+ new VariableGet(variable, type)..fileOffset = fileOffset,
+ type)
+ ..fileOffset = fileOffset)
..fileOffset = fileOffset)
- ..fileOffset = fileOffset)
..fileOffset = fileOffset;
}
}
@@ -317,13 +266,8 @@
/// Creates the body for the synthesized getter used to encode the lowering
/// of a late field or local without an initializer.
Statement createGetterBodyWithoutInitializer(
- CoreTypes coreTypes,
- int fileOffset,
- String name,
- DartType type,
- bool useNewMethodInvocationEncoding,
- {required Expression createVariableRead(bool useNewMethodInvocationEncoding,
- {bool needsPromotion}),
+ CoreTypes coreTypes, int fileOffset, String name, DartType type,
+ {required Expression createVariableRead({bool needsPromotion}),
required Expression createIsSetRead(),
required IsSetEncoding isSetEncoding,
required bool forField}) {
@@ -349,8 +293,7 @@
return new ReturnStatement(
new ConditionalExpression(
createIsSetRead()..fileOffset = fileOffset,
- createVariableRead(useNewMethodInvocationEncoding,
- needsPromotion: type.isPotentiallyNonNullable)
+ createVariableRead(needsPromotion: type.isPotentiallyNonNullable)
..fileOffset = fileOffset,
exception,
type)
@@ -361,8 +304,7 @@
//
// return let # = _#field in isSentinel(#) ? throw '...' : #;
VariableDeclaration variable = new VariableDeclaration.forValue(
- createVariableRead(useNewMethodInvocationEncoding)
- ..fileOffset = fileOffset,
+ createVariableRead()..fileOffset = fileOffset,
type: type.withDeclaredNullability(Nullability.nullable))
..fileOffset = fileOffset;
return new ReturnStatement(
@@ -387,30 +329,21 @@
//
// return let # = _#field in # == null ? throw '...' : #;
VariableDeclaration variable = new VariableDeclaration.forValue(
- createVariableRead(useNewMethodInvocationEncoding)
- ..fileOffset = fileOffset,
+ createVariableRead()..fileOffset = fileOffset,
type: type.withDeclaredNullability(Nullability.nullable))
..fileOffset = fileOffset;
- return new ReturnStatement(new Let(
- variable,
- new ConditionalExpression(
- useNewMethodInvocationEncoding
- ? (new EqualsNull(
+ return new ReturnStatement(
+ new Let(
+ variable,
+ new ConditionalExpression(
+ new EqualsNull(
new VariableGet(variable)..fileOffset = fileOffset)
- ..fileOffset = fileOffset)
- : new MethodInvocation(
- new VariableGet(variable)..fileOffset = fileOffset,
- equalsName,
- new Arguments(<Expression>[
- new NullLiteral()..fileOffset = fileOffset
- ])
- ..fileOffset = fileOffset)
- ..fileOffset = fileOffset,
- exception,
- new VariableGet(variable, type)..fileOffset = fileOffset,
- type)
+ ..fileOffset = fileOffset,
+ exception,
+ new VariableGet(variable, type)..fileOffset = fileOffset,
+ type)
+ ..fileOffset = fileOffset)
..fileOffset = fileOffset)
- ..fileOffset = fileOffset)
..fileOffset = fileOffset;
}
}
@@ -464,15 +397,10 @@
/// Creates the body for the synthesized setter used to encode the lowering
/// of a final late field or local.
-Statement createSetterBodyFinal(
- CoreTypes coreTypes,
- int fileOffset,
- String name,
- VariableDeclaration parameter,
- DartType type,
- bool useNewMethodInvocationEncoding,
+Statement createSetterBodyFinal(CoreTypes coreTypes, int fileOffset,
+ String name, VariableDeclaration parameter, DartType type,
{required bool shouldReturnValue,
- required Expression createVariableRead(bool useNewMethodInvocationEncoding),
+ required Expression createVariableRead(),
required Expression createVariableWrite(Expression value),
required Expression createIsSetRead(),
required Expression createIsSetWrite(Expression value),
@@ -536,10 +464,8 @@
return new IfStatement(
new StaticInvocation(
coreTypes.isSentinelMethod,
- new Arguments(<Expression>[
- createVariableRead(useNewMethodInvocationEncoding)
- ..fileOffset = fileOffset
- ])
+ new Arguments(
+ <Expression>[createVariableRead()..fileOffset = fileOffset])
..fileOffset = fileOffset)
..fileOffset = fileOffset,
createReturn(createVariableWrite(
@@ -556,18 +482,7 @@
// throw '...';
// }
return new IfStatement(
- useNewMethodInvocationEncoding
- ? (new EqualsNull(
- createVariableRead(useNewMethodInvocationEncoding)
- ..fileOffset = fileOffset)
- ..fileOffset = fileOffset)
- : new MethodInvocation(
- createVariableRead(useNewMethodInvocationEncoding)
- ..fileOffset = fileOffset,
- equalsName,
- new Arguments(
- <Expression>[new NullLiteral()..fileOffset = fileOffset])
- ..fileOffset = fileOffset)
+ new EqualsNull(createVariableRead()..fileOffset = fileOffset)
..fileOffset = fileOffset,
createReturn(createVariableWrite(
new VariableGet(parameter)..fileOffset = fileOffset)
diff --git a/pkg/front_end/lib/src/fasta/kernel/redirecting_factory_body.dart b/pkg/front_end/lib/src/fasta/kernel/redirecting_factory_body.dart
index 265cee2..4f63d8b 100644
--- a/pkg/front_end/lib/src/fasta/kernel/redirecting_factory_body.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/redirecting_factory_body.dart
@@ -179,12 +179,11 @@
}
RedirectionTarget? getRedirectionTarget(Procedure member, EnsureLoaded helper) {
- List<DartType> typeArguments = <DartType>[]..length =
- member.function.typeParameters.length;
- for (int i = 0; i < typeArguments.length; i++) {
- typeArguments[i] = new TypeParameterType.withDefaultNullabilityForLibrary(
+ List<DartType> typeArguments = new List<DartType>.generate(
+ member.function.typeParameters.length, (int i) {
+ return new TypeParameterType.withDefaultNullabilityForLibrary(
member.function.typeParameters[i], member.enclosingLibrary);
- }
+ }, growable: true);
// We use the [tortoise and hare algorithm]
// (https://en.wikipedia.org/wiki/Cycle_detection#Tortoise_and_hare) to
@@ -201,15 +200,15 @@
Member nextTortoise = tortoiseBody!.target!;
helper.ensureLoaded(nextTortoise);
List<DartType>? nextTypeArguments = tortoiseBody.typeArguments;
- if (nextTypeArguments == null) {
- nextTypeArguments = <DartType>[];
- }
-
- Substitution sub = Substitution.fromPairs(
- tortoise.function!.typeParameters, typeArguments);
- typeArguments = <DartType>[]..length = nextTypeArguments.length;
- for (int i = 0; i < typeArguments.length; i++) {
- typeArguments[i] = sub.substituteType(nextTypeArguments[i]);
+ if (nextTypeArguments != null) {
+ Substitution sub = Substitution.fromPairs(
+ tortoise.function!.typeParameters, typeArguments);
+ typeArguments =
+ new List<DartType>.generate(nextTypeArguments.length, (int i) {
+ return sub.substituteType(nextTypeArguments[i]);
+ }, growable: true);
+ } else {
+ typeArguments = <DartType>[];
}
tortoise = nextTortoise;
diff --git a/pkg/front_end/lib/src/fasta/kernel/transform_collections.dart b/pkg/front_end/lib/src/fasta/kernel/transform_collections.dart
index af26d1b..ed6516b 100644
--- a/pkg/front_end/lib/src/fasta/kernel/transform_collections.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/transform_collections.dart
@@ -46,7 +46,6 @@
final Procedure _setAddAll;
late final FunctionType _setAddAllFunctionType;
final Procedure _setOf;
- final Procedure _objectEquals;
final Procedure _mapEntries;
final Procedure _mapPut;
late final FunctionType _mapPutFunctionType;
@@ -54,7 +53,6 @@
final Field _mapEntryKey;
final Field _mapEntryValue;
final SourceLoaderDataForTesting? _dataForTesting;
- final bool useNewMethodInvocationEncoding;
/// Library that contains the transformed nodes.
///
@@ -83,8 +81,6 @@
_setAddAll =
_loader.coreTypes.index.getProcedure('dart:core', 'Set', 'addAll'),
_setOf = _findSetFactory(_loader.coreTypes, 'of'),
- _objectEquals =
- _loader.coreTypes.index.getProcedure('dart:core', 'Object', '=='),
_mapEntries = _loader.coreTypes.index
.getProcedure('dart:core', 'Map', 'get:entries'),
_mapPut =
@@ -95,9 +91,7 @@
_loader.coreTypes.index.getField('dart:core', 'MapEntry', 'key'),
_mapEntryValue =
_loader.coreTypes.index.getField('dart:core', 'MapEntry', 'value'),
- _dataForTesting = _loader.dataForTesting,
- useNewMethodInvocationEncoding =
- _loader.target.backendTarget.supportsNewMethodInvocationEncoding {
+ _dataForTesting = _loader.dataForTesting {
_listAddFunctionType = _listAdd.getterType as FunctionType;
_listAddAllFunctionType = _listAddAll.getterType as FunctionType;
_setAddFunctionType = _setAdd.getterType as FunctionType;
@@ -908,24 +902,17 @@
assert(argument != null);
assert(argument.fileOffset != TreeNode.noOffset,
"No fileOffset on ${argument}.");
- if (useNewMethodInvocationEncoding) {
- DartType functionType = Substitution.fromInterfaceType(receiverType)
- .substituteType(isSet ? _setAddFunctionType : _listAddFunctionType);
- if (!_currentLibrary!.isNonNullableByDefault) {
- functionType = legacyErasure(functionType);
- }
- return new InstanceInvocation(InstanceAccessKind.Instance, receiver,
- new Name('add'), new Arguments([argument]),
- functionType: functionType as FunctionType,
- interfaceTarget: isSet ? _setAdd : _listAdd)
- ..fileOffset = argument.fileOffset
- ..isInvariant = true;
- } else {
- return new MethodInvocation(receiver, new Name('add'),
- new Arguments([argument]), isSet ? _setAdd : _listAdd)
- ..fileOffset = argument.fileOffset
- ..isInvariant = true;
+ DartType functionType = Substitution.fromInterfaceType(receiverType)
+ .substituteType(isSet ? _setAddFunctionType : _listAddFunctionType);
+ if (!_currentLibrary!.isNonNullableByDefault) {
+ functionType = legacyErasure(functionType);
}
+ return new InstanceInvocation(InstanceAccessKind.Instance, receiver,
+ new Name('add'), new Arguments([argument]),
+ functionType: functionType as FunctionType,
+ interfaceTarget: isSet ? _setAdd : _listAdd)
+ ..fileOffset = argument.fileOffset
+ ..isInvariant = true;
}
Expression _createAddAll(Expression receiver, InterfaceType receiverType,
@@ -936,43 +923,26 @@
assert(argument != null);
assert(argument.fileOffset != TreeNode.noOffset,
"No fileOffset on ${argument}.");
- if (useNewMethodInvocationEncoding) {
- DartType functionType = Substitution.fromInterfaceType(receiverType)
- .substituteType(
- isSet ? _setAddAllFunctionType : _listAddAllFunctionType);
- if (!_currentLibrary!.isNonNullableByDefault) {
- functionType = legacyErasure(functionType);
- }
- return new InstanceInvocation(InstanceAccessKind.Instance, receiver,
- new Name('addAll'), new Arguments([argument]),
- functionType: functionType as FunctionType,
- interfaceTarget: isSet ? _setAddAll : _listAddAll)
- ..fileOffset = argument.fileOffset
- ..isInvariant = true;
- } else {
- return new MethodInvocation(receiver, new Name('addAll'),
- new Arguments([argument]), isSet ? _setAddAll : _listAddAll)
- ..fileOffset = argument.fileOffset
- ..isInvariant = true;
+ DartType functionType = Substitution.fromInterfaceType(receiverType)
+ .substituteType(
+ isSet ? _setAddAllFunctionType : _listAddAllFunctionType);
+ if (!_currentLibrary!.isNonNullableByDefault) {
+ functionType = legacyErasure(functionType);
}
+ return new InstanceInvocation(InstanceAccessKind.Instance, receiver,
+ new Name('addAll'), new Arguments([argument]),
+ functionType: functionType as FunctionType,
+ interfaceTarget: isSet ? _setAddAll : _listAddAll)
+ ..fileOffset = argument.fileOffset
+ ..isInvariant = true;
}
Expression _createEqualsNull(Expression expression, {bool notEquals: false}) {
// ignore: unnecessary_null_comparison
assert(expression != null);
assert(expression.fileOffset != TreeNode.noOffset);
- Expression check;
- if (useNewMethodInvocationEncoding) {
- check = new EqualsNull(expression)..fileOffset = expression.fileOffset;
- } else {
- check = new MethodInvocation(
- expression,
- new Name('=='),
- new Arguments(
- [new NullLiteral()..fileOffset = expression.fileOffset]),
- _objectEquals)
- ..fileOffset = expression.fileOffset;
- }
+ Expression check = new EqualsNull(expression)
+ ..fileOffset = expression.fileOffset;
if (notEquals) {
check = new Not(check)..fileOffset = expression.fileOffset;
}
@@ -984,23 +954,16 @@
// ignore: unnecessary_null_comparison
assert(fileOffset != null);
assert(fileOffset != TreeNode.noOffset);
- if (useNewMethodInvocationEncoding) {
- DartType functionType = Substitution.fromInterfaceType(receiverType)
- .substituteType(_mapPutFunctionType);
- if (!_currentLibrary!.isNonNullableByDefault) {
- functionType = legacyErasure(functionType);
- }
- return new InstanceInvocation(InstanceAccessKind.Instance, receiver,
- new Name('[]='), new Arguments([key, value]),
- functionType: functionType as FunctionType, interfaceTarget: _mapPut)
- ..fileOffset = fileOffset
- ..isInvariant = true;
- } else {
- return new MethodInvocation(
- receiver, new Name('[]='), new Arguments([key, value]), _mapPut)
- ..fileOffset = fileOffset
- ..isInvariant = true;
+ DartType functionType = Substitution.fromInterfaceType(receiverType)
+ .substituteType(_mapPutFunctionType);
+ if (!_currentLibrary!.isNonNullableByDefault) {
+ functionType = legacyErasure(functionType);
}
+ return new InstanceInvocation(InstanceAccessKind.Instance, receiver,
+ new Name('[]='), new Arguments([key, value]),
+ functionType: functionType as FunctionType, interfaceTarget: _mapPut)
+ ..fileOffset = fileOffset
+ ..isInvariant = true;
}
AsExpression _createImplicitAs(
@@ -1027,17 +990,12 @@
// ignore: unnecessary_null_comparison
assert(fileOffset != null);
assert(fileOffset != TreeNode.noOffset);
- if (useNewMethodInvocationEncoding) {
- DartType resultType = Substitution.fromInterfaceType(entryType)
- .substituteType(_mapEntryKey.type);
- return new InstanceGet(
- InstanceAccessKind.Instance, receiver, new Name('key'),
- interfaceTarget: _mapEntryKey, resultType: resultType)
- ..fileOffset = fileOffset;
- } else {
- return new PropertyGet(receiver, new Name('key'), _mapEntryKey)
- ..fileOffset = fileOffset;
- }
+ DartType resultType = Substitution.fromInterfaceType(entryType)
+ .substituteType(_mapEntryKey.type);
+ return new InstanceGet(
+ InstanceAccessKind.Instance, receiver, new Name('key'),
+ interfaceTarget: _mapEntryKey, resultType: resultType)
+ ..fileOffset = fileOffset;
}
Expression _createGetValue(
@@ -1045,17 +1003,12 @@
// ignore: unnecessary_null_comparison
assert(fileOffset != null);
assert(fileOffset != TreeNode.noOffset);
- if (useNewMethodInvocationEncoding) {
- DartType resultType = Substitution.fromInterfaceType(entryType)
- .substituteType(_mapEntryValue.type);
- return new InstanceGet(
- InstanceAccessKind.Instance, receiver, new Name('value'),
- interfaceTarget: _mapEntryValue, resultType: resultType)
- ..fileOffset = fileOffset;
- } else {
- return new PropertyGet(receiver, new Name('value'), _mapEntryValue)
- ..fileOffset = fileOffset;
- }
+ DartType resultType = Substitution.fromInterfaceType(entryType)
+ .substituteType(_mapEntryValue.type);
+ return new InstanceGet(
+ InstanceAccessKind.Instance, receiver, new Name('value'),
+ interfaceTarget: _mapEntryValue, resultType: resultType)
+ ..fileOffset = fileOffset;
}
Expression _createGetEntries(
@@ -1063,17 +1016,12 @@
// ignore: unnecessary_null_comparison
assert(fileOffset != null);
assert(fileOffset != TreeNode.noOffset);
- if (useNewMethodInvocationEncoding) {
- DartType resultType = Substitution.fromInterfaceType(mapType)
- .substituteType(_mapEntries.getterType);
- return new InstanceGet(
- InstanceAccessKind.Instance, receiver, new Name('entries'),
- interfaceTarget: _mapEntries, resultType: resultType)
- ..fileOffset = fileOffset;
- } else {
- return new PropertyGet(receiver, new Name('entries'), _mapEntries)
- ..fileOffset = fileOffset;
- }
+ DartType resultType = Substitution.fromInterfaceType(mapType)
+ .substituteType(_mapEntries.getterType);
+ return new InstanceGet(
+ InstanceAccessKind.Instance, receiver, new Name('entries'),
+ interfaceTarget: _mapEntries, resultType: resultType)
+ ..fileOffset = fileOffset;
}
ForStatement _createForStatement(
diff --git a/pkg/front_end/lib/src/fasta/kernel/transform_set_literals.dart b/pkg/front_end/lib/src/fasta/kernel/transform_set_literals.dart
index 74246b0..4cab9fe 100644
--- a/pkg/front_end/lib/src/fasta/kernel/transform_set_literals.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/transform_set_literals.dart
@@ -22,7 +22,6 @@
final Procedure setFactory;
final Procedure addMethod;
late final FunctionType _addMethodFunctionType;
- final bool useNewMethodInvocationEncoding;
/// Library that contains the transformed nodes.
///
@@ -44,9 +43,7 @@
SetLiteralTransformer(SourceLoader loader)
: coreTypes = loader.coreTypes,
setFactory = _findSetFactory(loader.coreTypes),
- addMethod = _findAddMethod(loader.coreTypes),
- useNewMethodInvocationEncoding =
- loader.target.backendTarget.supportsNewMethodInvocationEncoding {
+ addMethod = _findAddMethod(loader.coreTypes) {
_addMethodFunctionType = addMethod.getterType as FunctionType;
}
@@ -65,25 +62,20 @@
List<Statement> statements = [setVar];
for (int i = 0; i < node.expressions.length; i++) {
Expression entry = transform(node.expressions[i]);
- Expression methodInvocation;
- if (useNewMethodInvocationEncoding) {
- DartType functionType = Substitution.fromInterfaceType(receiverType)
- .substituteType(_addMethodFunctionType);
- if (!_currentLibrary!.isNonNullableByDefault) {
- functionType = legacyErasure(functionType);
- }
- methodInvocation = new InstanceInvocation(InstanceAccessKind.Instance,
- new VariableGet(setVar), new Name("add"), new Arguments([entry]),
- functionType: functionType as FunctionType,
- interfaceTarget: addMethod)
- ..fileOffset = entry.fileOffset
- ..isInvariant = true;
- } else {
- methodInvocation = new MethodInvocation(new VariableGet(setVar),
- new Name("add"), new Arguments([entry]), addMethod)
- ..fileOffset = entry.fileOffset
- ..isInvariant = true;
+ DartType functionType = Substitution.fromInterfaceType(receiverType)
+ .substituteType(_addMethodFunctionType);
+ if (!_currentLibrary!.isNonNullableByDefault) {
+ functionType = legacyErasure(functionType);
}
+ Expression methodInvocation = new InstanceInvocation(
+ InstanceAccessKind.Instance,
+ new VariableGet(setVar),
+ new Name("add"),
+ new Arguments([entry]),
+ functionType: functionType as FunctionType,
+ interfaceTarget: addMethod)
+ ..fileOffset = entry.fileOffset
+ ..isInvariant = true;
statements.add(new ExpressionStatement(methodInvocation)
..fileOffset = methodInvocation.fileOffset);
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/type_builder_computer.dart b/pkg/front_end/lib/src/fasta/kernel/type_builder_computer.dart
index b5828a4..7f6631d 100644
--- a/pkg/front_end/lib/src/fasta/kernel/type_builder_computer.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/type_builder_computer.dart
@@ -11,6 +11,7 @@
import '../builder/class_builder.dart';
import '../builder/dynamic_type_declaration_builder.dart';
+import '../builder/fixed_type_builder.dart';
import '../builder/formal_parameter_builder.dart';
import '../builder/function_type_builder.dart';
import '../builder/future_or_type_declaration_builder.dart';
@@ -39,7 +40,10 @@
@override
TypeBuilder visitInvalidType(InvalidType node) {
- throw "Not implemented";
+ return new FixedTypeBuilder(
+ node,
+ /* fileUri = */ null,
+ /* charOffset = */ null);
}
@override
diff --git a/pkg/front_end/lib/src/fasta/kernel/type_labeler.dart b/pkg/front_end/lib/src/fasta/kernel/type_labeler.dart
index aeb1696..8a23b53 100644
--- a/pkg/front_end/lib/src/fasta/kernel/type_labeler.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/type_labeler.dart
@@ -361,7 +361,7 @@
}
void visitStaticTearOffConstant(StaticTearOffConstant node) {
- Procedure procedure = node.procedure;
+ Procedure procedure = node.target;
Class? classNode = procedure.enclosingClass;
if (classNode != null) {
result.add(nameForEntity(
@@ -375,8 +375,21 @@
}
void visitConstructorTearOffConstant(ConstructorTearOffConstant node) {
- Constructor constructor = node.constructor;
- Class? classNode = constructor.enclosingClass;
+ Member constructor = node.target;
+ Class classNode = constructor.enclosingClass!;
+ result.add(nameForEntity(
+ classNode,
+ classNode.name,
+ classNode.enclosingLibrary.importUri,
+ classNode.enclosingLibrary.fileUri));
+ result.add(".");
+ result.add(constructor.name.text);
+ }
+
+ void visitRedirectingFactoryTearOffConstant(
+ RedirectingFactoryTearOffConstant node) {
+ Member constructor = node.target;
+ Class classNode = constructor.enclosingClass!;
result.add(nameForEntity(
classNode,
classNode.name,
diff --git a/pkg/front_end/lib/src/fasta/kernel/utils.dart b/pkg/front_end/lib/src/fasta/kernel/utils.dart
index b24667f..a077ad7 100644
--- a/pkg/front_end/lib/src/fasta/kernel/utils.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/utils.dart
@@ -32,9 +32,12 @@
import '../builder/fixed_type_builder.dart';
import '../builder/formal_parameter_builder.dart';
+import '../builder/metadata_builder.dart';
import '../builder/type_builder.dart';
import '../builder/type_variable_builder.dart';
+import '../builder/unresolved_type.dart';
import '../combinator.dart';
+import '../configuration.dart';
import '../identifiers.dart';
import '../source/source_library_builder.dart';
import 'body_builder.dart';
@@ -159,6 +162,7 @@
final Token dummyToken = new SyntheticToken(TokenType.AT, -1);
final Identifier dummyIdentifier = new Identifier(dummyToken);
final Combinator dummyCombinator = new Combinator(false, {}, -1, dummyUri);
+final MetadataBuilder dummyMetadataBuilder = new MetadataBuilder(dummyToken);
final TypeBuilder dummyTypeBuilder =
new FixedTypeBuilder(dummyDartType, dummyUri, -1);
final FormalParameterBuilder dummyFormalParameterBuilder =
@@ -167,3 +171,6 @@
new TypeVariableBuilder(TypeVariableBuilder.noNameSentinel, null, -1, null);
final Label dummyLabel = new Label('', -1);
final FieldInfo dummyFieldInfo = new FieldInfo('', -1, null, dummyToken, -1);
+final Configuration dummyConfiguration = new Configuration(-1, '', '', '');
+final UnresolvedType dummyUnresolvedType =
+ new UnresolvedType(dummyTypeBuilder, -1, dummyUri);
diff --git a/pkg/front_end/lib/src/fasta/kernel/verifier.dart b/pkg/front_end/lib/src/fasta/kernel/verifier.dart
index 363f618..7c313ec 100644
--- a/pkg/front_end/lib/src/fasta/kernel/verifier.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/verifier.dart
@@ -283,7 +283,7 @@
// the shape, but aren't of the RedirectingFactoryBody type.
bool hasBody = isRedirectingFactory(node) ||
RedirectingFactoryBody.hasRedirectingFactoryBodyShape(node);
- bool hasFlag = node.isRedirectingFactoryConstructor;
+ bool hasFlag = node.isRedirectingFactory;
if (hasBody != hasFlag) {
String hasBodyString = hasBody ? "has" : "doesn't have";
String hasFlagString = hasFlag ? "has" : "doesn't have";
@@ -291,7 +291,7 @@
node,
"Procedure '${node.name}' ${hasBodyString} a body "
"of a redirecting factory, but ${hasFlagString} the "
- "'isRedirectingFactoryConstructor' bit set.");
+ "'isRedirectingFactory' bit set.");
}
super.visitProcedure(node);
@@ -437,39 +437,6 @@
}
@override
- void visitMethodInvocation(MethodInvocation node) {
- if (target.supportsNewMethodInvocationEncoding) {
- problem(
- node,
- "New method invocation encoding is supported, "
- "but found a MethodInvocation.");
- }
- super.visitMethodInvocation(node);
- }
-
- @override
- void visitPropertyGet(PropertyGet node) {
- if (target.supportsNewMethodInvocationEncoding) {
- problem(
- node,
- "New method invocation encoding is supported, "
- "but found a PropertyGet.");
- }
- super.visitPropertyGet(node);
- }
-
- @override
- void visitPropertySet(PropertySet node) {
- if (target.supportsNewMethodInvocationEncoding) {
- problem(
- node,
- "New method invocation encoding is supported, "
- "but found a PropertySet.");
- }
- super.visitPropertySet(node);
- }
-
- @override
void defaultTreeNode(TreeNode node) {
enterTreeNode(node);
super.defaultTreeNode(node);
diff --git a/pkg/front_end/lib/src/fasta/loader.dart b/pkg/front_end/lib/src/fasta/loader.dart
index 31aea33..7dedab8 100644
--- a/pkg/front_end/lib/src/fasta/loader.dart
+++ b/pkg/front_end/lib/src/fasta/loader.dart
@@ -81,6 +81,15 @@
final List<FormattedMessage> allComponentProblems = <FormattedMessage>[];
final Set<String> seenMessages = new Set<String>();
+ bool _hasSeenError = false;
+
+ void resetSeenMessages() {
+ seenMessages.clear();
+ _hasSeenError = false;
+ }
+
+ /// Returns `true` if a compile time error has been reported.
+ bool get hasSeenError => _hasSeenError;
LibraryBuilder? _coreLibrary;
LibraryBuilder? typedDataLibrary;
@@ -362,6 +371,9 @@
severity: $severity
""";
if (!seenMessages.add(trace)) return null;
+ if (message.code.severity == Severity.error) {
+ _hasSeenError = true;
+ }
if (message.code.severity == Severity.context) {
internalProblem(
templateInternalProblemContextSeverity
diff --git a/pkg/front_end/lib/src/fasta/scope.dart b/pkg/front_end/lib/src/fasta/scope.dart
index 76daac6..34849e8 100644
--- a/pkg/front_end/lib/src/fasta/scope.dart
+++ b/pkg/front_end/lib/src/fasta/scope.dart
@@ -15,6 +15,7 @@
import 'builder/type_variable_builder.dart';
import 'kernel/body_builder.dart' show JumpTarget;
import 'kernel/class_hierarchy_builder.dart' show ClassMember;
+import 'kernel/kernel_helper.dart';
import 'util/helpers.dart' show DelayedActionPerformer;
import 'fasta_codes.dart'
@@ -806,8 +807,11 @@
ProcedureKind? get kind => null;
@override
- void buildOutlineExpressions(LibraryBuilder library, CoreTypes coreTypes,
- List<DelayedActionPerformer> delayedActionPerformers) {
+ void buildOutlineExpressions(
+ LibraryBuilder library,
+ CoreTypes coreTypes,
+ List<DelayedActionPerformer> delayedActionPerformers,
+ List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
throw new UnsupportedError(
'AmbiguousMemberBuilder.buildOutlineExpressions');
}
diff --git a/pkg/front_end/lib/src/fasta/source/diet_listener.dart b/pkg/front_end/lib/src/fasta/source/diet_listener.dart
index 88490a6..331d16b 100644
--- a/pkg/front_end/lib/src/fasta/source/diet_listener.dart
+++ b/pkg/front_end/lib/src/fasta/source/diet_listener.dart
@@ -339,7 +339,7 @@
debugEvent("TopLevelMethod");
Token bodyToken = pop() as Token;
Object? name = pop();
- Token metadata = pop() as Token;
+ Token? metadata = pop() as Token?;
checkEmpty(beginToken.charOffset);
if (name is ParserRecovery) return;
@@ -509,7 +509,7 @@
debugEvent("Import");
Object? name = pop(NullValue.Prefix);
- Token metadata = pop() as Token;
+ Token? metadata = pop() as Token?;
checkEmpty(importKeyword.charOffset);
if (name is ParserRecovery) return;
@@ -535,7 +535,7 @@
void endExport(Token exportKeyword, Token semicolon) {
debugEvent("Export");
- Token metadata = pop() as Token;
+ Token? metadata = pop() as Token?;
Library libraryNode = libraryBuilder.library;
LibraryDependency dependency =
libraryNode.dependencies[importExportDirectiveIndex++];
@@ -546,7 +546,7 @@
void endPart(Token partKeyword, Token semicolon) {
debugEvent("Part");
- Token metadata = pop() as Token;
+ Token? metadata = pop() as Token?;
Library libraryNode = libraryBuilder.library;
if (libraryNode.parts.length > partDirectiveIndex) {
// If partDirectiveIndex >= libraryNode.parts.length we are in a case of
@@ -588,7 +588,7 @@
debugEvent("ClassFactoryMethod");
Token bodyToken = pop() as Token;
Object? name = pop();
- Token metadata = pop() as Token;
+ Token? metadata = pop() as Token?;
checkEmpty(beginToken.charOffset);
if (name is ParserRecovery || currentClassIsParserRecovery) return;
@@ -699,7 +699,7 @@
// in handleNoFormalParameters rather than the supplied token.
pop(); // bodyToken
Object? name = pop();
- Token metadata = pop() as Token;
+ Token? metadata = pop() as Token?;
checkEmpty(beginToken.charOffset);
if (name is ParserRecovery || currentClassIsParserRecovery) return;
FunctionBuilderImpl builder;
@@ -1054,6 +1054,9 @@
? ""
: nameOrQualified as String;
}
+ if (libraryBuilder.enableConstructorTearOffsInLibrary) {
+ suffix = suffix == "new" ? "" : suffix;
+ }
declaration = currentClass!.constructors.local[suffix];
declaration = handleDuplicatedName(declaration, token);
checkBuilder(token, declaration, nameOrQualified);
diff --git a/pkg/front_end/lib/src/fasta/source/outline_builder.dart b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
index 4cc93c2..1cbd3d7 100644
--- a/pkg/front_end/lib/src/fasta/source/outline_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
@@ -129,9 +129,7 @@
List<String>? popIdentifierList(int count) {
if (count == 0) return null;
- List<String> list = new List<String>.filled(
- count,
- /* dummyValue = */ '');
+ List<String> list = new List<String>.filled(count, /* dummyValue = */ '');
bool isParserRecovery = false;
for (int i = count - 1; i >= 0; i--) {
popCharOffset();
@@ -164,7 +162,8 @@
@override
void endMetadataStar(int count) {
debugEvent("MetadataStar");
- push(const FixedNullableList<MetadataBuilder>().pop(stack, count) ??
+ push(const FixedNullableList<MetadataBuilder>()
+ .popNonNullable(stack, count, dummyMetadataBuilder) ??
NullValue.Metadata);
}
@@ -261,7 +260,8 @@
@override
void endConditionalUris(int count) {
debugEvent("EndConditionalUris");
- push(const FixedNullableList<Configuration>().pop(stack, count) ??
+ push(const FixedNullableList<Configuration>()
+ .popNonNullable(stack, count, dummyConfiguration) ??
NullValue.ConditionalUris);
}
@@ -1371,7 +1371,8 @@
@override
void endTypeArguments(int count, Token beginToken, Token endToken) {
debugEvent("TypeArguments");
- push(const FixedNullableList<TypeBuilder>().pop(stack, count) ??
+ push(const FixedNullableList<TypeBuilder>()
+ .popNonNullable(stack, count, dummyTypeBuilder) ??
NullValue.TypeArguments);
}
@@ -1470,8 +1471,14 @@
if (name is ParserRecovery) {
push(name);
} else {
- push(libraryBuilder.addFormalParameter(metadata, modifiers, type,
- name as String, thisKeyword != null, charOffset, initializerStart));
+ push(libraryBuilder.addFormalParameter(
+ metadata,
+ modifiers,
+ type,
+ name == null ? FormalParameterBuilder.noNameSentinel : name as String,
+ thisKeyword != null,
+ charOffset,
+ initializerStart));
}
}
@@ -1559,8 +1566,8 @@
assert(formals.isNotEmpty);
if (formals.length == 2) {
// The name may be null for generalized function types.
- // ignore: unnecessary_null_comparison
- if (formals[0].name != null && formals[0].name == formals[1].name) {
+ if (formals[0].name != FormalParameterBuilder.noNameSentinel &&
+ formals[0].name == formals[1].name) {
addProblem(
templateDuplicatedParameterName.withArguments(formals[1].name),
formals[1].charOffset,
@@ -1576,8 +1583,7 @@
Map<String, FormalParameterBuilder> seenNames =
<String, FormalParameterBuilder>{};
for (FormalParameterBuilder formal in formals) {
- // ignore: unnecessary_null_comparison
- if (formal.name == null) continue;
+ if (formal.name == FormalParameterBuilder.noNameSentinel) continue;
if (seenNames.containsKey(formal.name)) {
addProblem(
templateDuplicatedParameterName.withArguments(formal.name),
@@ -1808,11 +1814,7 @@
checkEmpty(beginToken.charOffset);
if (fieldInfos == null) return;
libraryBuilder.addFields(
- metadata,
- modifiers,
- /* isTopLevel = */ true,
- type,
- fieldInfos);
+ metadata, modifiers, /* isTopLevel = */ true, type, fieldInfos);
}
@override
@@ -1873,11 +1875,7 @@
List<MetadataBuilder>? metadata = pop() as List<MetadataBuilder>?;
if (fieldInfos == null) return;
libraryBuilder.addFields(
- metadata,
- modifiers,
- /* isTopLevel = */ false,
- type,
- fieldInfos);
+ metadata, modifiers, /* isTopLevel = */ false, type, fieldInfos);
}
List<FieldInfo>? popFieldInfos(int count) {
@@ -1887,7 +1885,7 @@
bool isParserRecovery = false;
for (int i = count - 1; i != -1; i--) {
int charEndOffset = popCharOffset();
- Token beforeLast = pop() as Token;
+ Token? beforeLast = pop() as Token?;
Token? initializerTokenForInference = pop() as Token?;
int charOffset = popCharOffset();
Object? name = pop(NullValue.Identifier);
@@ -1919,7 +1917,8 @@
void handleTypeVariablesDefined(Token token, int count) {
debugEvent("TypeVariablesDefined");
assert(count > 0);
- push(const FixedNullableList<TypeVariableBuilder>().pop(stack, count) ??
+ push(const FixedNullableList<TypeVariableBuilder>()
+ .popNonNullable(stack, count, dummyTypeVariableBuilder) ??
NullValue.TypeVariables);
}
@@ -2232,13 +2231,15 @@
@override
void handleNewAsIdentifier(Token token) {
- // TODO(johnniwinther, paulberry): disable this error when the
- // "constructor-tearoffs" feature is enabled.
- addProblem(
- templateExperimentNotEnabled.withArguments('constructor-tearoffs',
- libraryBuilder.enableConstructorTearOffsVersionInLibrary.toText()),
- token.charOffset,
- token.length);
+ if (!libraryBuilder.enableConstructorTearOffsInLibrary) {
+ addProblem(
+ templateExperimentNotEnabled.withArguments(
+ 'constructor-tearoffs',
+ libraryBuilder.enableConstructorTearOffsVersionInLibrary
+ .toText()),
+ token.charOffset,
+ token.length);
+ }
}
}
diff --git a/pkg/front_end/lib/src/fasta/source/source_class_builder.dart b/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
index 392acae..395a4d2 100644
--- a/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
@@ -17,6 +17,7 @@
import '../builder/class_builder.dart';
import '../builder/constructor_builder.dart';
import '../builder/constructor_reference_builder.dart';
+import '../builder/factory_builder.dart';
import '../builder/field_builder.dart';
import '../builder/function_builder.dart';
import '../builder/invalid_type_declaration_builder.dart';
@@ -160,8 +161,8 @@
cls.addField(member);
} else if (member is Constructor) {
cls.addConstructor(member);
- } else if (member is RedirectingFactoryConstructor) {
- cls.addRedirectingFactoryConstructor(member);
+ } else if (member is RedirectingFactory) {
+ cls.addRedirectingFactory(member);
} else {
unhandled("${member.runtimeType}", "getMember",
member.fileOffset, member.fileUri);
@@ -528,7 +529,7 @@
// Check procedures
checkVarianceInFunction(
builder.procedure, typeEnvironment, cls.typeParameters);
- library.checkTypesInProcedureBuilder(builder, typeEnvironment);
+ library.checkTypesInFunctionBuilder(builder, typeEnvironment);
} else {
assert(builder is DillFieldBuilder && builder.name == redirectingName,
"Unexpected member: $builder.");
@@ -540,9 +541,9 @@
library.checkTypesInConstructorBuilder(builder, typeEnvironment);
} else if (builder is RedirectingFactoryBuilder) {
library.checkTypesInRedirectingFactoryBuilder(builder, typeEnvironment);
- } else if (builder is ProcedureBuilder) {
+ } else if (builder is SourceFactoryBuilder) {
assert(builder.isFactory, "Unexpected constructor $builder.");
- library.checkTypesInProcedureBuilder(builder, typeEnvironment);
+ library.checkTypesInFunctionBuilder(builder, typeEnvironment);
} else {
assert(
// This is a synthesized constructor.
@@ -828,19 +829,11 @@
new Arguments.forwarded(procedure.function, library.library),
procedure.fileOffset,
/*isSuper=*/ false);
- Expression result;
- if (library
- .loader.target.backendTarget.supportsNewMethodInvocationEncoding) {
- result = new InstanceInvocation(InstanceAccessKind.Instance,
- new ThisExpression(), noSuchMethodName, new Arguments([invocation]),
- functionType: noSuchMethodInterface.getterType as FunctionType,
- interfaceTarget: noSuchMethodInterface)
- ..fileOffset = procedure.fileOffset;
- } else {
- result = new MethodInvocation(new ThisExpression(), noSuchMethodName,
- new Arguments([invocation]), noSuchMethodInterface)
- ..fileOffset = procedure.fileOffset;
- }
+ Expression result = new InstanceInvocation(InstanceAccessKind.Instance,
+ new ThisExpression(), noSuchMethodName, new Arguments([invocation]),
+ functionType: noSuchMethodInterface.getterType as FunctionType,
+ interfaceTarget: noSuchMethodInterface)
+ ..fileOffset = procedure.fileOffset;
if (procedure.function.returnType is! VoidType) {
result = new AsExpression(result, procedure.function.returnType)
..isTypeError = true
@@ -859,7 +852,7 @@
procedure.stubTarget = null;
}
- void _addRedirectingConstructor(ProcedureBuilder constructorBuilder,
+ void _addRedirectingConstructor(SourceFactoryBuilder constructorBuilder,
SourceLibraryBuilder library, Reference? getterReference) {
// Add a new synthetic field to this class for representing factory
// constructors. This is used to support resolving such constructors in
@@ -893,7 +886,7 @@
Field field = constructorsField.field;
ListLiteral literal = field.initializer as ListLiteral;
literal.expressions
- .add(new StaticGet(constructorBuilder.procedure)..parent = literal);
+ .add(new StaticGet(constructorBuilder.member)..parent = literal);
}
@override
diff --git a/pkg/front_end/lib/src/fasta/source/source_extension_builder.dart b/pkg/front_end/lib/src/fasta/source/source_extension_builder.dart
index 9adab49..5ffcb20 100644
--- a/pkg/front_end/lib/src/fasta/source/source_extension_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_extension_builder.dart
@@ -26,6 +26,8 @@
noLength,
templateExtensionMemberConflictsWithObjectMember;
+import '../kernel/kernel_helper.dart';
+
import '../problems.dart';
import '../scope.dart';
@@ -254,7 +256,7 @@
library.checkTypesInField(builder, typeEnvironment);
} else if (builder is ProcedureBuilder) {
// Check procedures
- library.checkTypesInProcedureBuilder(builder, typeEnvironment);
+ library.checkTypesInFunctionBuilder(builder, typeEnvironment);
if (builder.isGetter) {
Builder? setterDeclaration =
scope.lookupLocalMember(builder.name, setter: true);
@@ -273,7 +275,8 @@
void buildOutlineExpressions(
SourceLibraryBuilder library,
CoreTypes coreTypes,
- List<DelayedActionPerformer> delayedActionPerformers) {
+ List<DelayedActionPerformer> delayedActionPerformers,
+ List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
MetadataBuilder.buildAnnotations(isPatch ? origin.extension : extension,
metadata, library, this, null, fileUri);
if (typeParameters != null) {
@@ -285,8 +288,8 @@
void build(String ignore, Builder declaration) {
MemberBuilder member = declaration as MemberBuilder;
- member.buildOutlineExpressions(
- library, coreTypes, delayedActionPerformers);
+ member.buildOutlineExpressions(library, coreTypes,
+ delayedActionPerformers, synthesizedFunctionNodes);
}
scope.forEach(build);
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 b9eed88..324a721 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
@@ -12,9 +12,6 @@
import 'package:_fe_analyzer_shared/src/util/resolve_relative_uri.dart'
show resolveRelativeUri;
-import 'package:front_end/src/fasta/dill/dill_library_builder.dart'
- show DillLibraryBuilder;
-
import 'package:kernel/ast.dart' hide Combinator, MapLiteralEntry;
import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
@@ -47,6 +44,7 @@
import '../builder/dynamic_type_declaration_builder.dart';
import '../builder/enum_builder.dart';
import '../builder/extension_builder.dart';
+import '../builder/factory_builder.dart';
import '../builder/field_builder.dart';
import '../builder/formal_parameter_builder.dart';
import '../builder/function_builder.dart';
@@ -73,6 +71,8 @@
import '../configuration.dart' show Configuration;
+import '../dill/dill_library_builder.dart' show DillLibraryBuilder;
+
import '../export.dart' show Export;
import '../fasta_codes.dart';
@@ -642,6 +642,9 @@
prefix = name as String;
suffix = null;
}
+ if (enableConstructorTearOffsInLibrary) {
+ suffix = suffix == "new" ? "" : suffix;
+ }
if (prefix == className) {
return suffix ?? "";
}
@@ -800,7 +803,7 @@
if (startToken != null) {
// Extract only the tokens for the initializer expression from the
// token stream.
- Token endToken = info.beforeLast;
+ Token endToken = info.beforeLast!;
endToken.setNext(new Token.eof(endToken.next!.offset));
new Token.eof(startToken.previous!.offset).setNext(startToken);
}
@@ -2503,7 +2506,7 @@
procedureName, _currentClassReferencesFromIndexed!.library))
?.reference;
- ProcedureBuilder procedureBuilder;
+ SourceFactoryBuilder procedureBuilder;
if (redirectionTarget != null) {
procedureBuilder = new RedirectingFactoryBuilder(
metadata,
@@ -2525,7 +2528,7 @@
nativeMethodName,
redirectionTarget);
} else {
- procedureBuilder = new SourceProcedureBuilder(
+ procedureBuilder = new SourceFactoryBuilder(
metadata,
staticMask | modifiers,
returnType,
@@ -2535,18 +2538,14 @@
const <TypeVariableBuilder>[],
factoryDeclaration),
formals,
- ProcedureKind.Factory,
this,
startCharOffset,
charOffset,
charOpenParenOffset,
charEndOffset,
reference,
- /* tearOffReference = */ null,
asyncModifier,
procedureNameScheme,
- isExtensionMember: false,
- isInstanceMember: false,
nativeMethodName: nativeMethodName);
}
@@ -3272,7 +3271,7 @@
declaration.constructors.forEach((String name, Builder member) {
List<FormalParameterBuilder>? formals;
- if (member is ProcedureBuilder) {
+ if (member is SourceFactoryBuilder) {
assert(member.isFactory,
"Unexpected constructor member (${member.runtimeType}).");
count += computeDefaultTypesForVariables(member.typeVariables,
@@ -3828,10 +3827,10 @@
}
}
- void checkTypesInProcedureBuilder(
- ProcedureBuilder procedureBuilder, TypeEnvironment typeEnvironment) {
- checkBoundsInFunctionNode(procedureBuilder.procedure.function,
- typeEnvironment, procedureBuilder.fileUri!);
+ void checkTypesInFunctionBuilder(
+ FunctionBuilder procedureBuilder, TypeEnvironment typeEnvironment) {
+ checkBoundsInFunctionNode(
+ procedureBuilder.function, typeEnvironment, procedureBuilder.fileUri!);
if (procedureBuilder.formals != null &&
!(procedureBuilder.isAbstract || procedureBuilder.isExternal)) {
checkInitializersInFormals(procedureBuilder.formals!, typeEnvironment);
@@ -3850,7 +3849,7 @@
void checkTypesInRedirectingFactoryBuilder(
RedirectingFactoryBuilder redirectingFactoryBuilder,
TypeEnvironment typeEnvironment) {
- checkBoundsInFunctionNode(redirectingFactoryBuilder.procedure.function,
+ checkBoundsInFunctionNode(redirectingFactoryBuilder.function,
typeEnvironment, redirectingFactoryBuilder.fileUri);
// Default values are not required on redirecting factory constructors so
// we don't call [checkInitializersInFormals].
@@ -4137,7 +4136,7 @@
if (declaration is FieldBuilder) {
checkTypesInField(declaration, typeEnvironment);
} else if (declaration is ProcedureBuilder) {
- checkTypesInProcedureBuilder(declaration, typeEnvironment);
+ checkTypesInFunctionBuilder(declaration, typeEnvironment);
if (declaration.isGetter) {
Builder? setterDeclaration =
scope.lookupLocalMember(declaration.name, setter: true);
@@ -4235,6 +4234,24 @@
}
uncheckedTypedefTypes.clear();
}
+
+ void installTypedefTearOffs() {
+ Iterator<Builder> iterator = this.iterator;
+ while (iterator.moveNext()) {
+ Builder? declaration = iterator.current;
+ while (declaration != null) {
+ if (declaration is SourceTypeAliasBuilder) {
+ declaration.buildTypedefTearOffs(this, (Procedure procedure) {
+ procedure.isStatic = true;
+ if (!declaration!.isPatch && !declaration.isDuplicate) {
+ library.addProcedure(procedure);
+ }
+ });
+ }
+ declaration = declaration.next;
+ }
+ }
+ }
}
// The kind of type parameter scope built by a [TypeParameterScopeBuilder]
@@ -4505,7 +4522,7 @@
final String name;
final int charOffset;
final Token? initializerToken;
- final Token beforeLast;
+ final Token? beforeLast;
final int charEndOffset;
const FieldInfo(this.name, this.charOffset, this.initializerToken,
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 51b2dd8..538d6cc 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -30,12 +30,14 @@
AsyncMarker,
Class,
Component,
+ Constructor,
DartType,
Expression,
FunctionNode,
InterfaceType,
Library,
LibraryDependency,
+ Member,
NeverType,
Nullability,
Procedure,
@@ -70,6 +72,7 @@
import '../builder/builder.dart';
import '../builder/class_builder.dart';
+import '../builder/constructor_builder.dart';
import '../builder/dynamic_type_declaration_builder.dart';
import '../builder/enum_builder.dart';
import '../builder/extension_builder.dart';
@@ -89,17 +92,14 @@
import '../fasta_codes.dart';
+import '../kernel/body_builder.dart' show BodyBuilder;
import '../kernel/kernel_builder.dart'
show ClassHierarchyBuilder, ClassMember, DelayedCheck;
-
+import '../kernel/kernel_helper.dart'
+ show SynthesizedFunctionNode, TypeDependency;
import '../kernel/kernel_target.dart' show KernelTarget;
-
-import '../kernel/body_builder.dart' show BodyBuilder;
-
import '../kernel/transform_collections.dart' show CollectionTransformer;
-
import '../kernel/transform_set_literals.dart' show SetLiteralTransformer;
-
import '../kernel/type_builder_computer.dart' show TypeBuilderComputer;
import '../loader.dart' show Loader, untranslatableUriScheme;
@@ -109,20 +109,16 @@
import '../source/stack_listener_impl.dart' show offsetForToken;
import '../type_inference/type_inference_engine.dart';
-
import '../type_inference/type_inferrer.dart';
import '../util/helpers.dart';
import 'diet_listener.dart' show DietListener;
-
import 'diet_parser.dart' show DietParser;
-
import 'outline_builder.dart' show OutlineBuilder;
-
import 'source_class_builder.dart' show SourceClassBuilder;
-
import 'source_library_builder.dart' show SourceLibraryBuilder;
+import 'source_type_alias_builder.dart';
class SourceLoader extends Loader {
/// The [FileSystem] which should be used to access files.
@@ -366,6 +362,15 @@
hasInvalidNnbdModeLibrary = true;
}
+ void registerConstructorToBeInferred(
+ Constructor constructor, ConstructorBuilder builder) {
+ _typeInferenceEngine!.toBeInferred[constructor] = builder;
+ }
+
+ void registerTypeDependency(Member member, TypeDependency typeDependency) {
+ _typeInferenceEngine!.typeDependencies[member] = typeDependency;
+ }
+
@override
Future<Null> buildOutlines() async {
await super.buildOutlines();
@@ -718,6 +723,16 @@
ticker.logMs("Resolved $count constructors");
}
+ void installTypedefTearOffs() {
+ if (target.backendTarget.isTypedefTearOffLoweringEnabled) {
+ for (LibraryBuilder library in builders.values) {
+ if (library.loader == this && library is SourceLibraryBuilder) {
+ library.installTypedefTearOffs();
+ }
+ }
+ }
+ }
+
void finishTypeVariables(ClassBuilder object, TypeBuilder dynamicType) {
int count = 0;
for (LibraryBuilder library in builders.values) {
@@ -1182,7 +1197,8 @@
ticker.logMs("Checked mixin declaration applications");
}
- void buildOutlineExpressions(CoreTypes coreTypes) {
+ void buildOutlineExpressions(CoreTypes coreTypes,
+ List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
List<DelayedActionPerformer> delayedActionPerformers =
<DelayedActionPerformer>[];
for (LibraryBuilder library in builders.values) {
@@ -1192,17 +1208,17 @@
while (iterator.moveNext()) {
Builder declaration = iterator.current;
if (declaration is ClassBuilder) {
- declaration.buildOutlineExpressions(
- library, coreTypes, delayedActionPerformers);
+ declaration.buildOutlineExpressions(library, coreTypes,
+ delayedActionPerformers, synthesizedFunctionNodes);
} else if (declaration is ExtensionBuilder) {
- declaration.buildOutlineExpressions(
- library, coreTypes, delayedActionPerformers);
+ declaration.buildOutlineExpressions(library, coreTypes,
+ delayedActionPerformers, synthesizedFunctionNodes);
} else if (declaration is MemberBuilder) {
- declaration.buildOutlineExpressions(
- library, coreTypes, delayedActionPerformers);
- } else if (declaration is TypeAliasBuilder) {
- declaration.buildOutlineExpressions(
- library, coreTypes, delayedActionPerformers);
+ declaration.buildOutlineExpressions(library, coreTypes,
+ delayedActionPerformers, synthesizedFunctionNodes);
+ } else if (declaration is SourceTypeAliasBuilder) {
+ declaration.buildOutlineExpressions(library, coreTypes,
+ delayedActionPerformers, synthesizedFunctionNodes);
} else {
assert(
declaration is PrefixBuilder ||
diff --git a/pkg/front_end/lib/src/fasta/source/source_type_alias_builder.dart b/pkg/front_end/lib/src/fasta/source/source_type_alias_builder.dart
index ae4fbb9..60e717f 100644
--- a/pkg/front_end/lib/src/fasta/source/source_type_alias_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_type_alias_builder.dart
@@ -4,17 +4,8 @@
library fasta.source_type_alias_builder;
-import 'package:kernel/ast.dart'
- show
- DartType,
- DynamicType,
- InvalidType,
- TypeParameter,
- TypeParameterType,
- Typedef,
- TypedefType,
- VariableDeclaration,
- getAsTypeArguments;
+import 'package:front_end/src/fasta/kernel/expression_generator_helper.dart';
+import 'package:kernel/ast.dart';
import 'package:kernel/core_types.dart';
@@ -33,6 +24,7 @@
import '../builder/formal_parameter_builder.dart';
import '../builder/function_type_builder.dart';
import '../builder/library_builder.dart';
+import '../builder/member_builder.dart';
import '../builder/metadata_builder.dart';
import '../builder/named_type_builder.dart';
import '../builder/type_builder.dart';
@@ -40,6 +32,9 @@
import '../builder/type_declaration_builder.dart';
import '../builder/type_variable_builder.dart';
+import '../kernel/constructor_tearoff_lowering.dart';
+import '../kernel/kernel_helper.dart';
+
import '../util/helpers.dart';
import 'source_library_builder.dart' show SourceLibraryBuilder;
@@ -54,6 +49,8 @@
DartType? thisType;
+ Map<Name, Procedure>? tearOffs;
+
SourceTypeAliasBuilder(
List<MetadataBuilder>? metadata,
String name,
@@ -253,11 +250,11 @@
allowSuperBounded: false);
}
- @override
void buildOutlineExpressions(
SourceLibraryBuilder library,
CoreTypes coreTypes,
- List<DelayedActionPerformer> delayedActionPerformers) {
+ List<DelayedActionPerformer> delayedActionPerformers,
+ List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
MetadataBuilder.buildAnnotations(
typedef, metadata, library, null, null, fileUri);
if (typeVariables != null) {
@@ -266,5 +263,45 @@
library, null, null, coreTypes, delayedActionPerformers);
}
}
+ _tearOffDependencies?.forEach((Procedure tearOff, Member target) {
+ InterfaceType targetType = typedef.type as InterfaceType;
+ synthesizedFunctionNodes.add(new SynthesizedFunctionNode(
+ new Map<TypeParameter, DartType>.fromIterables(
+ target.enclosingClass!.typeParameters, targetType.typeArguments),
+ target.function!,
+ tearOff.function));
+ });
+ }
+
+ Map<Procedure, Member>? _tearOffDependencies;
+
+ void buildTypedefTearOffs(
+ SourceLibraryBuilder library, void Function(Procedure) f) {
+ TypeDeclarationBuilder? declaration = unaliasDeclaration(null);
+ if (declaration is ClassBuilder &&
+ typedef.typeParameters.isNotEmpty &&
+ !isProperRenameForClass(library.loader.typeEnvironment, typedef)) {
+ tearOffs = {};
+ _tearOffDependencies = {};
+ declaration
+ .forEachConstructor((String constructorName, MemberBuilder builder) {
+ Member? target = builder.invokeTarget;
+ if (target != null) {
+ if (target is Procedure && target.isRedirectingFactory) {
+ target = builder.readTarget!;
+ }
+ Name targetName =
+ new Name(constructorName, declaration.library.library);
+ Procedure tearOff = tearOffs![targetName] =
+ createTypedefTearOffProcedure(
+ name, constructorName, library, fileUri, charOffset);
+ _tearOffDependencies![tearOff] = target;
+ InterfaceType targetType = typedef.type as InterfaceType;
+ buildTypedefTearOffProcedure(tearOff, target, declaration.cls,
+ typedef.typeParameters, targetType.typeArguments, library);
+ f(tearOff);
+ }
+ });
+ }
}
}
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart
index 407fbfb..5ba0cfa 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart
@@ -3,7 +3,6 @@
// BSD-style license that can be found in the LICENSE.md file.
import 'package:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart';
-import 'package:front_end/src/fasta/kernel/internal_ast.dart';
import 'package:kernel/ast.dart';
@@ -18,9 +17,10 @@
import '../builder/constructor_builder.dart';
import '../kernel/forest.dart';
-
+import '../kernel/internal_ast.dart';
import '../kernel/kernel_builder.dart'
show ClassHierarchyBuilder, ImplicitFieldType;
+import '../kernel/kernel_helper.dart';
import '../source/source_library_builder.dart' show SourceLibraryBuilder;
@@ -128,6 +128,8 @@
/// is used to report errors.
final Map<Constructor, ConstructorBuilder> beingInferred = {};
+ final Map<Member, TypeDependency> typeDependencies = {};
+
final Instrumentation? instrumentation;
TypeInferenceEngine(this.instrumentation);
@@ -152,6 +154,10 @@
builder.inferFormalTypes();
}
toBeInferred.clear();
+ for (TypeDependency typeDependency in typeDependencies.values) {
+ typeDependency.copyInferred();
+ }
+ typeDependencies.clear();
}
/// Gets ready to do top level type inference for the component having the
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
index fe7c2c6..2bf3ff0 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
@@ -37,6 +37,7 @@
import '../fasta_codes.dart';
import '../kernel/class_hierarchy_builder.dart' show ClassMember;
+import '../kernel/kernel_helper.dart';
import '../kernel/inference_visitor.dart';
import '../kernel/internal_ast.dart';
import '../kernel/invalid_type.dart';
@@ -226,7 +227,7 @@
assignedVariables)
: new FlowAnalysis.legacy(
new TypeOperationsCfe(engine.typeSchemaEnvironment),
- assignedVariables);
+ assignedVariables) {}
CoreTypes get coreTypes => engine.coreTypes;
@@ -234,9 +235,6 @@
NnbdMode get nnbdMode => library.loader.nnbdMode;
- bool get useNewMethodInvocationEncoding =>
- library.loader.target.backendTarget.supportsNewMethodInvocationEncoding;
-
DartType get bottomType =>
isNonNullableByDefault ? const NeverType.nonNullable() : const NullType();
@@ -357,6 +355,19 @@
}
}
+ /// Ensures that the type of [member] has been computed.
+ // TODO(johnniwinther): Expand this to handle lowerings.
+ void ensureMemberType(Member member) {
+ if (member is Constructor) {
+ inferConstructorParameterTypes(member);
+ }
+ TypeDependency? typeDependency = engine.typeDependencies.remove(member);
+ if (typeDependency != null) {
+ ensureMemberType(typeDependency.original);
+ typeDependency.copyInferred();
+ }
+ }
+
@override
void inferConstructorParameterTypes(Constructor target) {
ConstructorBuilder? constructor = engine.beingInferred[target];
@@ -746,32 +757,19 @@
VariableDeclaration t =
new VariableDeclaration.forValue(expression, type: expressionType)
..fileOffset = fileOffset;
- Expression nullCheck;
+
// TODO(johnniwinther): Avoid null-check for non-nullable expressions.
- if (useNewMethodInvocationEncoding) {
- nullCheck = new EqualsNull(new VariableGet(t)..fileOffset = fileOffset)
- ..fileOffset = fileOffset;
- } else {
- nullCheck = new MethodInvocation(
- new VariableGet(t)..fileOffset = fileOffset,
- equalsName,
- new Arguments(
- <Expression>[new NullLiteral()..fileOffset = fileOffset]))
- ..fileOffset = fileOffset;
- }
- Expression tearOff;
+ Expression nullCheck =
+ new EqualsNull(new VariableGet(t)..fileOffset = fileOffset)
+ ..fileOffset = fileOffset;
+
DartType tearoffType =
getGetterTypeForMemberTarget(callMember, expressionType)
.withDeclaredNullability(expressionType.nullability);
- if (useNewMethodInvocationEncoding) {
- tearOff = new InstanceTearOff(
- InstanceAccessKind.Instance, new VariableGet(t), callName,
- interfaceTarget: callMember as Procedure, resultType: tearoffType)
- ..fileOffset = fileOffset;
- } else {
- tearOff = new PropertyGet(new VariableGet(t), callName, callMember)
- ..fileOffset = fileOffset;
- }
+ Expression tearOff = new InstanceTearOff(
+ InstanceAccessKind.Instance, new VariableGet(t), callName,
+ interfaceTarget: callMember as Procedure, resultType: tearoffType)
+ ..fileOffset = fileOffset;
ConditionalExpression conditional = new ConditionalExpression(nullCheck,
new NullLiteral()..fileOffset = fileOffset, tearOff, tearoffType);
return new TypedTearoff(
@@ -2754,15 +2752,9 @@
receiverType: const DynamicType(),
isImplicitCall: isImplicitCall);
assert(name != equalsName);
- Expression expression;
- if (useNewMethodInvocationEncoding) {
- expression = new DynamicInvocation(
- DynamicAccessKind.Dynamic, receiver, name, arguments)
- ..fileOffset = fileOffset;
- } else {
- expression = new MethodInvocation(receiver, name, arguments)
- ..fileOffset = fileOffset;
- }
+ Expression expression = new DynamicInvocation(
+ DynamicAccessKind.Dynamic, receiver, name, arguments)
+ ..fileOffset = fileOffset;
return createNullAwareExpressionInferenceResult(
result.inferredType, result.applyResult(expression), nullAwareGuards);
}
@@ -2785,15 +2777,9 @@
receiverType: receiverType,
isImplicitCall: isImplicitCall);
assert(name != equalsName);
- Expression expression;
- if (useNewMethodInvocationEncoding) {
- expression = new DynamicInvocation(
- DynamicAccessKind.Never, receiver, name, arguments)
- ..fileOffset = fileOffset;
- } else {
- expression = new MethodInvocation(receiver, name, arguments)
- ..fileOffset = fileOffset;
- }
+ Expression expression = new DynamicInvocation(
+ DynamicAccessKind.Never, receiver, name, arguments)
+ ..fileOffset = fileOffset;
return createNullAwareExpressionInferenceResult(
const NeverType.nonNullable(),
result.applyResult(expression),
@@ -2971,52 +2957,39 @@
isImplicitCall: isImplicitCall);
Expression? expression;
String? localName;
- if (useNewMethodInvocationEncoding) {
- DartType inferredFunctionType = result.functionType;
- if (result.isInapplicable) {
- // This was a function invocation whose arguments didn't match
- // the parameters.
- expression = new FunctionInvocation(
- FunctionAccessKind.Inapplicable, receiver, arguments,
- functionType: null)
- ..fileOffset = fileOffset;
- } else if (receiver is VariableGet) {
- VariableDeclaration variable = receiver.variable;
- TreeNode? parent = variable.parent;
- if (parent is FunctionDeclaration) {
- assert(!identical(inferredFunctionType, unknownFunction),
- "Unknown function type for local function invocation.");
- localName = variable.name!;
- expression = new LocalFunctionInvocation(variable, arguments,
- functionType: inferredFunctionType as FunctionType)
- ..fileOffset = receiver.fileOffset;
- }
- }
- expression ??= new FunctionInvocation(
- target.isNullableCallFunction
- ? FunctionAccessKind.Nullable
- : (identical(inferredFunctionType, unknownFunction)
- ? FunctionAccessKind.Function
- : FunctionAccessKind.FunctionType),
- receiver,
- arguments,
- functionType: identical(inferredFunctionType, unknownFunction)
- ? null
- : inferredFunctionType as FunctionType)
+
+ DartType inferredFunctionType = result.functionType;
+ if (result.isInapplicable) {
+ // This was a function invocation whose arguments didn't match
+ // the parameters.
+ expression = new FunctionInvocation(
+ FunctionAccessKind.Inapplicable, receiver, arguments,
+ functionType: null)
..fileOffset = fileOffset;
- } else {
- if (receiver is VariableGet) {
- VariableDeclaration variable = receiver.variable;
- TreeNode? parent = variable.parent;
- if (parent is FunctionDeclaration) {
- // This is a local function invocation. Use the name in bounds
- // checking below.
- localName = variable.name!;
- }
+ } else if (receiver is VariableGet) {
+ VariableDeclaration variable = receiver.variable;
+ TreeNode? parent = variable.parent;
+ if (parent is FunctionDeclaration) {
+ assert(!identical(inferredFunctionType, unknownFunction),
+ "Unknown function type for local function invocation.");
+ localName = variable.name!;
+ expression = new LocalFunctionInvocation(variable, arguments,
+ functionType: inferredFunctionType as FunctionType)
+ ..fileOffset = receiver.fileOffset;
}
- expression = new MethodInvocation(receiver, callName, arguments)
- ..fileOffset = fileOffset;
}
+ expression ??= new FunctionInvocation(
+ target.isNullableCallFunction
+ ? FunctionAccessKind.Nullable
+ : (identical(inferredFunctionType, unknownFunction)
+ ? FunctionAccessKind.Function
+ : FunctionAccessKind.FunctionType),
+ receiver,
+ arguments,
+ functionType: identical(inferredFunctionType, unknownFunction)
+ ? null
+ : inferredFunctionType as FunctionType)
+ ..fileOffset = fileOffset;
_checkBoundsInFunctionInvocation(
declaredFunctionType, localName, arguments, fileOffset);
@@ -3131,51 +3104,45 @@
isSpecialCasedTernaryOperator: isSpecialCasedTernaryOperator);
Expression expression;
- if (useNewMethodInvocationEncoding) {
- DartType inferredFunctionType = result.functionType;
- if (target.isDynamic) {
- // This was an Object member invocation whose arguments didn't match
- // the parameters.
- expression = new DynamicInvocation(
- DynamicAccessKind.Dynamic, receiver, methodName, arguments)
- ..fileOffset = fileOffset;
- } else if (result.isInapplicable) {
- // This was a method invocation whose arguments didn't match
- // the parameters.
- expression = new InstanceInvocation(
- InstanceAccessKind.Inapplicable, receiver, methodName, arguments,
- functionType: _computeFunctionTypeForArguments(
- arguments, const InvalidType()),
- interfaceTarget: method!)
- ..fileOffset = fileOffset;
- } else {
- assert(
- inferredFunctionType is FunctionType &&
- !identical(unknownFunction, inferredFunctionType),
- "No function type found for $receiver.$methodName ($target) on "
- "$receiverType");
- InstanceAccessKind kind;
- switch (target.kind) {
- case ObjectAccessTargetKind.instanceMember:
- kind = InstanceAccessKind.Instance;
- break;
- case ObjectAccessTargetKind.nullableInstanceMember:
- kind = InstanceAccessKind.Nullable;
- break;
- case ObjectAccessTargetKind.objectMember:
- kind = InstanceAccessKind.Object;
- break;
- default:
- throw new UnsupportedError('Unexpected target kind $target');
- }
- expression = new InstanceInvocation(
- kind, receiver, methodName, arguments,
- functionType: inferredFunctionType as FunctionType,
- interfaceTarget: method!)
- ..fileOffset = fileOffset;
- }
+ DartType inferredFunctionType = result.functionType;
+ if (target.isDynamic) {
+ // This was an Object member invocation whose arguments didn't match
+ // the parameters.
+ expression = new DynamicInvocation(
+ DynamicAccessKind.Dynamic, receiver, methodName, arguments)
+ ..fileOffset = fileOffset;
+ } else if (result.isInapplicable) {
+ // This was a method invocation whose arguments didn't match
+ // the parameters.
+ expression = new InstanceInvocation(
+ InstanceAccessKind.Inapplicable, receiver, methodName, arguments,
+ functionType:
+ _computeFunctionTypeForArguments(arguments, const InvalidType()),
+ interfaceTarget: method!)
+ ..fileOffset = fileOffset;
} else {
- expression = new MethodInvocation(receiver, methodName, arguments, method)
+ assert(
+ inferredFunctionType is FunctionType &&
+ !identical(unknownFunction, inferredFunctionType),
+ "No function type found for $receiver.$methodName ($target) on "
+ "$receiverType");
+ InstanceAccessKind kind;
+ switch (target.kind) {
+ case ObjectAccessTargetKind.instanceMember:
+ kind = InstanceAccessKind.Instance;
+ break;
+ case ObjectAccessTargetKind.nullableInstanceMember:
+ kind = InstanceAccessKind.Nullable;
+ break;
+ case ObjectAccessTargetKind.objectMember:
+ kind = InstanceAccessKind.Object;
+ break;
+ default:
+ throw new UnsupportedError('Unexpected target kind $target');
+ }
+ expression = new InstanceInvocation(kind, receiver, methodName, arguments,
+ functionType: inferredFunctionType as FunctionType,
+ interfaceTarget: method!)
..fileOffset = fileOffset;
}
Expression replacement;
@@ -3293,30 +3260,24 @@
Name originalName = getter!.name;
Expression originalReceiver = receiver;
Member originalTarget = getter;
- Expression originalPropertyGet;
- if (useNewMethodInvocationEncoding) {
- InstanceAccessKind kind;
- switch (target.kind) {
- case ObjectAccessTargetKind.instanceMember:
- kind = InstanceAccessKind.Instance;
- break;
- case ObjectAccessTargetKind.nullableInstanceMember:
- kind = InstanceAccessKind.Nullable;
- break;
- case ObjectAccessTargetKind.objectMember:
- kind = InstanceAccessKind.Object;
- break;
- default:
- throw new UnsupportedError('Unexpected target kind $target');
- }
- originalPropertyGet = new InstanceGet(
- kind, originalReceiver, originalName,
- resultType: calleeType, interfaceTarget: originalTarget)
- ..fileOffset = fileOffset;
- } else {
- originalPropertyGet = new PropertyGet(receiver, getter.name, getter)
- ..fileOffset = fileOffset;
+ InstanceAccessKind kind;
+ switch (target.kind) {
+ case ObjectAccessTargetKind.instanceMember:
+ kind = InstanceAccessKind.Instance;
+ break;
+ case ObjectAccessTargetKind.nullableInstanceMember:
+ kind = InstanceAccessKind.Nullable;
+ break;
+ case ObjectAccessTargetKind.objectMember:
+ kind = InstanceAccessKind.Object;
+ break;
+ default:
+ throw new UnsupportedError('Unexpected target kind $target');
}
+ InstanceGet originalPropertyGet = new InstanceGet(
+ kind, originalReceiver, originalName,
+ resultType: calleeType, interfaceTarget: originalTarget)
+ ..fileOffset = fileOffset;
Expression propertyGet = originalPropertyGet;
if (calleeType is! DynamicType &&
receiver is! ThisExpression &&
@@ -3381,45 +3342,29 @@
// TODO(johnniwinther): Remove this when dart2js/ddc supports explicit
// getter calls.
Expression nullAwareAction = invocationResult.nullAwareAction;
- if (nullAwareAction is MethodInvocation &&
+ if (nullAwareAction is InstanceInvocation &&
nullAwareAction.receiver == originalPropertyGet) {
invocationResult = new ExpressionInferenceResult(
invocationResult.inferredType,
- new MethodInvocation(originalReceiver, originalName,
- nullAwareAction.arguments, originalTarget)
- ..fileOffset = nullAwareAction.fileOffset);
- } else if (nullAwareAction is InstanceInvocation &&
- nullAwareAction.receiver == originalPropertyGet) {
- // TODO(johnniwinther): Remove this when [MethodInvocation] is no longer
- // used and [originalPropertyGet] can be an [InstanceGet].
- InstanceGet instanceGet = originalPropertyGet as InstanceGet;
- invocationResult = new ExpressionInferenceResult(
- invocationResult.inferredType,
- new InstanceGetterInvocation(instanceGet.kind, originalReceiver,
- originalName, nullAwareAction.arguments,
+ new InstanceGetterInvocation(originalPropertyGet.kind,
+ originalReceiver, originalName, nullAwareAction.arguments,
interfaceTarget: originalTarget,
functionType: nullAwareAction.functionType)
..fileOffset = nullAwareAction.fileOffset);
} else if (nullAwareAction is DynamicInvocation &&
nullAwareAction.receiver == originalPropertyGet) {
- // TODO(johnniwinther): Remove this when [MethodInvocation] is no longer
- // used and [originalPropertyGet] can be an [InstanceGet].
- InstanceGet instanceGet = originalPropertyGet as InstanceGet;
invocationResult = new ExpressionInferenceResult(
invocationResult.inferredType,
- new InstanceGetterInvocation(instanceGet.kind, originalReceiver,
- originalName, nullAwareAction.arguments,
+ new InstanceGetterInvocation(originalPropertyGet.kind,
+ originalReceiver, originalName, nullAwareAction.arguments,
interfaceTarget: originalTarget, functionType: null)
..fileOffset = nullAwareAction.fileOffset);
} else if (nullAwareAction is FunctionInvocation &&
nullAwareAction.receiver == originalPropertyGet) {
- // TODO(johnniwinther): Remove this when [MethodInvocation] is no longer
- // used and [originalPropertyGet] can be an [InstanceGet].
- InstanceGet instanceGet = originalPropertyGet as InstanceGet;
invocationResult = new ExpressionInferenceResult(
invocationResult.inferredType,
- new InstanceGetterInvocation(instanceGet.kind, originalReceiver,
- originalName, nullAwareAction.arguments,
+ new InstanceGetterInvocation(originalPropertyGet.kind,
+ originalReceiver, originalName, nullAwareAction.arguments,
interfaceTarget: originalTarget,
functionType: nullAwareAction.functionType)
..fileOffset = nullAwareAction.fileOffset);
@@ -3497,31 +3442,24 @@
Name originalName = field.name;
Expression originalReceiver = receiver;
Member originalTarget = field;
- Expression originalPropertyGet;
- if (useNewMethodInvocationEncoding) {
- InstanceAccessKind kind;
- switch (target.kind) {
- case ObjectAccessTargetKind.instanceMember:
- kind = InstanceAccessKind.Instance;
- break;
- case ObjectAccessTargetKind.nullableInstanceMember:
- kind = InstanceAccessKind.Nullable;
- break;
- case ObjectAccessTargetKind.objectMember:
- kind = InstanceAccessKind.Object;
- break;
- default:
- throw new UnsupportedError('Unexpected target kind $target');
- }
- originalPropertyGet = new InstanceGet(
- kind, originalReceiver, originalName,
- resultType: calleeType, interfaceTarget: originalTarget)
- ..fileOffset = fileOffset;
- } else {
- originalPropertyGet =
- new PropertyGet(originalReceiver, originalName, originalTarget)
- ..fileOffset = fileOffset;
+ InstanceAccessKind kind;
+ switch (target.kind) {
+ case ObjectAccessTargetKind.instanceMember:
+ kind = InstanceAccessKind.Instance;
+ break;
+ case ObjectAccessTargetKind.nullableInstanceMember:
+ kind = InstanceAccessKind.Nullable;
+ break;
+ case ObjectAccessTargetKind.objectMember:
+ kind = InstanceAccessKind.Object;
+ break;
+ default:
+ throw new UnsupportedError('Unexpected target kind $target');
}
+ InstanceGet originalPropertyGet = new InstanceGet(
+ kind, originalReceiver, originalName,
+ resultType: calleeType, interfaceTarget: originalTarget)
+ ..fileOffset = fileOffset;
flowAnalysis.propertyGet(originalPropertyGet, originalReceiver,
originalName.text, originalTarget, calleeType);
Expression propertyGet = originalPropertyGet;
@@ -3592,45 +3530,29 @@
// TODO(johnniwinther): Remove this when dart2js/ddc supports explicit
// getter calls.
Expression nullAwareAction = invocationResult.nullAwareAction;
- if (nullAwareAction is MethodInvocation &&
+ if (nullAwareAction is InstanceInvocation &&
nullAwareAction.receiver == originalPropertyGet) {
invocationResult = new ExpressionInferenceResult(
invocationResult.inferredType,
- new MethodInvocation(originalReceiver, originalName,
- nullAwareAction.arguments, originalTarget)
- ..fileOffset = nullAwareAction.fileOffset);
- } else if (nullAwareAction is InstanceInvocation &&
- nullAwareAction.receiver == originalPropertyGet) {
- // TODO(johnniwinther): Remove this when [MethodInvocation] is no longer
- // used and [originalPropertyGet] can be an [InstanceGet].
- InstanceGet instanceGet = originalPropertyGet as InstanceGet;
- invocationResult = new ExpressionInferenceResult(
- invocationResult.inferredType,
- new InstanceGetterInvocation(instanceGet.kind, originalReceiver,
- originalName, nullAwareAction.arguments,
+ new InstanceGetterInvocation(originalPropertyGet.kind,
+ originalReceiver, originalName, nullAwareAction.arguments,
interfaceTarget: originalTarget,
functionType: nullAwareAction.functionType)
..fileOffset = nullAwareAction.fileOffset);
} else if (nullAwareAction is DynamicInvocation &&
nullAwareAction.receiver == originalPropertyGet) {
- // TODO(johnniwinther): Remove this when [MethodInvocation] is no longer
- // used and [originalPropertyGet] can be an [InstanceGet].
- InstanceGet instanceGet = originalPropertyGet as InstanceGet;
invocationResult = new ExpressionInferenceResult(
invocationResult.inferredType,
- new InstanceGetterInvocation(instanceGet.kind, originalReceiver,
- originalName, nullAwareAction.arguments,
+ new InstanceGetterInvocation(originalPropertyGet.kind,
+ originalReceiver, originalName, nullAwareAction.arguments,
interfaceTarget: originalTarget, functionType: null)
..fileOffset = nullAwareAction.fileOffset);
} else if (nullAwareAction is FunctionInvocation &&
nullAwareAction.receiver == originalPropertyGet) {
- // TODO(johnniwinther): Remove this when [MethodInvocation] is no longer
- // used and [originalPropertyGet] can be an [InstanceGet].
- InstanceGet instanceGet = originalPropertyGet as InstanceGet;
invocationResult = new ExpressionInferenceResult(
invocationResult.inferredType,
- new InstanceGetterInvocation(instanceGet.kind, originalReceiver,
- originalName, nullAwareAction.arguments,
+ new InstanceGetterInvocation(originalPropertyGet.kind,
+ originalReceiver, originalName, nullAwareAction.arguments,
interfaceTarget: originalTarget,
functionType: nullAwareAction.functionType)
..fileOffset = nullAwareAction.fileOffset);
@@ -4472,18 +4394,7 @@
/// the interface target of the created method invocation.
Expression createEqualsNull(
int fileOffset, Expression left, Member equalsMember) {
- if (useNewMethodInvocationEncoding) {
- return new EqualsNull(left)..fileOffset = fileOffset;
- } else {
- return new MethodInvocation(
- left,
- equalsName,
- new Arguments(
- <Expression>[new NullLiteral()..fileOffset = fileOffset])
- ..fileOffset = fileOffset)
- ..fileOffset = fileOffset
- ..interfaceTarget = equalsMember;
- }
+ return new EqualsNull(left)..fileOffset = fileOffset;
}
}
diff --git a/pkg/front_end/lib/src/testing/id_extractor.dart b/pkg/front_end/lib/src/testing/id_extractor.dart
index 50cf52f..13229aa 100644
--- a/pkg/front_end/lib/src/testing/id_extractor.dart
+++ b/pkg/front_end/lib/src/testing/id_extractor.dart
@@ -208,24 +208,6 @@
}
@override
- visitMethodInvocation(MethodInvocation node) {
- TreeNode receiver = node.receiver;
- if (receiver is VariableGet &&
- receiver.variable.parent is FunctionDeclaration) {
- // This is an invocation of a named local function.
- computeForNode(node, createInvokeId(node.receiver));
- node.arguments.accept(this);
- } else if (node.name.text == '==' &&
- receiver is VariableGet &&
- receiver.variable.name == null) {
- // This is a desugared `?.`.
- } else {
- _visitInvocation(node, node.name);
- super.visitMethodInvocation(node);
- }
- }
-
- @override
visitDynamicInvocation(DynamicInvocation node) {
_visitInvocation(node, node.name);
super.visitDynamicInvocation(node);
@@ -278,12 +260,6 @@
}
@override
- visitPropertyGet(PropertyGet node) {
- computeForNode(node, computeDefaultNodeId(node));
- super.visitPropertyGet(node);
- }
-
- @override
visitDynamicGet(DynamicGet node) {
computeForNode(node, computeDefaultNodeId(node));
super.visitDynamicGet(node);
@@ -344,12 +320,6 @@
}
@override
- visitPropertySet(PropertySet node) {
- computeForNode(node, createUpdateId(node));
- super.visitPropertySet(node);
- }
-
- @override
visitDynamicSet(DynamicSet node) {
computeForNode(node, createUpdateId(node));
super.visitDynamicSet(node);
@@ -529,11 +499,8 @@
visitThisExpression(ThisExpression node) {
TreeNode parent = node.parent!;
if (node.fileOffset == TreeNode.noOffset ||
- (parent is PropertyGet ||
- parent is InstanceGet ||
- parent is PropertySet ||
+ (parent is InstanceGet ||
parent is InstanceSet ||
- parent is MethodInvocation ||
parent is InstanceInvocation) &&
parent.fileOffset == node.fileOffset) {
// Skip implicit this expressions.
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 fafad3a..0067517 100644
--- a/pkg/front_end/lib/src/testing/id_testing_utils.dart
+++ b/pkg/front_end/lib/src/testing/id_testing_utils.dart
@@ -415,7 +415,12 @@
void visitInstantiationConstant(InstantiationConstant node) {
sb.write('Instantiation(');
- sb.write(getMemberName(node.tearOffConstant.member));
+ Constant tearOffConstant = node.tearOffConstant;
+ if (tearOffConstant is TearOffConstant) {
+ sb.write(getMemberName(tearOffConstant.target));
+ } else {
+ visit(tearOffConstant);
+ }
sb.write('<');
typeToText.visitList(node.types);
sb.write('>)');
@@ -423,7 +428,7 @@
void visitTypedefTearOffConstant(TypedefTearOffConstant node) {
sb.write('TypedefTearOff(');
- sb.write(getMemberName(node.tearOffConstant.member));
+ sb.write(getMemberName(node.tearOffConstant.target));
if (node.parameters.isNotEmpty) {
sb.write('<');
for (int i = 0; i < node.parameters.length; i++) {
@@ -451,13 +456,20 @@
void visitStaticTearOffConstant(StaticTearOffConstant node) {
sb.write('Function(');
- sb.write(getMemberName(node.procedure));
+ sb.write(getMemberName(node.target));
sb.write(')');
}
void visitConstructorTearOffConstant(ConstructorTearOffConstant node) {
sb.write('Constructor(');
- sb.write(getMemberName(node.constructor));
+ sb.write(getMemberName(node.target));
+ sb.write(')');
+ }
+
+ void visitRedirectingFactoryTearOffConstant(
+ RedirectingFactoryTearOffConstant node) {
+ sb.write('RedirectingFactory(');
+ sb.write(getMemberName(node.target));
sb.write(')');
}
diff --git a/pkg/front_end/messages.status b/pkg/front_end/messages.status
index f6e79b9a..8eb1f8d 100644
--- a/pkg/front_end/messages.status
+++ b/pkg/front_end/messages.status
@@ -103,6 +103,10 @@
ConstEvalDuplicateKey/example: Fail
ConstEvalElementImplementsEqual/example: Fail
ConstEvalExtension/example: Fail
+ConstEvalExternalConstructor/analyzerCode: Fail
+ConstEvalExternalConstructor/example: Fail
+ConstEvalExternalFactory/analyzerCode: Fail
+ConstEvalExternalFactory/example: Fail
ConstEvalFailedAssertion/example: Fail
ConstEvalFailedAssertionWithMessage/example: Fail
ConstEvalFreeTypeParameter/analyzerCode: Fail
@@ -340,6 +344,7 @@
FfiFieldNull/analyzerCode: Fail
FfiLeafCallMustNotReturnHandle/analyzerCode: Fail
FfiLeafCallMustNotTakeHandle/analyzerCode: Fail
+FfiNativeAnnotationMustAnnotateStatic/analyzerCode: Fail
FfiNotStatic/analyzerCode: Fail
FfiPackedAnnotation/analyzerCode: Fail
FfiPackedAnnotationAlignment/analyzerCode: Fail
@@ -509,6 +514,8 @@
JsInteropDartClassExtendsJSClass/example: Fail # Web compiler specific
JsInteropEnclosingClassJSAnnotation/analyzerCode: Fail # Web compiler specific
JsInteropEnclosingClassJSAnnotation/example: Fail # Web compiler specific
+JsInteropExternalExtensionMemberOnTypeInvalid/analyzerCode: Fail # Web compiler specific
+JsInteropExternalExtensionMemberOnTypeInvalid/example: Fail # Web compiler specific
JsInteropExternalMemberNotJSAnnotated/analyzerCode: Fail # Web compiler specific
JsInteropExternalMemberNotJSAnnotated/example: Fail # Web compiler specific
JsInteropIndexNotSupported/analyzerCode: Fail # Web compiler specific
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index 84ed8c2..e94eac1 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -219,6 +219,12 @@
template: "Extension operations can't be used in constant expressions."
analyzerCode: NOT_CONSTANT_EXPRESSION
+ConstEvalExternalConstructor:
+ template: "External constructors can't be evaluated in constant expressions."
+
+ConstEvalExternalFactory:
+ template: "External factory constructors can't be evaluated in constant expressions."
+
ConstEvalUnevaluated:
template: "Couldn't evaluate constant expression."
@@ -4537,6 +4543,11 @@
template: "FFI leaf call must not have Handle return type."
external: test/ffi_test.dart
+FfiNativeAnnotationMustAnnotateStatic:
+ # Used by dart:ffi
+ template: "FfiNative annotations can only be used on static functions."
+ external: test/ffi_test.dart
+
SpreadTypeMismatch:
template: "Unexpected type '#type' of a spread. Expected 'dynamic' or an Iterable."
script:
@@ -4903,6 +4914,10 @@
template: "This is the enclosing class."
severity: CONTEXT
+JsInteropExternalExtensionMemberOnTypeInvalid:
+ template: "JS interop or Native class required for 'external' extension members."
+ tip: "Try adding a JS interop annotation to the on type class of the extension."
+
JsInteropExternalMemberNotJSAnnotated:
template: "Only JS interop members may be 'external'."
tip: "Try removing the 'external' keyword or adding a JS interop annotation."
diff --git a/pkg/front_end/test/comments_on_certain_arguments_tool.dart b/pkg/front_end/test/comments_on_certain_arguments_tool.dart
index 56ddf2e..4ad6562 100644
--- a/pkg/front_end/test/comments_on_certain_arguments_tool.dart
+++ b/pkg/front_end/test/comments_on_certain_arguments_tool.dart
@@ -181,13 +181,6 @@
super.visitProcedure(node);
}
- void visitMethodInvocation(MethodInvocation node) {
- super.visitMethodInvocation(node);
- if (node.interfaceTargetReference?.node != null) {
- note(node.interfaceTargetReference?.node, node.arguments, node);
- }
- }
-
void visitSuperMethodInvocation(SuperMethodInvocation node) {
super.visitSuperMethodInvocation(node);
note(node.interfaceTargetReference.node, node.arguments, node);
@@ -226,8 +219,15 @@
} else if (arguments.positional[i] is ListLiteral) {
ListLiteral literal = arguments.positional[i];
if (literal.expressions.isEmpty) wantComment = true;
- } else if (arguments.positional[i] is MethodInvocation) {
- MethodInvocation methodInvocation = arguments.positional[i];
+ } else if (arguments.positional[i] is InstanceInvocation) {
+ InstanceInvocation methodInvocation = arguments.positional[i];
+ if (methodInvocation.receiver is NullLiteral ||
+ methodInvocation.receiver is IntLiteral ||
+ methodInvocation.receiver is BoolLiteral) {
+ wantComment = true;
+ }
+ } else if (arguments.positional[i] is DynamicInvocation) {
+ DynamicInvocation methodInvocation = arguments.positional[i];
if (methodInvocation.receiver is NullLiteral ||
methodInvocation.receiver is IntLiteral ||
methodInvocation.receiver is BoolLiteral) {
diff --git a/pkg/front_end/test/desugar_test.dart b/pkg/front_end/test/desugar_test.dart
index 7aa716d..f8078d1 100644
--- a/pkg/front_end/test/desugar_test.dart
+++ b/pkg/front_end/test/desugar_test.dart
@@ -67,7 +67,7 @@
Expect.isTrue(
member.kind == ir.ProcedureKind.Factory, "$member is not a factory");
Expect.isTrue(api.isRedirectingFactory(member));
- Expect.isTrue(member.isRedirectingFactoryConstructor);
+ Expect.isTrue(member.isRedirectingFactory);
}
const aSource = '''
diff --git a/pkg/front_end/test/generated_files_up_to_date_git_test.dart b/pkg/front_end/test/generated_files_up_to_date_git_test.dart
index 47f7548..0800570 100644
--- a/pkg/front_end/test/generated_files_up_to_date_git_test.dart
+++ b/pkg/front_end/test/generated_files_up_to_date_git_test.dart
@@ -13,16 +13,18 @@
as generateDirectParserAstHelper;
import "parser_test_listener_creator.dart" as generateParserTestListener;
import "parser_test_parser_creator.dart" as generateParserTestParser;
+import '../tool/generate_ast_equivalence.dart' as generateAstEquivalence;
import 'utils/io_utils.dart' show computeRepoDirUri;
final Uri repoDir = computeRepoDirUri();
-main() {
+main() async {
messages();
experimentalFlags();
directParserAstHelper();
parserTestListener();
parserTestParser();
+ await astEquivalence();
}
void parserTestParser() {
@@ -48,6 +50,14 @@
"dart pkg/front_end/tool/_fasta/direct_parser_ast_helper_creator.dart");
}
+Future<void> astEquivalence() async {
+ Uri generatedFile = generateAstEquivalence.computeEquivalenceUri(repoDir);
+ String generated =
+ await generateAstEquivalence.generateAstEquivalence(repoDir);
+ check(generated, generatedFile,
+ "dart pkg/front_end/tool/generate_ast_equivalence.dart");
+}
+
void experimentalFlags() {
{
Uri generatedFile =
diff --git a/pkg/front_end/test/incremental_compiler_leak_test.dart b/pkg/front_end/test/incremental_compiler_leak_test.dart
index d304ccb..922866f 100644
--- a/pkg/front_end/test/incremental_compiler_leak_test.dart
+++ b/pkg/front_end/test/incremental_compiler_leak_test.dart
@@ -243,7 +243,7 @@
"Field",
"Library",
"Procedure",
- "RedirectingFactoryConstructor",
+ "RedirectingFactory",
"Typedef",
};
diff --git a/pkg/front_end/test/incremental_dart2js_load_from_dill_test.dart b/pkg/front_end/test/incremental_dart2js_load_from_dill_test.dart
index 1fb8ad1..4320981 100644
--- a/pkg/front_end/test/incremental_dart2js_load_from_dill_test.dart
+++ b/pkg/front_end/test/incremental_dart2js_load_from_dill_test.dart
@@ -13,7 +13,8 @@
import 'package:kernel/binary/ast_from_binary.dart' show BinaryBuilder;
-import 'package:kernel/kernel.dart' show Component;
+import 'package:kernel/ast.dart';
+import 'package:kernel/src/equivalence.dart';
import 'package:kernel/target/targets.dart';
import 'incremental_suite.dart'
@@ -93,7 +94,19 @@
List<int> normalDillData = new File.fromUri(normalDill).readAsBytesSync();
List<int> initializedDillData =
new File.fromUri(fullDillFromInitialized).readAsBytesSync();
- checkIsEqual(normalDillData, initializedDillData);
+
+ Component component1 = new Component();
+ new BinaryBuilder(normalDillData).readComponent(component1);
+
+ Component component2 = new Component();
+ new BinaryBuilder(initializedDillData).readComponent(component2);
+ EquivalenceResult result =
+ checkEquivalence(component1, component2, strategy: const Strategy());
+ Expect.isTrue(result.isEquivalent, result.toString());
+
+ // TODO(johnniwinther): Reenable this check when the discrepancies have been
+ // fixed.
+ //checkIsEqual(normalDillData, initializedDillData);
// Also try without invalidating anything.
stopwatch.reset();
@@ -110,3 +123,49 @@
checkIsEqual(normalDillData, initializedDillData);
}
}
+
+class Strategy extends EquivalenceStrategy {
+ const Strategy();
+
+ @override
+ bool checkClass_procedures(
+ EquivalenceVisitor visitor, Class node, Class other) {
+ // Check procedures as a set instead of a list to allow for reordering.
+ return visitor.checkSets(node.procedures.toSet(), other.procedures.toSet(),
+ visitor.matchNamedNodes, visitor.checkNodes, 'procedures');
+ }
+
+ bool _isMixinOrCloneReference(EquivalenceVisitor visitor, Reference a,
+ Reference b, String propertyName) {
+ if (a != null && b != null) {
+ ReferenceName thisName = ReferenceName.fromReference(a);
+ ReferenceName otherName = ReferenceName.fromReference(b);
+ if (thisName.kind == ReferenceNameKind.Member &&
+ otherName.kind == ReferenceNameKind.Member &&
+ thisName.memberName == otherName.memberName) {
+ String thisClassName = thisName.declarationName;
+ String otherClassName = otherName.declarationName;
+ if (thisClassName != null &&
+ otherClassName != null &&
+ thisClassName.contains('&${otherClassName}')) {
+ visitor.assumeReferences(a, b);
+ }
+ }
+ }
+ return visitor.checkReferences(a, b, propertyName);
+ }
+
+ @override
+ bool checkProcedure_stubTargetReference(
+ EquivalenceVisitor visitor, Procedure node, Procedure other) {
+ return _isMixinOrCloneReference(visitor, node.stubTargetReference,
+ other.stubTargetReference, 'stubTargetReference');
+ }
+
+ @override
+ bool checkInstanceGet_interfaceTargetReference(
+ EquivalenceVisitor visitor, InstanceGet node, InstanceGet other) {
+ return _isMixinOrCloneReference(visitor, node.interfaceTargetReference,
+ other.interfaceTargetReference, 'interfaceTargetReference');
+ }
+}
diff --git a/pkg/front_end/test/simple_stats.dart b/pkg/front_end/test/simple_stats.dart
index dd69a4e..6ffd5c5 100644
--- a/pkg/front_end/test/simple_stats.dart
+++ b/pkg/front_end/test/simple_stats.dart
@@ -2,14 +2,12 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE.md file.
-// @dart = 2.9
-
import 'dart:math' as math;
class SimpleTTestStat {
static TTestResult ttest<E extends num>(List<E> a, List<E> b) {
- E aSum = a.reduce((value, element) => (value + element));
- E bSum = b.reduce((value, element) => (value + element));
+ E aSum = a.reduce((value, element) => (value + element) as E);
+ E bSum = b.reduce((value, element) => (value + element) as E);
int aCount = a.length;
int bCount = b.length;
double aMean = aSum / aCount;
@@ -37,7 +35,7 @@
}
static double variance<E extends num>(List<E> data) {
- E sum = data.reduce((value, element) => (value + element));
+ E sum = data.reduce((value, element) => (value + element) as E);
int count = data.length;
double average = sum / count;
diff --git a/pkg/front_end/test/spell_checking_list_code.txt b/pkg/front_end/test/spell_checking_list_code.txt
index 510170a..7cc2003 100644
--- a/pkg/front_end/test/spell_checking_list_code.txt
+++ b/pkg/front_end/test/spell_checking_list_code.txt
@@ -62,6 +62,7 @@
askesc
aspect
aspx
+asserting
assigning
assigns
association
@@ -142,7 +143,6 @@
bslash
buffered
builder`s
-bulder
bulk
bump
bypassing
@@ -168,6 +168,7 @@
casts
categorized
ce
+ceil
cfe
ch
channel
@@ -221,6 +222,7 @@
combiner
compared
compares
+compilations
completes
complicating
component's
@@ -298,6 +300,7 @@
deepest
deeply
def
+defaulting
degrades
degree
del
@@ -359,6 +362,7 @@
dummy
dupdate
dyn
+dynamically
e
easy
ecma
@@ -386,11 +390,14 @@
enforced
enforces
enforcing
+enters
+engineered
enumerates
env
eof
eq
equation
+equivalences
erased
erasure
es
@@ -577,6 +584,9 @@
indirection
individual
inequality
+inequivalence
+inequivalences
+inequivalent
influence
informative
infos
@@ -601,6 +611,7 @@
int8
integrate
intentionally
+interested
interim
interior
interleaved
@@ -783,6 +794,7 @@
nk
nnbd
node's
+nominality
nonimplementation
norm
normalization
@@ -818,6 +830,7 @@
ogham
oked
op
+opens
opt
optimizations
opting
@@ -1017,7 +1030,9 @@
remedy
removal
remover
+renames
render
+reordered
reparse
repeating
replacements
@@ -1032,6 +1047,7 @@
residue
resource
respond
+restoring
restriction
resumed
ret
@@ -1057,6 +1073,7 @@
rs
runnable
s
+sand
sanitizing
saw
say
@@ -1102,6 +1119,7 @@
siblings
sides
sigmund
+signaling
significant
simplify
singleton
@@ -1200,12 +1218,14 @@
sw
swapped
sweep
+symbolic
synchronously
syncs
synth
t
tagged
tagger
+tagging
tags
tailor
taking
@@ -1408,6 +1428,7 @@
wiki
wikipedia
wind
+wise
wiser
with1
wn
diff --git a/pkg/front_end/test/spell_checking_list_common.txt b/pkg/front_end/test/spell_checking_list_common.txt
index 816ad78..0b93c1a 100644
--- a/pkg/front_end/test/spell_checking_list_common.txt
+++ b/pkg/front_end/test/spell_checking_list_common.txt
@@ -1179,6 +1179,7 @@
fetch
few
fewer
+ffinative
field
field's
fieldname
diff --git a/pkg/front_end/test/spell_checking_list_tests.txt b/pkg/front_end/test/spell_checking_list_tests.txt
index c241a42..150c716 100644
--- a/pkg/front_end/test/spell_checking_list_tests.txt
+++ b/pkg/front_end/test/spell_checking_list_tests.txt
@@ -45,6 +45,7 @@
asserter
assure
asterisk
+atomic
auth
authority
autobianchi
@@ -111,27 +112,44 @@
c1b
c1c
c1d
+c1e
+c1f
c2a
c2b
c2c
c2d
+c2e
c3a
c3b
c3c
c3d
+c3e
+c3f
c4a
c4b
+c4c
+c4d
+c4e
+c4f
+c4g
+c4h
c59cdee365b94ce066344840f9e3412d642019b
c5a
c5b
+c5c
+c5d
c6a
c6b
c6c
+c7a
+c8a
+c8b
ca
cafebabe
calloc
camel
capitalized
+categorization
causal
cb
cc
@@ -157,6 +175,10 @@
class5b
class5c
class5d
+class7a
+class7b
+class8a
+class8b
cloneable
cm
cmd
@@ -184,6 +206,7 @@
confirm
consecutive
considering
+consist
constrains
consts
contract
@@ -225,10 +248,12 @@
dash
dashes
day
+days
db
ddart
dds
debugger
+declarative
decrease
decrements
dectcem
@@ -262,6 +287,7 @@
disallowed
disconnect
discovering
+discrepancies
dispatcher
dispose
dist
@@ -293,10 +319,12 @@
elegantly
ell
emethod
+enters
entrypoint
entrypoints
eoo
epoch
+equivalences
erase
erased
err
@@ -322,19 +350,42 @@
f1a
f1b
f1c
+f1d
+f1e
+f1f
+f1g
+f1h
+f1i
f2
f2a
f2b
+f2c
+f2d
+f2e
+f2f
+f2g
+f2h
+f2i
f3
f3a
f3b
+f3c
+f3d
+f3e
+f3f
f4
f4a
f4b
+f4c
+f4d
+f4e
+f4f
f5a
f5b
f6a
f6b
+f7a
+f8a
fac
faking
falling
@@ -404,6 +455,14 @@
fuzz
fuzzing
fx
+g1a
+g1b
+g1c
+g2a
+g2b
+g2c
+g3a
+g3b
gallery
gamma
gave
@@ -421,6 +480,20 @@
gtgt
gulp
gunk
+h1a
+h1b
+h1c
+h2a
+h2b
+h2c
+h3a
+h3b
+h4a
+h4b
+h5a
+h5b
+h6a
+h6b
hackish
hardly
helper2
@@ -439,6 +512,9 @@
hunk
hurray
i'm
+i2a
+i3a
+i3b
ia
ideal
identification
@@ -469,6 +545,7 @@
insufficient
intdiv
interactive
+interested
internet
interpolate
introducer
@@ -601,6 +678,8 @@
nil
ninja
noisy
+nominal
+nominality
nondefault
nonexisting
noo
@@ -633,6 +712,7 @@
pack
paging
paint
+parallax
parameterized
party
pause
@@ -700,6 +780,8 @@
redirections
rediscover
reducer
+reenable
+referential
referring
reflectee
refusing
@@ -711,6 +793,7 @@
reload
remap
remaps
+renames
rendition
reorder
reordering
@@ -733,6 +816,7 @@
rows
runtimes
rv
+sand
saves
scans
scheduler
@@ -746,6 +830,7 @@
selection
semifuzz
sensitive
+serves
services
setter1a
setter1b
@@ -759,6 +844,7 @@
shortest
shot
sigint
+signaling
signalled
sigwinch
slashes
@@ -881,6 +967,8 @@
verbatim
versioned
vf
+visitor0
+visitor1
vp
vt
vte
@@ -894,6 +982,7 @@
wherever
whiskers
wins
+wise
wording
workflow
worlds
diff --git a/pkg/front_end/test/static_types/analysis_helper.dart b/pkg/front_end/test/static_types/analysis_helper.dart
index 3ae2d5b..2091112 100644
--- a/pkg/front_end/test/static_types/analysis_helper.dart
+++ b/pkg/front_end/test/static_types/analysis_helper.dart
@@ -282,33 +282,6 @@
}
@override
- void visitPropertyGet(PropertyGet node) {
- DartType receiverType = node.receiver.getStaticType(staticTypeContext);
- if (receiverType is DynamicType && node.interfaceTarget == null) {
- registerError(node, "Dynamic access of '${node.name}'.");
- }
- super.visitPropertyGet(node);
- }
-
- @override
- void visitPropertySet(PropertySet node) {
- DartType receiverType = node.receiver.getStaticType(staticTypeContext);
- if (receiverType is DynamicType) {
- registerError(node, "Dynamic update to '${node.name}'.");
- }
- super.visitPropertySet(node);
- }
-
- @override
- void visitMethodInvocation(MethodInvocation node) {
- DartType receiverType = node.receiver.getStaticType(staticTypeContext);
- if (receiverType is DynamicType && node.interfaceTarget == null) {
- registerError(node, "Dynamic invocation of '${node.name}'.");
- }
- super.visitMethodInvocation(node);
- }
-
- @override
void visitFunctionDeclaration(FunctionDeclaration node) {
if (checkReturnTypes && node.function.returnType is DynamicType) {
registerError(node, "Dynamic return type");
diff --git a/pkg/front_end/test/text_representation/empty_reference_test.dart b/pkg/front_end/test/text_representation/empty_reference_test.dart
index a33bd6b..0e36da8 100644
--- a/pkg/front_end/test/text_representation/empty_reference_test.dart
+++ b/pkg/front_end/test/text_representation/empty_reference_test.dart
@@ -83,15 +83,15 @@
}
void testMembers() {
- testExpression(new PropertyGet(new IntLiteral(0), new Name('foo')), '''
-0.foo''');
testExpression(new StaticGet.byReference(null), '''
<missing-member-reference>''');
Reference unlinkedMemberName = new Reference();
testExpression(
- new PropertyGet.byReference(
- new IntLiteral(0), new Name('foo'), unlinkedMemberName),
+ new InstanceGet.byReference(
+ InstanceAccessKind.Instance, new IntLiteral(0), new Name('foo'),
+ interfaceTargetReference: unlinkedMemberName,
+ resultType: const DynamicType()),
'''
0.foo''');
testExpression(new StaticGet.byReference(unlinkedMemberName), '''
@@ -100,8 +100,10 @@
CanonicalName root = new CanonicalName.root();
Reference rootReference = new Reference()..canonicalName = root;
testExpression(
- new PropertyGet.byReference(
- new IntLiteral(0), new Name('foo'), rootReference),
+ new InstanceGet.byReference(
+ InstanceAccessKind.Instance, new IntLiteral(0), new Name('foo'),
+ interfaceTargetReference: rootReference,
+ resultType: const DynamicType()),
'''
0.foo''');
testExpression(new StaticGet.byReference(rootReference), '''
@@ -110,8 +112,10 @@
CanonicalName library = root.getChild('library');
Reference libraryReference = new Reference()..canonicalName = library;
testExpression(
- new PropertyGet.byReference(
- new IntLiteral(0), new Name('foo'), libraryReference),
+ new InstanceGet.byReference(
+ InstanceAccessKind.Instance, new IntLiteral(0), new Name('foo'),
+ interfaceTargetReference: libraryReference,
+ resultType: const DynamicType()),
'''
0.foo''');
testExpression(new StaticGet.byReference(libraryReference), '''
@@ -121,8 +125,10 @@
Reference topLevelMemberNameReference = new Reference()
..canonicalName = topLevelMemberName;
testExpression(
- new PropertyGet.byReference(
- new IntLiteral(0), new Name('foo'), topLevelMemberNameReference),
+ new InstanceGet.byReference(
+ InstanceAccessKind.Instance, new IntLiteral(0), new Name('foo'),
+ interfaceTargetReference: topLevelMemberNameReference,
+ resultType: const DynamicType()),
'''
0.foo''');
testExpression(new StaticGet.byReference(topLevelMemberNameReference), '''
@@ -132,8 +138,10 @@
CanonicalName className = library.getChild('Class');
Reference classNameReference = new Reference()..canonicalName = className;
testExpression(
- new PropertyGet.byReference(
- new IntLiteral(0), new Name('foo'), classNameReference),
+ new InstanceGet.byReference(
+ InstanceAccessKind.Instance, new IntLiteral(0), new Name('foo'),
+ interfaceTargetReference: classNameReference,
+ resultType: const DynamicType()),
'''
0.foo''');
testExpression(new StaticGet.byReference(classNameReference), '''
@@ -144,8 +152,10 @@
Reference classMemberNameReference = new Reference()
..canonicalName = classMemberName;
testExpression(
- new PropertyGet.byReference(
- new IntLiteral(0), new Name('foo'), classMemberNameReference),
+ new InstanceGet.byReference(
+ InstanceAccessKind.Instance, new IntLiteral(0), new Name('foo'),
+ interfaceTargetReference: classMemberNameReference,
+ resultType: const DynamicType()),
'''
0.foo''');
testExpression(new StaticGet.byReference(classMemberNameReference), '''
diff --git a/pkg/front_end/test/text_representation/internal_ast_text_representation_test.dart b/pkg/front_end/test/text_representation/internal_ast_text_representation_test.dart
index e1f4a5b..e483c41 100644
--- a/pkg/front_end/test/text_representation/internal_ast_text_representation_test.dart
+++ b/pkg/front_end/test/text_representation/internal_ast_text_representation_test.dart
@@ -44,6 +44,9 @@
_testFunctionDeclarationImpl();
_testIfNullExpression();
_testIntLiterals();
+ _testInternalMethodInvocation();
+ _testInternalPropertyGet();
+ _testInternalPropertySet();
_testExpressionInvocation();
_testNamedFunctionExpressionJudgment();
_testNullAwareMethodInvocation();
@@ -284,7 +287,7 @@
testExpression(cascade, '''
let final dynamic #0 = 0 in cascade {} => #0''');
- cascade.addCascadeExpression(new PropertySet(
+ cascade.addCascadeExpression(new DynamicSet(DynamicAccessKind.Dynamic,
new VariableGet(variable), new Name('foo'), new IntLiteral(1)));
testExpression(cascade, '''
let final dynamic #0 = 0 in cascade {
@@ -292,7 +295,7 @@
} => #0''', limited: '''
let final dynamic #0 = 0 in cascade { #0.foo = 1; } => #0''');
- cascade.addCascadeExpression(new PropertySet(
+ cascade.addCascadeExpression(new DynamicSet(DynamicAccessKind.Dynamic,
new VariableGet(variable), new Name('bar'), new IntLiteral(2)));
testExpression(cascade, '''
let final dynamic #0 = 0 in cascade {
@@ -372,6 +375,44 @@
testExpression(new ShadowLargeIntLiteral('bar', TreeNode.noOffset), 'bar');
}
+void _testInternalMethodInvocation() {
+ testExpression(
+ new MethodInvocation(
+ new IntLiteral(0), new Name('boz'), new ArgumentsImpl([])),
+ '''
+0.boz()''');
+ testExpression(
+ new MethodInvocation(
+ new IntLiteral(0),
+ new Name('boz'),
+ new ArgumentsImpl([
+ new IntLiteral(1)
+ ], types: [
+ const VoidType(),
+ const DynamicType()
+ ], named: [
+ new NamedExpression('foo', new IntLiteral(2)),
+ new NamedExpression('bar', new IntLiteral(3))
+ ])),
+ '''
+0.boz<void, dynamic>(1, foo: 2, bar: 3)''');
+}
+
+void _testInternalPropertyGet() {
+ testExpression(
+ new PropertyGet(new IntLiteral(0), new Name('boz')), '''
+0.boz''');
+}
+
+void _testInternalPropertySet() {
+ testExpression(
+ new PropertySet(
+ new IntLiteral(0), new Name('boz'), new IntLiteral(1),
+ forEffect: false, readOnlyReceiver: false),
+ '''
+0.boz = 1''');
+}
+
void _testExpressionInvocation() {
testExpression(
new ExpressionInvocation(new IntLiteral(0), new ArgumentsImpl([])), '''
@@ -409,11 +450,17 @@
testExpression(
new NullAwareMethodInvocation(
variable,
- new MethodInvocation(new VariableGet(variable), new Name('foo'),
+ new DynamicInvocation(
+ DynamicAccessKind.Dynamic,
+ new VariableGet(variable),
+ new Name('foo'),
new ArgumentsImpl([]))),
'''
0?.foo()''');
+ // TODO(johnniwinther): Add a test using InstanceInvocation instead of
+ // DynamicInvocation.
+
// An unusual use of this node.
testExpression(
new NullAwareMethodInvocation(variable,
@@ -437,7 +484,10 @@
testExpression(
new NullAwarePropertyGet(
variable,
- new MethodInvocation(new VariableGet(variable), new Name('foo'),
+ new DynamicInvocation(
+ DynamicAccessKind.Dynamic,
+ new VariableGet(variable),
+ new Name('foo'),
new ArgumentsImpl([]))),
'''
let final dynamic #0 = 0 in null-aware #0.foo()''');
@@ -450,15 +500,20 @@
testExpression(
new NullAwarePropertySet(
variable,
- new PropertySet(
- new VariableGet(variable), new Name('foo'), new IntLiteral(1))),
+ new DynamicSet(DynamicAccessKind.Dynamic, new VariableGet(variable),
+ new Name('foo'), new IntLiteral(1))),
'''
0?.foo = 1''');
+ // TODO(johnniwinther): Add a test using InstanceSet instead of DynamicSet.
+
testExpression(
new NullAwarePropertySet(
variable,
- new MethodInvocation(new VariableGet(variable), new Name('foo'),
+ new DynamicInvocation(
+ DynamicAccessKind.Dynamic,
+ new VariableGet(variable),
+ new Name('foo'),
new ArgumentsImpl([]))),
'''
let final dynamic #0 = 0 in null-aware #0.foo()''');
diff --git a/pkg/front_end/testcases/aot/enum_from_lib_used_as_type/main.dart.strong.transformed.expect b/pkg/front_end/testcases/aot/enum_from_lib_used_as_type/main.dart.strong.transformed.expect
index f92bdce..a821c4b 100644
--- a/pkg/front_end/testcases/aot/enum_from_lib_used_as_type/main.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/aot/enum_from_lib_used_as_type/main.dart.strong.transformed.expect
@@ -9,7 +9,10 @@
static method main() → dynamic {
core::List<dynamic> list = core::_GrowableList::•<dynamic>(0);
if(list.{core::Iterable::isNotEmpty}{core::bool}) {
- let dynamic #t1 = new mai::Class::•() in let dynamic #t2 = _in::unsafeCast<dynamic>(null) as{TypeError,ForDynamic,ForNonNullableByDefault} mai::Enum in throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
+ block {
+ new mai::Class::•();
+ _in::unsafeCast<dynamic>(null) as{TypeError,ForDynamic,ForNonNullableByDefault} mai::Enum;
+ } =>throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
}
}
diff --git a/pkg/front_end/testcases/aot/tree_shake/main.dart.strong.transformed.expect b/pkg/front_end/testcases/aot/tree_shake/main.dart.strong.transformed.expect
index 077bd72..0aaa3a0 100644
--- a/pkg/front_end/testcases/aot/tree_shake/main.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/aot/tree_shake/main.dart.strong.transformed.expect
@@ -35,7 +35,10 @@
#C3;
core::List<self::UnusedEnum> list = core::_GrowableList::•<self::UnusedEnum>(0);
if(list.{core::Iterable::isNotEmpty}{core::bool}) {
- let dynamic #t2 = new mai::ConstClass::•() in let dynamic #t3 = _in::unsafeCast<dynamic>(null) as{TypeError,ForDynamic,ForNonNullableByDefault} mai::ConstEnum in throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
+ block {
+ new mai::ConstClass::•();
+ _in::unsafeCast<dynamic>(null) as{TypeError,ForDynamic,ForNonNullableByDefault} mai::ConstEnum;
+ } =>throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
}
}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart.strong.expect
index e8c1280..7435151 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart.strong.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart.strong.expect
@@ -46,14 +46,14 @@
extension Extension on core::int {
}
static method test() → dynamic {
- self::ConcreteClass::•;
+ #C1;
invalid-expression "pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart:14:17: Error: Constructors on abstract classes can't be torn off.
AbstractClass.new; // error
^^^";
invalid-expression "pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart:15:9: Error: Getter not found: 'new'.
Mixin.new; // error
^^^";
- self::NamedMixinApplication::•;
+ #C2;
invalid-expression "pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart:17:33: Error: Constructors on abstract classes can't be torn off.
AbstractNamedMixinApplication.new; // error
^^^";
@@ -62,3 +62,8 @@
^^^";
}
static method main() → dynamic {}
+
+constants {
+ #C1 = constructor-tearoff self::ConcreteClass::•
+ #C2 = constructor-tearoff self::NamedMixinApplication::•
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart.strong.transformed.expect
index b86fac8..2b7289e 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart.strong.transformed.expect
@@ -46,14 +46,14 @@
extension Extension on core::int {
}
static method test() → dynamic {
- self::ConcreteClass::•;
+ #C1;
invalid-expression "pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart:14:17: Error: Constructors on abstract classes can't be torn off.
AbstractClass.new; // error
^^^";
invalid-expression "pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart:15:9: Error: Getter not found: 'new'.
Mixin.new; // error
^^^";
- self::NamedMixinApplication::•;
+ #C2;
invalid-expression "pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart:17:33: Error: Constructors on abstract classes can't be torn off.
AbstractNamedMixinApplication.new; // error
^^^";
@@ -62,3 +62,8 @@
^^^";
}
static method main() → dynamic {}
+
+constants {
+ #C1 = constructor-tearoff self::ConcreteClass::•
+ #C2 = constructor-tearoff self::NamedMixinApplication::•
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart.weak.expect
index e8c1280..7435151 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart.weak.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart.weak.expect
@@ -46,14 +46,14 @@
extension Extension on core::int {
}
static method test() → dynamic {
- self::ConcreteClass::•;
+ #C1;
invalid-expression "pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart:14:17: Error: Constructors on abstract classes can't be torn off.
AbstractClass.new; // error
^^^";
invalid-expression "pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart:15:9: Error: Getter not found: 'new'.
Mixin.new; // error
^^^";
- self::NamedMixinApplication::•;
+ #C2;
invalid-expression "pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart:17:33: Error: Constructors on abstract classes can't be torn off.
AbstractNamedMixinApplication.new; // error
^^^";
@@ -62,3 +62,8 @@
^^^";
}
static method main() → dynamic {}
+
+constants {
+ #C1 = constructor-tearoff self::ConcreteClass::•
+ #C2 = constructor-tearoff self::NamedMixinApplication::•
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart.weak.transformed.expect
index b86fac8..2b7289e 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart.weak.transformed.expect
@@ -46,14 +46,14 @@
extension Extension on core::int {
}
static method test() → dynamic {
- self::ConcreteClass::•;
+ #C1;
invalid-expression "pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart:14:17: Error: Constructors on abstract classes can't be torn off.
AbstractClass.new; // error
^^^";
invalid-expression "pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart:15:9: Error: Getter not found: 'new'.
Mixin.new; // error
^^^";
- self::NamedMixinApplication::•;
+ #C2;
invalid-expression "pkg/front_end/testcases/constructor_tearoffs/abstract_class_constructor_tear_off.dart:17:33: Error: Constructors on abstract classes can't be torn off.
AbstractNamedMixinApplication.new; // error
^^^";
@@ -62,3 +62,8 @@
^^^";
}
static method main() → dynamic {}
+
+constants {
+ #C1 = constructor-tearoff self::ConcreteClass::•
+ #C2 = constructor-tearoff self::NamedMixinApplication::•
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart b/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart
index 6d8b22b..8650911 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart
+++ b/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart
@@ -5,5 +5,10 @@
T func<T>(T value) => value;
var funcValue = func;
int Function(int) f = funcValue.call; // Disallowed!
+int Function(int) g = funcValue.call<int>; // Disallowed!
+
+test(Function f) {
+ int Function(int) g = f.call<int>; // Disallowed!
+}
main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.strong.expect
index 2d0b3bf..fe25279 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.strong.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.strong.expect
@@ -6,6 +6,12 @@
// int Function(int) f = funcValue.call; // Disallowed!
// ^
//
+// pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart:11:31: Error: The static type of the explicit instantiation operand must be a generic function type but is 'Function'.
+// - 'Function' is from 'dart:core'.
+// Try changing the operand or remove the type arguments.
+// int Function(int) g = f.call<int>; // Disallowed!
+// ^
+//
import self as self;
import "dart:core" as core;
@@ -13,10 +19,18 @@
static field (core::int) → core::int f = let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart:7:33: Error: A value of type 'T Function<T>(T)' can't be assigned to a variable of type 'int Function(int)'.
int Function(int) f = funcValue.call; // Disallowed!
^" in self::funcValue.call as{TypeError,ForNonNullableByDefault} (core::int) → core::int;
+static field (core::int) → core::int g = self::funcValue.call<core::int>;
static method func<T extends core::Object? = dynamic>(self::func::T% value) → self::func::T%
return value;
+static method test(core::Function f) → dynamic {
+ (core::int) → core::int g = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart:11:31: Error: The static type of the explicit instantiation operand must be a generic function type but is 'Function'.
+ - 'Function' is from 'dart:core'.
+Try changing the operand or remove the type arguments.
+ int Function(int) g = f.call<int>; // Disallowed!
+ ^";
+}
static method main() → dynamic {}
constants {
- #C1 = tearoff self::func
+ #C1 = static-tearoff self::func
}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.strong.transformed.expect
index 2d0b3bf..bdc66d1 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.strong.transformed.expect
@@ -18,5 +18,5 @@
static method main() → dynamic {}
constants {
- #C1 = tearoff self::func
+ #C1 = static-tearoff self::func
}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.textual_outline.expect
index 26c075f..6488494 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.textual_outline.expect
@@ -1,4 +1,6 @@
T func<T>(T value) => value;
var funcValue = func;
int Function(int) f = funcValue.call;
+int Function(int) g = funcValue.call<int>;
+test(Function f) {}
main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.weak.expect
index 2d0b3bf..fe25279 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.weak.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.weak.expect
@@ -6,6 +6,12 @@
// int Function(int) f = funcValue.call; // Disallowed!
// ^
//
+// pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart:11:31: Error: The static type of the explicit instantiation operand must be a generic function type but is 'Function'.
+// - 'Function' is from 'dart:core'.
+// Try changing the operand or remove the type arguments.
+// int Function(int) g = f.call<int>; // Disallowed!
+// ^
+//
import self as self;
import "dart:core" as core;
@@ -13,10 +19,18 @@
static field (core::int) → core::int f = let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart:7:33: Error: A value of type 'T Function<T>(T)' can't be assigned to a variable of type 'int Function(int)'.
int Function(int) f = funcValue.call; // Disallowed!
^" in self::funcValue.call as{TypeError,ForNonNullableByDefault} (core::int) → core::int;
+static field (core::int) → core::int g = self::funcValue.call<core::int>;
static method func<T extends core::Object? = dynamic>(self::func::T% value) → self::func::T%
return value;
+static method test(core::Function f) → dynamic {
+ (core::int) → core::int g = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart:11:31: Error: The static type of the explicit instantiation operand must be a generic function type but is 'Function'.
+ - 'Function' is from 'dart:core'.
+Try changing the operand or remove the type arguments.
+ int Function(int) g = f.call<int>; // Disallowed!
+ ^";
+}
static method main() → dynamic {}
constants {
- #C1 = tearoff self::func
+ #C1 = static-tearoff self::func
}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.weak.outline.expect
index cce6eb8..fc89fd2 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.weak.outline.expect
@@ -4,7 +4,10 @@
static field <T extends core::Object? = dynamic>(T%) → T% funcValue;
static field (core::int) → core::int f;
+static field (core::int) → core::int g;
static method func<T extends core::Object? = dynamic>(self::func::T% value) → self::func::T%
;
+static method test(core::Function f) → dynamic
+ ;
static method main() → dynamic
;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.weak.transformed.expect
index 2d0b3bf..bdc66d1 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/call_instantiation.dart.weak.transformed.expect
@@ -18,5 +18,5 @@
static method main() → dynamic {}
constants {
- #C1 = tearoff self::func
+ #C1 = static-tearoff self::func
}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart b/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart
new file mode 100644
index 0000000..e832879f
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart
@@ -0,0 +1,52 @@
+// 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 A<T> {
+ A();
+ factory A.fact() => new A();
+ factory A.redirect() = A;
+}
+
+typedef B<T> = A<T>;
+typedef C<T> = A<int>;
+
+const a = A.new;
+const b = A<int>.new;
+const c = A.fact;
+const d = A<int>.fact;
+const e = A.redirect;
+const f = A<int>.redirect;
+const g = B.new;
+const h = B<int>.new;
+const i = B.fact;
+const j = B<int>.fact;
+const k = B.redirect;
+const l = B<int>.redirect;
+const m = C.new;
+const n = C<int>.new;
+const o = C.fact;
+const p = C<int>.fact;
+const q = C.redirect;
+const r = C<int>.redirect;
+
+main() {
+ var a = A.new;
+ var b = A<int>.new;
+ var c = A.fact;
+ var d = A<int>.fact;
+ var e = A.redirect;
+ var f = A<int>.redirect;
+ var g = B.new;
+ var h = B<int>.new;
+ var i = B.fact;
+ var j = B<int>.fact;
+ var k = B.redirect;
+ var l = B<int>.redirect;
+ var m = C.new;
+ var n = C<int>.new;
+ var o = C.fact;
+ var p = C<int>.fact;
+ var q = C.redirect;
+ var r = C<int>.redirect;
+}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.strong.expect
new file mode 100644
index 0000000..cfec78a
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.strong.expect
@@ -0,0 +1,66 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef B<T extends core::Object? = dynamic> = self::A<T%>;
+typedef C<unrelated T extends core::Object? = dynamic> = self::A<core::int>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::A::redirect]/*isLegacy*/;
+ constructor •() → self::A<self::A::T%>
+ : super core::Object::•()
+ ;
+ static factory fact<T extends core::Object? = dynamic>() → self::A<self::A::fact::T%>
+ return new self::A::•<self::A::fact::T%>();
+ static factory redirect<T extends core::Object? = dynamic>() → self::A<self::A::redirect::T%>
+ let dynamic #redirecting_factory = self::A::• in let self::A::redirect::T% #typeArg0 = null in invalid-expression;
+}
+static const field <T extends core::Object? = dynamic>() → self::A<T%> a = #C1;
+static const field () → self::A<core::int> b = #C2;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> c = #C3;
+static const field () → self::A<core::int> d = #C4;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> e = #C5;
+static const field () → self::A<core::int> f = #C6;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> g = #C1;
+static const field () → self::A<core::int> h = #C2;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> i = #C3;
+static const field () → self::A<core::int> j = #C4;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> k = #C5;
+static const field () → self::A<core::int> l = #C6;
+static const field <unrelated T extends core::Object? = dynamic>() → self::A<core::int> m = #C7;
+static const field () → self::A<core::int> n = #C2;
+static const field <unrelated T extends core::Object? = dynamic>() → self::A<core::int> o = #C8;
+static const field () → self::A<core::int> p = #C4;
+static const field <unrelated T extends core::Object? = dynamic>() → self::A<core::int> q = #C9;
+static const field () → self::A<core::int> r = #C6;
+static method main() → dynamic {
+ <T extends core::Object? = dynamic>() → self::A<T%> a = #C1;
+ () → self::A<core::int> b = #C2;
+ <T extends core::Object? = dynamic>() → self::A<T%> c = #C3;
+ () → self::A<core::int> d = #C4;
+ <T extends core::Object? = dynamic>() → self::A<T%> e = #C5;
+ () → self::A<core::int> f = #C6;
+ <T extends core::Object? = dynamic>() → self::A<T%> g = #C1;
+ () → self::A<core::int> h = #C2;
+ <T extends core::Object? = dynamic>() → self::A<T%> i = #C3;
+ () → self::A<core::int> j = #C4;
+ <T extends core::Object? = dynamic>() → self::A<T%> k = #C5;
+ () → self::A<core::int> l = #C6;
+ <unrelated T extends core::Object? = dynamic>() → self::A<core::int> m = #C7;
+ () → self::A<core::int> n = #C2;
+ <unrelated T extends core::Object? = dynamic>() → self::A<core::int> o = #C8;
+ () → self::A<core::int> p = #C4;
+ <unrelated T extends core::Object? = dynamic>() → self::A<core::int> q = #C9;
+ () → self::A<core::int> r = #C6;
+}
+
+constants {
+ #C1 = constructor-tearoff self::A::•
+ #C2 = instantiation self::A::• <core::int>
+ #C3 = static-tearoff self::A::fact
+ #C4 = instantiation self::A::fact <core::int>
+ #C5 = redirecting-factory-tearoff self::A::redirect
+ #C6 = instantiation self::A::redirect <core::int>
+ #C7 = typedef-tearoff <unrelated T extends core::Object? = dynamic>.(#C1<core::int>)
+ #C8 = typedef-tearoff <unrelated T extends core::Object? = dynamic>.(#C3<core::int>)
+ #C9 = typedef-tearoff <unrelated T extends core::Object? = dynamic>.(#C5<core::int>)
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.strong.transformed.expect
new file mode 100644
index 0000000..d84286f
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.strong.transformed.expect
@@ -0,0 +1,66 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef B<T extends core::Object? = dynamic> = self::A<T%>;
+typedef C<unrelated T extends core::Object? = dynamic> = self::A<core::int>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::A::redirect]/*isLegacy*/;
+ constructor •() → self::A<self::A::T%>
+ : super core::Object::•()
+ ;
+ static factory fact<T extends core::Object? = dynamic>() → self::A<self::A::fact::T%>
+ return new self::A::•<self::A::fact::T%>();
+ static factory redirect<T extends core::Object? = dynamic>() → self::A<self::A::redirect::T%>
+ let Never #redirecting_factory = self::A::• in let self::A::redirect::T% #typeArg0 = null in invalid-expression;
+}
+static const field <T extends core::Object? = dynamic>() → self::A<T%> a = #C1;
+static const field () → self::A<core::int> b = #C2;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> c = #C3;
+static const field () → self::A<core::int> d = #C4;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> e = #C5;
+static const field () → self::A<core::int> f = #C6;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> g = #C1;
+static const field () → self::A<core::int> h = #C2;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> i = #C3;
+static const field () → self::A<core::int> j = #C4;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> k = #C5;
+static const field () → self::A<core::int> l = #C6;
+static const field <unrelated T extends core::Object? = dynamic>() → self::A<core::int> m = #C7;
+static const field () → self::A<core::int> n = #C2;
+static const field <unrelated T extends core::Object? = dynamic>() → self::A<core::int> o = #C8;
+static const field () → self::A<core::int> p = #C4;
+static const field <unrelated T extends core::Object? = dynamic>() → self::A<core::int> q = #C9;
+static const field () → self::A<core::int> r = #C6;
+static method main() → dynamic {
+ <T extends core::Object? = dynamic>() → self::A<T%> a = #C1;
+ () → self::A<core::int> b = #C2;
+ <T extends core::Object? = dynamic>() → self::A<T%> c = #C3;
+ () → self::A<core::int> d = #C4;
+ <T extends core::Object? = dynamic>() → self::A<T%> e = #C5;
+ () → self::A<core::int> f = #C6;
+ <T extends core::Object? = dynamic>() → self::A<T%> g = #C1;
+ () → self::A<core::int> h = #C2;
+ <T extends core::Object? = dynamic>() → self::A<T%> i = #C3;
+ () → self::A<core::int> j = #C4;
+ <T extends core::Object? = dynamic>() → self::A<T%> k = #C5;
+ () → self::A<core::int> l = #C6;
+ <unrelated T extends core::Object? = dynamic>() → self::A<core::int> m = #C7;
+ () → self::A<core::int> n = #C2;
+ <unrelated T extends core::Object? = dynamic>() → self::A<core::int> o = #C8;
+ () → self::A<core::int> p = #C4;
+ <unrelated T extends core::Object? = dynamic>() → self::A<core::int> q = #C9;
+ () → self::A<core::int> r = #C6;
+}
+
+constants {
+ #C1 = constructor-tearoff self::A::•
+ #C2 = instantiation self::A::• <core::int>
+ #C3 = static-tearoff self::A::fact
+ #C4 = instantiation self::A::fact <core::int>
+ #C5 = redirecting-factory-tearoff self::A::redirect
+ #C6 = instantiation self::A::redirect <core::int>
+ #C7 = typedef-tearoff <unrelated T extends core::Object? = dynamic>.(#C1<core::int>)
+ #C8 = typedef-tearoff <unrelated T extends core::Object? = dynamic>.(#C3<core::int>)
+ #C9 = typedef-tearoff <unrelated T extends core::Object? = dynamic>.(#C5<core::int>)
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.textual_outline.expect
new file mode 100644
index 0000000..a4b6c13
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.textual_outline.expect
@@ -0,0 +1,26 @@
+class A<T> {
+ A();
+ factory A.fact() => new A();
+ factory A.redirect() = A;
+}
+typedef B<T> = A<T>;
+typedef C<T> = A<int>;
+const a = A.new;
+const b = A<int>.new;
+const c = A.fact;
+const d = A<int>.fact;
+const e = A.redirect;
+const f = A<int>.redirect;
+const g = B.new;
+const h = B<int>.new;
+const i = B.fact;
+const j = B<int>.fact;
+const k = B.redirect;
+const l = B<int>.redirect;
+const m = C.new;
+const n = C<int>.new;
+const o = C.fact;
+const p = C<int>.fact;
+const q = C.redirect;
+const r = C<int>.redirect;
+main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.weak.expect
new file mode 100644
index 0000000..7412c43
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.weak.expect
@@ -0,0 +1,66 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef B<T extends core::Object? = dynamic> = self::A<T%>;
+typedef C<unrelated T extends core::Object? = dynamic> = self::A<core::int>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::A::redirect]/*isLegacy*/;
+ constructor •() → self::A<self::A::T%>
+ : super core::Object::•()
+ ;
+ static factory fact<T extends core::Object? = dynamic>() → self::A<self::A::fact::T%>
+ return new self::A::•<self::A::fact::T%>();
+ static factory redirect<T extends core::Object? = dynamic>() → self::A<self::A::redirect::T%>
+ let dynamic #redirecting_factory = self::A::• in let self::A::redirect::T% #typeArg0 = null in invalid-expression;
+}
+static const field <T extends core::Object? = dynamic>() → self::A<T%> a = #C1;
+static const field () → self::A<core::int> b = #C2;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> c = #C3;
+static const field () → self::A<core::int> d = #C4;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> e = #C5;
+static const field () → self::A<core::int> f = #C6;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> g = #C1;
+static const field () → self::A<core::int> h = #C2;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> i = #C3;
+static const field () → self::A<core::int> j = #C4;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> k = #C5;
+static const field () → self::A<core::int> l = #C6;
+static const field <unrelated T extends core::Object? = dynamic>() → self::A<core::int> m = #C7;
+static const field () → self::A<core::int> n = #C2;
+static const field <unrelated T extends core::Object? = dynamic>() → self::A<core::int> o = #C8;
+static const field () → self::A<core::int> p = #C4;
+static const field <unrelated T extends core::Object? = dynamic>() → self::A<core::int> q = #C9;
+static const field () → self::A<core::int> r = #C6;
+static method main() → dynamic {
+ <T extends core::Object? = dynamic>() → self::A<T%> a = #C1;
+ () → self::A<core::int> b = #C2;
+ <T extends core::Object? = dynamic>() → self::A<T%> c = #C3;
+ () → self::A<core::int> d = #C4;
+ <T extends core::Object? = dynamic>() → self::A<T%> e = #C5;
+ () → self::A<core::int> f = #C6;
+ <T extends core::Object? = dynamic>() → self::A<T%> g = #C1;
+ () → self::A<core::int> h = #C2;
+ <T extends core::Object? = dynamic>() → self::A<T%> i = #C3;
+ () → self::A<core::int> j = #C4;
+ <T extends core::Object? = dynamic>() → self::A<T%> k = #C5;
+ () → self::A<core::int> l = #C6;
+ <unrelated T extends core::Object? = dynamic>() → self::A<core::int> m = #C7;
+ () → self::A<core::int> n = #C2;
+ <unrelated T extends core::Object? = dynamic>() → self::A<core::int> o = #C8;
+ () → self::A<core::int> p = #C4;
+ <unrelated T extends core::Object? = dynamic>() → self::A<core::int> q = #C9;
+ () → self::A<core::int> r = #C6;
+}
+
+constants {
+ #C1 = constructor-tearoff self::A::•
+ #C2 = instantiation self::A::• <core::int*>
+ #C3 = static-tearoff self::A::fact
+ #C4 = instantiation self::A::fact <core::int*>
+ #C5 = redirecting-factory-tearoff self::A::redirect
+ #C6 = instantiation self::A::redirect <core::int*>
+ #C7 = typedef-tearoff <unrelated T extends core::Object? = dynamic>.(#C1<core::int>)
+ #C8 = typedef-tearoff <unrelated T extends core::Object? = dynamic>.(#C3<core::int>)
+ #C9 = typedef-tearoff <unrelated T extends core::Object? = dynamic>.(#C5<core::int>)
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.weak.outline.expect
new file mode 100644
index 0000000..b93adae
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.weak.outline.expect
@@ -0,0 +1,57 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef B<T extends core::Object? = dynamic> = self::A<T%>;
+typedef C<unrelated T extends core::Object? = dynamic> = self::A<core::int>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::A::redirect]/*isLegacy*/;
+ constructor •() → self::A<self::A::T%>
+ ;
+ static factory fact<T extends core::Object? = dynamic>() → self::A<self::A::fact::T%>
+ ;
+ static factory redirect<T extends core::Object? = dynamic>() → self::A<self::A::redirect::T%>
+ let dynamic #redirecting_factory = self::A::• in let self::A::redirect::T% #typeArg0 = null in invalid-expression;
+}
+static const field <T extends core::Object? = dynamic>() → self::A<T%> a = self::A::•;
+static const field () → self::A<core::int> b = self::A::•<core::int>;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> c = self::A::fact;
+static const field () → self::A<core::int> d = self::A::fact<core::int>;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> e = self::A::redirect;
+static const field () → self::A<core::int> f = self::A::redirect<core::int>;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> g = self::A::•;
+static const field () → self::A<core::int> h = self::A::•<core::int>;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> i = self::A::fact;
+static const field () → self::A<core::int> j = self::A::fact<core::int>;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> k = self::A::redirect;
+static const field () → self::A<core::int> l = self::A::redirect<core::int>;
+static const field <unrelated T extends core::Object? = dynamic>() → self::A<core::int> m = <unrelated T extends core::Object? = dynamic>.(self::A::•<core::int>);
+static const field () → self::A<core::int> n = self::A::•<core::int>;
+static const field <unrelated T extends core::Object? = dynamic>() → self::A<core::int> o = <unrelated T extends core::Object? = dynamic>.(self::A::fact<core::int>);
+static const field () → self::A<core::int> p = self::A::fact<core::int>;
+static const field <unrelated T extends core::Object? = dynamic>() → self::A<core::int> q = <unrelated T extends core::Object? = dynamic>.(self::A::redirect<core::int>);
+static const field () → self::A<core::int> r = self::A::redirect<core::int>;
+static method main() → dynamic
+ ;
+
+
+Extra constant evaluation status:
+Evaluated: ConstructorTearOff @ org-dartlang-testcase:///const_tear_off.dart:14:11 -> ConstructorTearOffConstant(A.)
+Evaluated: Instantiation @ org-dartlang-testcase:///const_tear_off.dart:15:11 -> InstantiationConstant(A.<int*>)
+Evaluated: StaticTearOff @ org-dartlang-testcase:///const_tear_off.dart:16:11 -> StaticTearOffConstant(A.fact)
+Evaluated: Instantiation @ org-dartlang-testcase:///const_tear_off.dart:17:11 -> InstantiationConstant(A.fact<int*>)
+Evaluated: RedirectingFactoryTearOff @ org-dartlang-testcase:///const_tear_off.dart:18:11 -> RedirectingFactoryTearOffConstant(A.redirect)
+Evaluated: Instantiation @ org-dartlang-testcase:///const_tear_off.dart:19:11 -> InstantiationConstant(A.redirect<int*>)
+Evaluated: ConstructorTearOff @ org-dartlang-testcase:///const_tear_off.dart:20:11 -> ConstructorTearOffConstant(A.)
+Evaluated: Instantiation @ org-dartlang-testcase:///const_tear_off.dart:21:11 -> InstantiationConstant(A.<int*>)
+Evaluated: StaticTearOff @ org-dartlang-testcase:///const_tear_off.dart:22:11 -> StaticTearOffConstant(A.fact)
+Evaluated: Instantiation @ org-dartlang-testcase:///const_tear_off.dart:23:11 -> InstantiationConstant(A.fact<int*>)
+Evaluated: RedirectingFactoryTearOff @ org-dartlang-testcase:///const_tear_off.dart:24:11 -> RedirectingFactoryTearOffConstant(A.redirect)
+Evaluated: Instantiation @ org-dartlang-testcase:///const_tear_off.dart:25:11 -> InstantiationConstant(A.redirect<int*>)
+Evaluated: TypedefTearOff @ org-dartlang-testcase:///const_tear_off.dart:26:11 -> TypedefTearOffConstant(<T>A.<int>)
+Evaluated: Instantiation @ org-dartlang-testcase:///const_tear_off.dart:27:11 -> InstantiationConstant(A.<int*>)
+Evaluated: TypedefTearOff @ org-dartlang-testcase:///const_tear_off.dart:28:11 -> TypedefTearOffConstant(<T>A.fact<int>)
+Evaluated: Instantiation @ org-dartlang-testcase:///const_tear_off.dart:29:11 -> InstantiationConstant(A.fact<int*>)
+Evaluated: TypedefTearOff @ org-dartlang-testcase:///const_tear_off.dart:30:11 -> TypedefTearOffConstant(<T>A.redirect<int>)
+Evaluated: Instantiation @ org-dartlang-testcase:///const_tear_off.dart:31:11 -> InstantiationConstant(A.redirect<int*>)
+Extra constant evaluation: evaluated: 23, effectively constant: 18
diff --git a/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.weak.transformed.expect
new file mode 100644
index 0000000..0a0394c
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/const_tear_off.dart.weak.transformed.expect
@@ -0,0 +1,66 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef B<T extends core::Object? = dynamic> = self::A<T%>;
+typedef C<unrelated T extends core::Object? = dynamic> = self::A<core::int>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::A::redirect]/*isLegacy*/;
+ constructor •() → self::A<self::A::T%>
+ : super core::Object::•()
+ ;
+ static factory fact<T extends core::Object? = dynamic>() → self::A<self::A::fact::T%>
+ return new self::A::•<self::A::fact::T%>();
+ static factory redirect<T extends core::Object? = dynamic>() → self::A<self::A::redirect::T%>
+ let Never #redirecting_factory = self::A::• in let self::A::redirect::T% #typeArg0 = null in invalid-expression;
+}
+static const field <T extends core::Object? = dynamic>() → self::A<T%> a = #C1;
+static const field () → self::A<core::int> b = #C2;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> c = #C3;
+static const field () → self::A<core::int> d = #C4;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> e = #C5;
+static const field () → self::A<core::int> f = #C6;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> g = #C1;
+static const field () → self::A<core::int> h = #C2;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> i = #C3;
+static const field () → self::A<core::int> j = #C4;
+static const field <T extends core::Object? = dynamic>() → self::A<T%> k = #C5;
+static const field () → self::A<core::int> l = #C6;
+static const field <unrelated T extends core::Object? = dynamic>() → self::A<core::int> m = #C7;
+static const field () → self::A<core::int> n = #C2;
+static const field <unrelated T extends core::Object? = dynamic>() → self::A<core::int> o = #C8;
+static const field () → self::A<core::int> p = #C4;
+static const field <unrelated T extends core::Object? = dynamic>() → self::A<core::int> q = #C9;
+static const field () → self::A<core::int> r = #C6;
+static method main() → dynamic {
+ <T extends core::Object? = dynamic>() → self::A<T%> a = #C1;
+ () → self::A<core::int> b = #C2;
+ <T extends core::Object? = dynamic>() → self::A<T%> c = #C3;
+ () → self::A<core::int> d = #C4;
+ <T extends core::Object? = dynamic>() → self::A<T%> e = #C5;
+ () → self::A<core::int> f = #C6;
+ <T extends core::Object? = dynamic>() → self::A<T%> g = #C1;
+ () → self::A<core::int> h = #C2;
+ <T extends core::Object? = dynamic>() → self::A<T%> i = #C3;
+ () → self::A<core::int> j = #C4;
+ <T extends core::Object? = dynamic>() → self::A<T%> k = #C5;
+ () → self::A<core::int> l = #C6;
+ <unrelated T extends core::Object? = dynamic>() → self::A<core::int> m = #C7;
+ () → self::A<core::int> n = #C2;
+ <unrelated T extends core::Object? = dynamic>() → self::A<core::int> o = #C8;
+ () → self::A<core::int> p = #C4;
+ <unrelated T extends core::Object? = dynamic>() → self::A<core::int> q = #C9;
+ () → self::A<core::int> r = #C6;
+}
+
+constants {
+ #C1 = constructor-tearoff self::A::•
+ #C2 = instantiation self::A::• <core::int*>
+ #C3 = static-tearoff self::A::fact
+ #C4 = instantiation self::A::fact <core::int*>
+ #C5 = redirecting-factory-tearoff self::A::redirect
+ #C6 = instantiation self::A::redirect <core::int*>
+ #C7 = typedef-tearoff <unrelated T extends core::Object? = dynamic>.(#C1<core::int>)
+ #C8 = typedef-tearoff <unrelated T extends core::Object? = dynamic>.(#C3<core::int>)
+ #C9 = typedef-tearoff <unrelated T extends core::Object? = dynamic>.(#C5<core::int>)
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart b/pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart
new file mode 100644
index 0000000..50c03ac
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart
@@ -0,0 +1,10 @@
+// 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.
+
+test1(dynamic x) => x.foo<int>; // Error.
+test2(Never x) => x.foo<int>; // Error.
+test3(dynamic x) => x.toString<int>; // Error.
+test4(Never x) => x.toString<int>; // Error.
+
+main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart.strong.expect
new file mode 100644
index 0000000..ee9aed5
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart.strong.expect
@@ -0,0 +1,47 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:5:26: Error: The static type of the explicit instantiation operand must be a generic function type but is 'dynamic'.
+// Try changing the operand or remove the type arguments.
+// test1(dynamic x) => x.foo<int>; // Error.
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:6:24: Error: The static type of the explicit instantiation operand must be a generic function type but is 'Never'.
+// Try changing the operand or remove the type arguments.
+// test2(Never x) => x.foo<int>; // Error.
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:7:31: Error: The static type of the explicit instantiation operand must be a generic function type but is 'String Function()'.
+// Try changing the operand or remove the type arguments.
+// test3(dynamic x) => x.toString<int>; // Error.
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:8:29: Error: The static type of the explicit instantiation operand must be a generic function type but is 'Never'.
+// Try changing the operand or remove the type arguments.
+// test4(Never x) => x.toString<int>; // Error.
+// ^
+//
+import self as self;
+
+static method test1(dynamic x) → dynamic
+ return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:5:26: Error: The static type of the explicit instantiation operand must be a generic function type but is 'dynamic'.
+Try changing the operand or remove the type arguments.
+test1(dynamic x) => x.foo<int>; // Error.
+ ^";
+static method test2(Never x) → dynamic
+ return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:6:24: Error: The static type of the explicit instantiation operand must be a generic function type but is 'Never'.
+Try changing the operand or remove the type arguments.
+test2(Never x) => x.foo<int>; // Error.
+ ^";
+static method test3(dynamic x) → dynamic
+ return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:7:31: Error: The static type of the explicit instantiation operand must be a generic function type but is 'String Function()'.
+Try changing the operand or remove the type arguments.
+test3(dynamic x) => x.toString<int>; // Error.
+ ^";
+static method test4(Never x) → dynamic
+ return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:8:29: Error: The static type of the explicit instantiation operand must be a generic function type but is 'Never'.
+Try changing the operand or remove the type arguments.
+test4(Never x) => x.toString<int>; // Error.
+ ^";
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart.strong.transformed.expect
new file mode 100644
index 0000000..ee9aed5
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart.strong.transformed.expect
@@ -0,0 +1,47 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:5:26: Error: The static type of the explicit instantiation operand must be a generic function type but is 'dynamic'.
+// Try changing the operand or remove the type arguments.
+// test1(dynamic x) => x.foo<int>; // Error.
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:6:24: Error: The static type of the explicit instantiation operand must be a generic function type but is 'Never'.
+// Try changing the operand or remove the type arguments.
+// test2(Never x) => x.foo<int>; // Error.
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:7:31: Error: The static type of the explicit instantiation operand must be a generic function type but is 'String Function()'.
+// Try changing the operand or remove the type arguments.
+// test3(dynamic x) => x.toString<int>; // Error.
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:8:29: Error: The static type of the explicit instantiation operand must be a generic function type but is 'Never'.
+// Try changing the operand or remove the type arguments.
+// test4(Never x) => x.toString<int>; // Error.
+// ^
+//
+import self as self;
+
+static method test1(dynamic x) → dynamic
+ return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:5:26: Error: The static type of the explicit instantiation operand must be a generic function type but is 'dynamic'.
+Try changing the operand or remove the type arguments.
+test1(dynamic x) => x.foo<int>; // Error.
+ ^";
+static method test2(Never x) → dynamic
+ return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:6:24: Error: The static type of the explicit instantiation operand must be a generic function type but is 'Never'.
+Try changing the operand or remove the type arguments.
+test2(Never x) => x.foo<int>; // Error.
+ ^";
+static method test3(dynamic x) → dynamic
+ return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:7:31: Error: The static type of the explicit instantiation operand must be a generic function type but is 'String Function()'.
+Try changing the operand or remove the type arguments.
+test3(dynamic x) => x.toString<int>; // Error.
+ ^";
+static method test4(Never x) → dynamic
+ return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:8:29: Error: The static type of the explicit instantiation operand must be a generic function type but is 'Never'.
+Try changing the operand or remove the type arguments.
+test4(Never x) => x.toString<int>; // Error.
+ ^";
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart.textual_outline.expect
new file mode 100644
index 0000000..8143249
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart.textual_outline.expect
@@ -0,0 +1,5 @@
+test1(dynamic x) => x.foo<int>;
+test2(Never x) => x.foo<int>;
+test3(dynamic x) => x.toString<int>;
+test4(Never x) => x.toString<int>;
+main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart.weak.expect
new file mode 100644
index 0000000..ee9aed5
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart.weak.expect
@@ -0,0 +1,47 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:5:26: Error: The static type of the explicit instantiation operand must be a generic function type but is 'dynamic'.
+// Try changing the operand or remove the type arguments.
+// test1(dynamic x) => x.foo<int>; // Error.
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:6:24: Error: The static type of the explicit instantiation operand must be a generic function type but is 'Never'.
+// Try changing the operand or remove the type arguments.
+// test2(Never x) => x.foo<int>; // Error.
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:7:31: Error: The static type of the explicit instantiation operand must be a generic function type but is 'String Function()'.
+// Try changing the operand or remove the type arguments.
+// test3(dynamic x) => x.toString<int>; // Error.
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:8:29: Error: The static type of the explicit instantiation operand must be a generic function type but is 'Never'.
+// Try changing the operand or remove the type arguments.
+// test4(Never x) => x.toString<int>; // Error.
+// ^
+//
+import self as self;
+
+static method test1(dynamic x) → dynamic
+ return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:5:26: Error: The static type of the explicit instantiation operand must be a generic function type but is 'dynamic'.
+Try changing the operand or remove the type arguments.
+test1(dynamic x) => x.foo<int>; // Error.
+ ^";
+static method test2(Never x) → dynamic
+ return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:6:24: Error: The static type of the explicit instantiation operand must be a generic function type but is 'Never'.
+Try changing the operand or remove the type arguments.
+test2(Never x) => x.foo<int>; // Error.
+ ^";
+static method test3(dynamic x) → dynamic
+ return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:7:31: Error: The static type of the explicit instantiation operand must be a generic function type but is 'String Function()'.
+Try changing the operand or remove the type arguments.
+test3(dynamic x) => x.toString<int>; // Error.
+ ^";
+static method test4(Never x) → dynamic
+ return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:8:29: Error: The static type of the explicit instantiation operand must be a generic function type but is 'Never'.
+Try changing the operand or remove the type arguments.
+test4(Never x) => x.toString<int>; // Error.
+ ^";
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart.weak.outline.expect
new file mode 100644
index 0000000..a0dbfbd
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart.weak.outline.expect
@@ -0,0 +1,13 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+static method test1(dynamic x) → dynamic
+ ;
+static method test2(Never x) → dynamic
+ ;
+static method test3(dynamic x) → dynamic
+ ;
+static method test4(Never x) → dynamic
+ ;
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart.weak.transformed.expect
new file mode 100644
index 0000000..ee9aed5
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart.weak.transformed.expect
@@ -0,0 +1,47 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:5:26: Error: The static type of the explicit instantiation operand must be a generic function type but is 'dynamic'.
+// Try changing the operand or remove the type arguments.
+// test1(dynamic x) => x.foo<int>; // Error.
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:6:24: Error: The static type of the explicit instantiation operand must be a generic function type but is 'Never'.
+// Try changing the operand or remove the type arguments.
+// test2(Never x) => x.foo<int>; // Error.
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:7:31: Error: The static type of the explicit instantiation operand must be a generic function type but is 'String Function()'.
+// Try changing the operand or remove the type arguments.
+// test3(dynamic x) => x.toString<int>; // Error.
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:8:29: Error: The static type of the explicit instantiation operand must be a generic function type but is 'Never'.
+// Try changing the operand or remove the type arguments.
+// test4(Never x) => x.toString<int>; // Error.
+// ^
+//
+import self as self;
+
+static method test1(dynamic x) → dynamic
+ return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:5:26: Error: The static type of the explicit instantiation operand must be a generic function type but is 'dynamic'.
+Try changing the operand or remove the type arguments.
+test1(dynamic x) => x.foo<int>; // Error.
+ ^";
+static method test2(Never x) → dynamic
+ return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:6:24: Error: The static type of the explicit instantiation operand must be a generic function type but is 'Never'.
+Try changing the operand or remove the type arguments.
+test2(Never x) => x.foo<int>; // Error.
+ ^";
+static method test3(dynamic x) → dynamic
+ return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:7:31: Error: The static type of the explicit instantiation operand must be a generic function type but is 'String Function()'.
+Try changing the operand or remove the type arguments.
+test3(dynamic x) => x.toString<int>; // Error.
+ ^";
+static method test4(Never x) → dynamic
+ return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/dynamic_explicit_instantiation.dart:8:29: Error: The static type of the explicit instantiation operand must be a generic function type but is 'Never'.
+Try changing the operand or remove the type arguments.
+test4(Never x) => x.toString<int>; // Error.
+ ^";
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.strong.expect
index efd5a53..ceaf4af 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.strong.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.strong.expect
@@ -92,12 +92,12 @@
}
constants {
- #C1 = tearoff self::C::stat
- #C2 = partial-instantiation self::C::stat <core::int>
- #C3 = tearoff self::M::mstat
- #C4 = partial-instantiation self::M::mstat <core::int>
- #C5 = tearoff self::Ext|estat
- #C6 = partial-instantiation self::Ext|estat <core::int>
+ #C1 = static-tearoff self::C::stat
+ #C2 = instantiation self::C::stat <core::int>
+ #C3 = static-tearoff self::M::mstat
+ #C4 = instantiation self::M::mstat <core::int>
+ #C5 = static-tearoff self::Ext|estat
+ #C6 = instantiation self::Ext|estat <core::int>
#C7 = TypeLiteralConstant(core::List<core::int>)
#C8 = TypeLiteralConstant(core::List<core::List<core::int>>)
}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.strong.transformed.expect
index ba6e6f0..aa394b3 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.strong.transformed.expect
@@ -100,12 +100,12 @@
}
constants {
- #C1 = tearoff self::C::stat
- #C2 = partial-instantiation self::C::stat <core::int>
- #C3 = tearoff self::M::mstat
- #C4 = partial-instantiation self::M::mstat <core::int>
- #C5 = tearoff self::Ext|estat
- #C6 = partial-instantiation self::Ext|estat <core::int>
+ #C1 = static-tearoff self::C::stat
+ #C2 = instantiation self::C::stat <core::int>
+ #C3 = static-tearoff self::M::mstat
+ #C4 = instantiation self::M::mstat <core::int>
+ #C5 = static-tearoff self::Ext|estat
+ #C6 = instantiation self::Ext|estat <core::int>
#C7 = TypeLiteralConstant(core::List<core::int>)
#C8 = TypeLiteralConstant(core::List<core::List<core::int>>)
}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.weak.expect
index 70f8b63..ea4ceb1 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.weak.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.weak.expect
@@ -92,12 +92,12 @@
}
constants {
- #C1 = tearoff self::C::stat
- #C2 = partial-instantiation self::C::stat <core::int*>
- #C3 = tearoff self::M::mstat
- #C4 = partial-instantiation self::M::mstat <core::int*>
- #C5 = tearoff self::Ext|estat
- #C6 = partial-instantiation self::Ext|estat <core::int*>
+ #C1 = static-tearoff self::C::stat
+ #C2 = instantiation self::C::stat <core::int*>
+ #C3 = static-tearoff self::M::mstat
+ #C4 = instantiation self::M::mstat <core::int*>
+ #C5 = static-tearoff self::Ext|estat
+ #C6 = instantiation self::Ext|estat <core::int*>
#C7 = TypeLiteralConstant(core::List<core::int*>*)
#C8 = TypeLiteralConstant(core::List<core::List<core::int*>*>*)
}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.weak.transformed.expect
index 217f0b6..fc6c975 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation.dart.weak.transformed.expect
@@ -100,12 +100,12 @@
}
constants {
- #C1 = tearoff self::C::stat
- #C2 = partial-instantiation self::C::stat <core::int*>
- #C3 = tearoff self::M::mstat
- #C4 = partial-instantiation self::M::mstat <core::int*>
- #C5 = tearoff self::Ext|estat
- #C6 = partial-instantiation self::Ext|estat <core::int*>
+ #C1 = static-tearoff self::C::stat
+ #C2 = instantiation self::C::stat <core::int*>
+ #C3 = static-tearoff self::M::mstat
+ #C4 = instantiation self::M::mstat <core::int*>
+ #C5 = static-tearoff self::Ext|estat
+ #C6 = instantiation self::Ext|estat <core::int*>
#C7 = TypeLiteralConstant(core::List<core::int*>*)
#C8 = TypeLiteralConstant(core::List<core::List<core::int*>*>*)
}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart.strong.expect
index 7d47228..630fe40 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart.strong.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart.strong.expect
@@ -105,8 +105,8 @@
static method main() → dynamic {}
constants {
- #C1 = tearoff self::id
- #C2 = partial-instantiation self::id <core::int>
- #C3 = tearoff self::boundedMethod
- #C4 = partial-instantiation self::boundedMethod <core::String>
+ #C1 = static-tearoff self::id
+ #C2 = instantiation self::id <core::int>
+ #C3 = static-tearoff self::boundedMethod
+ #C4 = instantiation self::boundedMethod <core::String>
}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart.strong.transformed.expect
index 7d47228..630fe40 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart.strong.transformed.expect
@@ -105,8 +105,8 @@
static method main() → dynamic {}
constants {
- #C1 = tearoff self::id
- #C2 = partial-instantiation self::id <core::int>
- #C3 = tearoff self::boundedMethod
- #C4 = partial-instantiation self::boundedMethod <core::String>
+ #C1 = static-tearoff self::id
+ #C2 = instantiation self::id <core::int>
+ #C3 = static-tearoff self::boundedMethod
+ #C4 = instantiation self::boundedMethod <core::String>
}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart.weak.expect
index c32e295..2e9d2db 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart.weak.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart.weak.expect
@@ -105,8 +105,8 @@
static method main() → dynamic {}
constants {
- #C1 = tearoff self::id
- #C2 = partial-instantiation self::id <core::int*>
- #C3 = tearoff self::boundedMethod
- #C4 = partial-instantiation self::boundedMethod <core::String*>
+ #C1 = static-tearoff self::id
+ #C2 = instantiation self::id <core::int*>
+ #C3 = static-tearoff self::boundedMethod
+ #C4 = instantiation self::boundedMethod <core::String*>
}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart.weak.transformed.expect
index c32e295..2e9d2db 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/explicit_instantiation_errors.dart.weak.transformed.expect
@@ -105,8 +105,8 @@
static method main() → dynamic {}
constants {
- #C1 = tearoff self::id
- #C2 = partial-instantiation self::id <core::int*>
- #C3 = tearoff self::boundedMethod
- #C4 = partial-instantiation self::boundedMethod <core::String*>
+ #C1 = static-tearoff self::id
+ #C2 = instantiation self::id <core::int*>
+ #C3 = static-tearoff self::boundedMethod
+ #C4 = instantiation self::boundedMethod <core::String*>
}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart b/pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart
new file mode 100644
index 0000000..fe45034
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart
@@ -0,0 +1,47 @@
+// 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 A {
+ A.new();
+}
+
+class B {
+ B();
+}
+
+class C {
+ C();
+ C.new(); // Error.
+}
+
+class D {
+ D.new();
+ D(); // Error.
+}
+
+class E1 {
+ E1._();
+ E1();
+ factory E1.new() => E1._(); // Error.
+}
+
+class E2 {
+ E2._();
+ factory E2.new() => E2._(); // Error.
+ E2();
+}
+
+class E3 {
+ E3._();
+ E3();
+ factory E3.new() = E3._; // Error.
+}
+
+class E4 {
+ E4._();
+ factory E4.new() = E4._;
+ E4(); // Error.
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart.strong.expect
new file mode 100644
index 0000000..331bcc5
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart.strong.expect
@@ -0,0 +1,101 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:15:3: Error: 'C' is already declared in this scope.
+// C.new(); // Error.
+// ^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:14:3: Context: Previous declaration of 'C'.
+// C();
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:20:3: Error: 'D' is already declared in this scope.
+// D(); // Error.
+// ^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:19:3: Context: Previous declaration of 'D'.
+// D.new();
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:26:11: Error: 'E1' is already declared in this scope.
+// factory E1.new() => E1._(); // Error.
+// ^^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:25:3: Context: Previous declaration of 'E1'.
+// E1();
+// ^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:32:3: Error: 'E2' is already declared in this scope.
+// E2();
+// ^^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:31:11: Context: Previous declaration of 'E2'.
+// factory E2.new() => E2._(); // Error.
+// ^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:38:11: Error: 'E3' is already declared in this scope.
+// factory E3.new() = E3._; // Error.
+// ^^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:37:3: Context: Previous declaration of 'E3'.
+// E3();
+// ^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:44:3: Error: 'E4' is already declared in this scope.
+// E4(); // Error.
+// ^^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:43:11: Context: Previous declaration of 'E4'.
+// factory E4.new() = E4._;
+// ^^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ constructor •() → self::A
+ : super core::Object::•()
+ ;
+}
+class B extends core::Object {
+ constructor •() → self::B
+ : super core::Object::•()
+ ;
+}
+class C extends core::Object {
+ constructor •() → self::C
+ : super core::Object::•()
+ ;
+}
+class D extends core::Object {
+ constructor •() → self::D
+ : super core::Object::•()
+ ;
+}
+class E1 extends core::Object {
+ constructor _() → self::E1
+ : super core::Object::•()
+ ;
+ constructor •() → self::E1
+ : super core::Object::•()
+ ;
+}
+class E2 extends core::Object {
+ constructor _() → self::E2
+ : super core::Object::•()
+ ;
+ static factory •() → self::E2
+ return new self::E2::_();
+}
+class E3 extends core::Object {
+ constructor _() → self::E3
+ : super core::Object::•()
+ ;
+ constructor •() → self::E3
+ : super core::Object::•()
+ ;
+}
+class E4 extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::E4::•]/*isLegacy*/;
+ constructor _() → self::E4
+ : super core::Object::•()
+ ;
+ static factory •() → self::E4
+ let dynamic #redirecting_factory = self::E4::_ in invalid-expression;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart.strong.transformed.expect
new file mode 100644
index 0000000..fdbc0b6
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart.strong.transformed.expect
@@ -0,0 +1,101 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:15:3: Error: 'C' is already declared in this scope.
+// C.new(); // Error.
+// ^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:14:3: Context: Previous declaration of 'C'.
+// C();
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:20:3: Error: 'D' is already declared in this scope.
+// D(); // Error.
+// ^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:19:3: Context: Previous declaration of 'D'.
+// D.new();
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:26:11: Error: 'E1' is already declared in this scope.
+// factory E1.new() => E1._(); // Error.
+// ^^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:25:3: Context: Previous declaration of 'E1'.
+// E1();
+// ^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:32:3: Error: 'E2' is already declared in this scope.
+// E2();
+// ^^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:31:11: Context: Previous declaration of 'E2'.
+// factory E2.new() => E2._(); // Error.
+// ^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:38:11: Error: 'E3' is already declared in this scope.
+// factory E3.new() = E3._; // Error.
+// ^^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:37:3: Context: Previous declaration of 'E3'.
+// E3();
+// ^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:44:3: Error: 'E4' is already declared in this scope.
+// E4(); // Error.
+// ^^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:43:11: Context: Previous declaration of 'E4'.
+// factory E4.new() = E4._;
+// ^^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ constructor •() → self::A
+ : super core::Object::•()
+ ;
+}
+class B extends core::Object {
+ constructor •() → self::B
+ : super core::Object::•()
+ ;
+}
+class C extends core::Object {
+ constructor •() → self::C
+ : super core::Object::•()
+ ;
+}
+class D extends core::Object {
+ constructor •() → self::D
+ : super core::Object::•()
+ ;
+}
+class E1 extends core::Object {
+ constructor _() → self::E1
+ : super core::Object::•()
+ ;
+ constructor •() → self::E1
+ : super core::Object::•()
+ ;
+}
+class E2 extends core::Object {
+ constructor _() → self::E2
+ : super core::Object::•()
+ ;
+ static factory •() → self::E2
+ return new self::E2::_();
+}
+class E3 extends core::Object {
+ constructor _() → self::E3
+ : super core::Object::•()
+ ;
+ constructor •() → self::E3
+ : super core::Object::•()
+ ;
+}
+class E4 extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::E4::•]/*isLegacy*/;
+ constructor _() → self::E4
+ : super core::Object::•()
+ ;
+ static factory •() → self::E4
+ let Never #redirecting_factory = self::E4::_ in invalid-expression;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart.textual_outline.expect
new file mode 100644
index 0000000..d6ac347
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart.textual_outline.expect
@@ -0,0 +1,35 @@
+class A {
+ A.new();
+}
+class B {
+ B();
+}
+class C {
+ C();
+ C.new();
+}
+class D {
+ D.new();
+ D();
+}
+class E1 {
+ E1._();
+ E1();
+ factory E1.new() => E1._();
+}
+class E2 {
+ E2._();
+ factory E2.new() => E2._();
+ E2();
+}
+class E3 {
+ E3._();
+ E3();
+ factory E3.new() = E3._;
+}
+class E4 {
+ E4._();
+ factory E4.new() = E4._;
+ E4();
+}
+main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart.weak.expect
new file mode 100644
index 0000000..331bcc5
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart.weak.expect
@@ -0,0 +1,101 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:15:3: Error: 'C' is already declared in this scope.
+// C.new(); // Error.
+// ^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:14:3: Context: Previous declaration of 'C'.
+// C();
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:20:3: Error: 'D' is already declared in this scope.
+// D(); // Error.
+// ^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:19:3: Context: Previous declaration of 'D'.
+// D.new();
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:26:11: Error: 'E1' is already declared in this scope.
+// factory E1.new() => E1._(); // Error.
+// ^^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:25:3: Context: Previous declaration of 'E1'.
+// E1();
+// ^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:32:3: Error: 'E2' is already declared in this scope.
+// E2();
+// ^^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:31:11: Context: Previous declaration of 'E2'.
+// factory E2.new() => E2._(); // Error.
+// ^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:38:11: Error: 'E3' is already declared in this scope.
+// factory E3.new() = E3._; // Error.
+// ^^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:37:3: Context: Previous declaration of 'E3'.
+// E3();
+// ^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:44:3: Error: 'E4' is already declared in this scope.
+// E4(); // Error.
+// ^^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:43:11: Context: Previous declaration of 'E4'.
+// factory E4.new() = E4._;
+// ^^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ constructor •() → self::A
+ : super core::Object::•()
+ ;
+}
+class B extends core::Object {
+ constructor •() → self::B
+ : super core::Object::•()
+ ;
+}
+class C extends core::Object {
+ constructor •() → self::C
+ : super core::Object::•()
+ ;
+}
+class D extends core::Object {
+ constructor •() → self::D
+ : super core::Object::•()
+ ;
+}
+class E1 extends core::Object {
+ constructor _() → self::E1
+ : super core::Object::•()
+ ;
+ constructor •() → self::E1
+ : super core::Object::•()
+ ;
+}
+class E2 extends core::Object {
+ constructor _() → self::E2
+ : super core::Object::•()
+ ;
+ static factory •() → self::E2
+ return new self::E2::_();
+}
+class E3 extends core::Object {
+ constructor _() → self::E3
+ : super core::Object::•()
+ ;
+ constructor •() → self::E3
+ : super core::Object::•()
+ ;
+}
+class E4 extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::E4::•]/*isLegacy*/;
+ constructor _() → self::E4
+ : super core::Object::•()
+ ;
+ static factory •() → self::E4
+ let dynamic #redirecting_factory = self::E4::_ in invalid-expression;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart.weak.outline.expect
new file mode 100644
index 0000000..34ae47c
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart.weak.outline.expect
@@ -0,0 +1,92 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:15:3: Error: 'C' is already declared in this scope.
+// C.new(); // Error.
+// ^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:14:3: Context: Previous declaration of 'C'.
+// C();
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:20:3: Error: 'D' is already declared in this scope.
+// D(); // Error.
+// ^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:19:3: Context: Previous declaration of 'D'.
+// D.new();
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:26:11: Error: 'E1' is already declared in this scope.
+// factory E1.new() => E1._(); // Error.
+// ^^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:25:3: Context: Previous declaration of 'E1'.
+// E1();
+// ^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:32:3: Error: 'E2' is already declared in this scope.
+// E2();
+// ^^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:31:11: Context: Previous declaration of 'E2'.
+// factory E2.new() => E2._(); // Error.
+// ^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:38:11: Error: 'E3' is already declared in this scope.
+// factory E3.new() = E3._; // Error.
+// ^^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:37:3: Context: Previous declaration of 'E3'.
+// E3();
+// ^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:44:3: Error: 'E4' is already declared in this scope.
+// E4(); // Error.
+// ^^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:43:11: Context: Previous declaration of 'E4'.
+// factory E4.new() = E4._;
+// ^^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ constructor •() → self::A
+ ;
+}
+class B extends core::Object {
+ constructor •() → self::B
+ ;
+}
+class C extends core::Object {
+ constructor •() → self::C
+ ;
+}
+class D extends core::Object {
+ constructor •() → self::D
+ ;
+}
+class E1 extends core::Object {
+ constructor _() → self::E1
+ ;
+ constructor •() → self::E1
+ ;
+}
+class E2 extends core::Object {
+ constructor _() → self::E2
+ ;
+ static factory •() → self::E2
+ ;
+}
+class E3 extends core::Object {
+ constructor _() → self::E3
+ ;
+ constructor •() → self::E3
+ ;
+}
+class E4 extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::E4::•]/*isLegacy*/;
+ constructor _() → self::E4
+ ;
+ static factory •() → self::E4
+ let dynamic #redirecting_factory = self::E4::_ in invalid-expression;
+}
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart.weak.transformed.expect
new file mode 100644
index 0000000..fdbc0b6
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart.weak.transformed.expect
@@ -0,0 +1,101 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:15:3: Error: 'C' is already declared in this scope.
+// C.new(); // Error.
+// ^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:14:3: Context: Previous declaration of 'C'.
+// C();
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:20:3: Error: 'D' is already declared in this scope.
+// D(); // Error.
+// ^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:19:3: Context: Previous declaration of 'D'.
+// D.new();
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:26:11: Error: 'E1' is already declared in this scope.
+// factory E1.new() => E1._(); // Error.
+// ^^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:25:3: Context: Previous declaration of 'E1'.
+// E1();
+// ^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:32:3: Error: 'E2' is already declared in this scope.
+// E2();
+// ^^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:31:11: Context: Previous declaration of 'E2'.
+// factory E2.new() => E2._(); // Error.
+// ^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:38:11: Error: 'E3' is already declared in this scope.
+// factory E3.new() = E3._; // Error.
+// ^^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:37:3: Context: Previous declaration of 'E3'.
+// E3();
+// ^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:44:3: Error: 'E4' is already declared in this scope.
+// E4(); // Error.
+// ^^
+// pkg/front_end/testcases/constructor_tearoffs/explicit_new_as_unnamed.dart:43:11: Context: Previous declaration of 'E4'.
+// factory E4.new() = E4._;
+// ^^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ constructor •() → self::A
+ : super core::Object::•()
+ ;
+}
+class B extends core::Object {
+ constructor •() → self::B
+ : super core::Object::•()
+ ;
+}
+class C extends core::Object {
+ constructor •() → self::C
+ : super core::Object::•()
+ ;
+}
+class D extends core::Object {
+ constructor •() → self::D
+ : super core::Object::•()
+ ;
+}
+class E1 extends core::Object {
+ constructor _() → self::E1
+ : super core::Object::•()
+ ;
+ constructor •() → self::E1
+ : super core::Object::•()
+ ;
+}
+class E2 extends core::Object {
+ constructor _() → self::E2
+ : super core::Object::•()
+ ;
+ static factory •() → self::E2
+ return new self::E2::_();
+}
+class E3 extends core::Object {
+ constructor _() → self::E3
+ : super core::Object::•()
+ ;
+ constructor •() → self::E3
+ : super core::Object::•()
+ ;
+}
+class E4 extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::E4::•]/*isLegacy*/;
+ constructor _() → self::E4
+ : super core::Object::•()
+ ;
+ static factory •() → self::E4
+ let Never #redirecting_factory = self::E4::_ in invalid-expression;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart.strong.expect
index 3ac9d56..fdd4fb7 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart.strong.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart.strong.expect
@@ -4,14 +4,14 @@
//
// pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:13:32: Error: A value of type 'A<X/*1*/> Function<X>(X/*1*/, int)' can't be returned from a function with return type 'A<X/*2*/> Function<X>(X/*2*/)'.
// - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
-// - 'X/*1*/' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
+// - 'X/*1*/' is from 'unknown'.
// - 'X/*2*/' is from 'unknown'.
// A<X> Function<X>(X) test2() => A.foo2; // Error.
// ^
//
// pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:14:32: Error: A value of type 'A<X/*1*/> Function<X>()' can't be returned from a function with return type 'A<X/*2*/> Function<X>(X/*2*/)'.
// - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
-// - 'X/*1*/' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
+// - 'X/*1*/' is from 'unknown'.
// - 'X/*2*/' is from 'unknown'.
// A<X> Function<X>(X) test3() => A.new; // Error.
// ^
@@ -68,26 +68,26 @@
return new self::A::•<self::A::bar1::X%>();
}
static method test1() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
- return self::A::foo1;
+ return #C1;
static method test2() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
return let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:13:32: Error: A value of type 'A<X/*1*/> Function<X>(X/*1*/, int)' can't be returned from a function with return type 'A<X/*2*/> Function<X>(X/*2*/)'.
- 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
- - 'X/*1*/' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
+ - 'X/*1*/' is from 'unknown'.
- 'X/*2*/' is from 'unknown'.
A<X> Function<X>(X) test2() => A.foo2; // Error.
- ^" in self::A::foo2 as{TypeError,ForNonNullableByDefault} Never;
+ ^" in (#C2) as{TypeError,ForNonNullableByDefault} Never;
static method test3() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
return let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:14:32: Error: A value of type 'A<X/*1*/> Function<X>()' can't be returned from a function with return type 'A<X/*2*/> Function<X>(X/*2*/)'.
- 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
- - 'X/*1*/' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
+ - 'X/*1*/' is from 'unknown'.
- 'X/*2*/' is from 'unknown'.
A<X> Function<X>(X) test3() => A.new; // Error.
- ^" in self::A::• as{TypeError,ForNonNullableByDefault} Never;
+ ^" in (#C3) as{TypeError,ForNonNullableByDefault} Never;
static method test4() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
return let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:15:32: Error: A value of type 'A<int> Function()' can't be returned from a function with return type 'A<X> Function<X>(X)'.
- 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
A<X> Function<X>(X) test4() => A<int>.new; // Error.
- ^" in (self::A::•<core::int>) as{TypeError,ForNonNullableByDefault} Never;
+ ^" in (#C4) as{TypeError,ForNonNullableByDefault} Never;
static method test5() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:16:32: Error: Too many type arguments: 1 allowed, but 2 found.
Try removing the extra type arguments.
@@ -97,7 +97,7 @@
return let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:17:32: Error: A value of type 'A<int> Function(int)' can't be returned from a function with return type 'A<X> Function<X>(X)'.
- 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
A<X> Function<X>(X) test6() => A<int>.foo1; // Error.
- ^" in (self::A::foo1<core::int>) as{TypeError,ForNonNullableByDefault} Never;
+ ^" in (#C5) as{TypeError,ForNonNullableByDefault} Never;
static method test7() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:18:32: Error: Too many type arguments: 1 allowed, but 2 found.
Try removing the extra type arguments.
@@ -107,23 +107,34 @@
return let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:19:32: Error: A value of type 'A<int> Function(int, int)' can't be returned from a function with return type 'A<X> Function<X>(X)'.
- 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
A<X> Function<X>(X) test8() => A<int>.foo2; // Error.
- ^" in (self::A::foo2<core::int>) as{TypeError,ForNonNullableByDefault} Never;
+ ^" in (#C6) as{TypeError,ForNonNullableByDefault} Never;
static method test9() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:20:32: Error: Too many type arguments: 1 allowed, but 2 found.
Try removing the extra type arguments.
A<X> Function<X>(X) test9() => A<int, String>.foo2; // Error.
^";
static method test10() → <X extends core::Object? = dynamic>() → self::A<X%>
- return self::A::bar1;
+ return #C7;
static method test11() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
return let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:22:33: Error: A value of type 'A<X/*1*/> Function<X>()' can't be returned from a function with return type 'A<X/*2*/> Function<X>(X/*2*/)'.
- 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
- 'X/*1*/' is from 'unknown'.
- 'X/*2*/' is from 'unknown'.
A<X> Function<X>(X) test11() => A.bar1; // Error.
- ^" in self::A::bar1 as{TypeError,ForNonNullableByDefault} Never;
+ ^" in (#C7) as{TypeError,ForNonNullableByDefault} Never;
static method test12() → () → self::A<core::int>
- return self::A::bar1<core::int>;
+ return #C8;
static method test13() → () → self::A<core::int>
- return self::A::bar1<core::int>;
+ return #C8;
static method main() → dynamic {}
+
+constants {
+ #C1 = constructor-tearoff self::A::foo1
+ #C2 = constructor-tearoff self::A::foo2
+ #C3 = constructor-tearoff self::A::•
+ #C4 = instantiation self::A::• <core::int>
+ #C5 = instantiation self::A::foo1 <core::int>
+ #C6 = instantiation self::A::foo2 <core::int>
+ #C7 = static-tearoff self::A::bar1
+ #C8 = instantiation self::A::bar1 <core::int>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart.strong.transformed.expect
index 3ac9d56..fdd4fb7 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart.strong.transformed.expect
@@ -4,14 +4,14 @@
//
// pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:13:32: Error: A value of type 'A<X/*1*/> Function<X>(X/*1*/, int)' can't be returned from a function with return type 'A<X/*2*/> Function<X>(X/*2*/)'.
// - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
-// - 'X/*1*/' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
+// - 'X/*1*/' is from 'unknown'.
// - 'X/*2*/' is from 'unknown'.
// A<X> Function<X>(X) test2() => A.foo2; // Error.
// ^
//
// pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:14:32: Error: A value of type 'A<X/*1*/> Function<X>()' can't be returned from a function with return type 'A<X/*2*/> Function<X>(X/*2*/)'.
// - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
-// - 'X/*1*/' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
+// - 'X/*1*/' is from 'unknown'.
// - 'X/*2*/' is from 'unknown'.
// A<X> Function<X>(X) test3() => A.new; // Error.
// ^
@@ -68,26 +68,26 @@
return new self::A::•<self::A::bar1::X%>();
}
static method test1() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
- return self::A::foo1;
+ return #C1;
static method test2() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
return let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:13:32: Error: A value of type 'A<X/*1*/> Function<X>(X/*1*/, int)' can't be returned from a function with return type 'A<X/*2*/> Function<X>(X/*2*/)'.
- 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
- - 'X/*1*/' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
+ - 'X/*1*/' is from 'unknown'.
- 'X/*2*/' is from 'unknown'.
A<X> Function<X>(X) test2() => A.foo2; // Error.
- ^" in self::A::foo2 as{TypeError,ForNonNullableByDefault} Never;
+ ^" in (#C2) as{TypeError,ForNonNullableByDefault} Never;
static method test3() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
return let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:14:32: Error: A value of type 'A<X/*1*/> Function<X>()' can't be returned from a function with return type 'A<X/*2*/> Function<X>(X/*2*/)'.
- 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
- - 'X/*1*/' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
+ - 'X/*1*/' is from 'unknown'.
- 'X/*2*/' is from 'unknown'.
A<X> Function<X>(X) test3() => A.new; // Error.
- ^" in self::A::• as{TypeError,ForNonNullableByDefault} Never;
+ ^" in (#C3) as{TypeError,ForNonNullableByDefault} Never;
static method test4() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
return let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:15:32: Error: A value of type 'A<int> Function()' can't be returned from a function with return type 'A<X> Function<X>(X)'.
- 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
A<X> Function<X>(X) test4() => A<int>.new; // Error.
- ^" in (self::A::•<core::int>) as{TypeError,ForNonNullableByDefault} Never;
+ ^" in (#C4) as{TypeError,ForNonNullableByDefault} Never;
static method test5() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:16:32: Error: Too many type arguments: 1 allowed, but 2 found.
Try removing the extra type arguments.
@@ -97,7 +97,7 @@
return let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:17:32: Error: A value of type 'A<int> Function(int)' can't be returned from a function with return type 'A<X> Function<X>(X)'.
- 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
A<X> Function<X>(X) test6() => A<int>.foo1; // Error.
- ^" in (self::A::foo1<core::int>) as{TypeError,ForNonNullableByDefault} Never;
+ ^" in (#C5) as{TypeError,ForNonNullableByDefault} Never;
static method test7() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:18:32: Error: Too many type arguments: 1 allowed, but 2 found.
Try removing the extra type arguments.
@@ -107,23 +107,34 @@
return let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:19:32: Error: A value of type 'A<int> Function(int, int)' can't be returned from a function with return type 'A<X> Function<X>(X)'.
- 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
A<X> Function<X>(X) test8() => A<int>.foo2; // Error.
- ^" in (self::A::foo2<core::int>) as{TypeError,ForNonNullableByDefault} Never;
+ ^" in (#C6) as{TypeError,ForNonNullableByDefault} Never;
static method test9() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:20:32: Error: Too many type arguments: 1 allowed, but 2 found.
Try removing the extra type arguments.
A<X> Function<X>(X) test9() => A<int, String>.foo2; // Error.
^";
static method test10() → <X extends core::Object? = dynamic>() → self::A<X%>
- return self::A::bar1;
+ return #C7;
static method test11() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
return let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:22:33: Error: A value of type 'A<X/*1*/> Function<X>()' can't be returned from a function with return type 'A<X/*2*/> Function<X>(X/*2*/)'.
- 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
- 'X/*1*/' is from 'unknown'.
- 'X/*2*/' is from 'unknown'.
A<X> Function<X>(X) test11() => A.bar1; // Error.
- ^" in self::A::bar1 as{TypeError,ForNonNullableByDefault} Never;
+ ^" in (#C7) as{TypeError,ForNonNullableByDefault} Never;
static method test12() → () → self::A<core::int>
- return self::A::bar1<core::int>;
+ return #C8;
static method test13() → () → self::A<core::int>
- return self::A::bar1<core::int>;
+ return #C8;
static method main() → dynamic {}
+
+constants {
+ #C1 = constructor-tearoff self::A::foo1
+ #C2 = constructor-tearoff self::A::foo2
+ #C3 = constructor-tearoff self::A::•
+ #C4 = instantiation self::A::• <core::int>
+ #C5 = instantiation self::A::foo1 <core::int>
+ #C6 = instantiation self::A::foo2 <core::int>
+ #C7 = static-tearoff self::A::bar1
+ #C8 = instantiation self::A::bar1 <core::int>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart.weak.expect
index 3ac9d56..b0da904 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart.weak.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart.weak.expect
@@ -4,14 +4,14 @@
//
// pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:13:32: Error: A value of type 'A<X/*1*/> Function<X>(X/*1*/, int)' can't be returned from a function with return type 'A<X/*2*/> Function<X>(X/*2*/)'.
// - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
-// - 'X/*1*/' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
+// - 'X/*1*/' is from 'unknown'.
// - 'X/*2*/' is from 'unknown'.
// A<X> Function<X>(X) test2() => A.foo2; // Error.
// ^
//
// pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:14:32: Error: A value of type 'A<X/*1*/> Function<X>()' can't be returned from a function with return type 'A<X/*2*/> Function<X>(X/*2*/)'.
// - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
-// - 'X/*1*/' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
+// - 'X/*1*/' is from 'unknown'.
// - 'X/*2*/' is from 'unknown'.
// A<X> Function<X>(X) test3() => A.new; // Error.
// ^
@@ -68,26 +68,26 @@
return new self::A::•<self::A::bar1::X%>();
}
static method test1() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
- return self::A::foo1;
+ return #C1;
static method test2() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
return let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:13:32: Error: A value of type 'A<X/*1*/> Function<X>(X/*1*/, int)' can't be returned from a function with return type 'A<X/*2*/> Function<X>(X/*2*/)'.
- 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
- - 'X/*1*/' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
+ - 'X/*1*/' is from 'unknown'.
- 'X/*2*/' is from 'unknown'.
A<X> Function<X>(X) test2() => A.foo2; // Error.
- ^" in self::A::foo2 as{TypeError,ForNonNullableByDefault} Never;
+ ^" in (#C2) as{TypeError,ForNonNullableByDefault} Never;
static method test3() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
return let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:14:32: Error: A value of type 'A<X/*1*/> Function<X>()' can't be returned from a function with return type 'A<X/*2*/> Function<X>(X/*2*/)'.
- 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
- - 'X/*1*/' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
+ - 'X/*1*/' is from 'unknown'.
- 'X/*2*/' is from 'unknown'.
A<X> Function<X>(X) test3() => A.new; // Error.
- ^" in self::A::• as{TypeError,ForNonNullableByDefault} Never;
+ ^" in (#C3) as{TypeError,ForNonNullableByDefault} Never;
static method test4() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
return let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:15:32: Error: A value of type 'A<int> Function()' can't be returned from a function with return type 'A<X> Function<X>(X)'.
- 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
A<X> Function<X>(X) test4() => A<int>.new; // Error.
- ^" in (self::A::•<core::int>) as{TypeError,ForNonNullableByDefault} Never;
+ ^" in (#C4) as{TypeError,ForNonNullableByDefault} Never;
static method test5() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:16:32: Error: Too many type arguments: 1 allowed, but 2 found.
Try removing the extra type arguments.
@@ -97,7 +97,7 @@
return let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:17:32: Error: A value of type 'A<int> Function(int)' can't be returned from a function with return type 'A<X> Function<X>(X)'.
- 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
A<X> Function<X>(X) test6() => A<int>.foo1; // Error.
- ^" in (self::A::foo1<core::int>) as{TypeError,ForNonNullableByDefault} Never;
+ ^" in (#C5) as{TypeError,ForNonNullableByDefault} Never;
static method test7() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:18:32: Error: Too many type arguments: 1 allowed, but 2 found.
Try removing the extra type arguments.
@@ -107,23 +107,34 @@
return let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:19:32: Error: A value of type 'A<int> Function(int, int)' can't be returned from a function with return type 'A<X> Function<X>(X)'.
- 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
A<X> Function<X>(X) test8() => A<int>.foo2; // Error.
- ^" in (self::A::foo2<core::int>) as{TypeError,ForNonNullableByDefault} Never;
+ ^" in (#C6) as{TypeError,ForNonNullableByDefault} Never;
static method test9() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:20:32: Error: Too many type arguments: 1 allowed, but 2 found.
Try removing the extra type arguments.
A<X> Function<X>(X) test9() => A<int, String>.foo2; // Error.
^";
static method test10() → <X extends core::Object? = dynamic>() → self::A<X%>
- return self::A::bar1;
+ return #C7;
static method test11() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
return let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:22:33: Error: A value of type 'A<X/*1*/> Function<X>()' can't be returned from a function with return type 'A<X/*2*/> Function<X>(X/*2*/)'.
- 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
- 'X/*1*/' is from 'unknown'.
- 'X/*2*/' is from 'unknown'.
A<X> Function<X>(X) test11() => A.bar1; // Error.
- ^" in self::A::bar1 as{TypeError,ForNonNullableByDefault} Never;
+ ^" in (#C7) as{TypeError,ForNonNullableByDefault} Never;
static method test12() → () → self::A<core::int>
- return self::A::bar1<core::int>;
+ return #C8;
static method test13() → () → self::A<core::int>
- return self::A::bar1<core::int>;
+ return #C8;
static method main() → dynamic {}
+
+constants {
+ #C1 = constructor-tearoff self::A::foo1
+ #C2 = constructor-tearoff self::A::foo2
+ #C3 = constructor-tearoff self::A::•
+ #C4 = instantiation self::A::• <core::int*>
+ #C5 = instantiation self::A::foo1 <core::int*>
+ #C6 = instantiation self::A::foo2 <core::int*>
+ #C7 = static-tearoff self::A::bar1
+ #C8 = instantiation self::A::bar1 <core::int*>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart.weak.transformed.expect
index 3ac9d56..b0da904 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart.weak.transformed.expect
@@ -4,14 +4,14 @@
//
// pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:13:32: Error: A value of type 'A<X/*1*/> Function<X>(X/*1*/, int)' can't be returned from a function with return type 'A<X/*2*/> Function<X>(X/*2*/)'.
// - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
-// - 'X/*1*/' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
+// - 'X/*1*/' is from 'unknown'.
// - 'X/*2*/' is from 'unknown'.
// A<X> Function<X>(X) test2() => A.foo2; // Error.
// ^
//
// pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:14:32: Error: A value of type 'A<X/*1*/> Function<X>()' can't be returned from a function with return type 'A<X/*2*/> Function<X>(X/*2*/)'.
// - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
-// - 'X/*1*/' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
+// - 'X/*1*/' is from 'unknown'.
// - 'X/*2*/' is from 'unknown'.
// A<X> Function<X>(X) test3() => A.new; // Error.
// ^
@@ -68,26 +68,26 @@
return new self::A::•<self::A::bar1::X%>();
}
static method test1() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
- return self::A::foo1;
+ return #C1;
static method test2() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
return let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:13:32: Error: A value of type 'A<X/*1*/> Function<X>(X/*1*/, int)' can't be returned from a function with return type 'A<X/*2*/> Function<X>(X/*2*/)'.
- 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
- - 'X/*1*/' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
+ - 'X/*1*/' is from 'unknown'.
- 'X/*2*/' is from 'unknown'.
A<X> Function<X>(X) test2() => A.foo2; // Error.
- ^" in self::A::foo2 as{TypeError,ForNonNullableByDefault} Never;
+ ^" in (#C2) as{TypeError,ForNonNullableByDefault} Never;
static method test3() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
return let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:14:32: Error: A value of type 'A<X/*1*/> Function<X>()' can't be returned from a function with return type 'A<X/*2*/> Function<X>(X/*2*/)'.
- 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
- - 'X/*1*/' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
+ - 'X/*1*/' is from 'unknown'.
- 'X/*2*/' is from 'unknown'.
A<X> Function<X>(X) test3() => A.new; // Error.
- ^" in self::A::• as{TypeError,ForNonNullableByDefault} Never;
+ ^" in (#C3) as{TypeError,ForNonNullableByDefault} Never;
static method test4() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
return let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:15:32: Error: A value of type 'A<int> Function()' can't be returned from a function with return type 'A<X> Function<X>(X)'.
- 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
A<X> Function<X>(X) test4() => A<int>.new; // Error.
- ^" in (self::A::•<core::int>) as{TypeError,ForNonNullableByDefault} Never;
+ ^" in (#C4) as{TypeError,ForNonNullableByDefault} Never;
static method test5() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:16:32: Error: Too many type arguments: 1 allowed, but 2 found.
Try removing the extra type arguments.
@@ -97,7 +97,7 @@
return let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:17:32: Error: A value of type 'A<int> Function(int)' can't be returned from a function with return type 'A<X> Function<X>(X)'.
- 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
A<X> Function<X>(X) test6() => A<int>.foo1; // Error.
- ^" in (self::A::foo1<core::int>) as{TypeError,ForNonNullableByDefault} Never;
+ ^" in (#C5) as{TypeError,ForNonNullableByDefault} Never;
static method test7() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:18:32: Error: Too many type arguments: 1 allowed, but 2 found.
Try removing the extra type arguments.
@@ -107,23 +107,34 @@
return let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:19:32: Error: A value of type 'A<int> Function(int, int)' can't be returned from a function with return type 'A<X> Function<X>(X)'.
- 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
A<X> Function<X>(X) test8() => A<int>.foo2; // Error.
- ^" in (self::A::foo2<core::int>) as{TypeError,ForNonNullableByDefault} Never;
+ ^" in (#C6) as{TypeError,ForNonNullableByDefault} Never;
static method test9() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:20:32: Error: Too many type arguments: 1 allowed, but 2 found.
Try removing the extra type arguments.
A<X> Function<X>(X) test9() => A<int, String>.foo2; // Error.
^";
static method test10() → <X extends core::Object? = dynamic>() → self::A<X%>
- return self::A::bar1;
+ return #C7;
static method test11() → <X extends core::Object? = dynamic>(X%) → self::A<X%>
return let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart:22:33: Error: A value of type 'A<X/*1*/> Function<X>()' can't be returned from a function with return type 'A<X/*2*/> Function<X>(X/*2*/)'.
- 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_with_context.dart'.
- 'X/*1*/' is from 'unknown'.
- 'X/*2*/' is from 'unknown'.
A<X> Function<X>(X) test11() => A.bar1; // Error.
- ^" in self::A::bar1 as{TypeError,ForNonNullableByDefault} Never;
+ ^" in (#C7) as{TypeError,ForNonNullableByDefault} Never;
static method test12() → () → self::A<core::int>
- return self::A::bar1<core::int>;
+ return #C8;
static method test13() → () → self::A<core::int>
- return self::A::bar1<core::int>;
+ return #C8;
static method main() → dynamic {}
+
+constants {
+ #C1 = constructor-tearoff self::A::foo1
+ #C2 = constructor-tearoff self::A::foo2
+ #C3 = constructor-tearoff self::A::•
+ #C4 = instantiation self::A::• <core::int*>
+ #C5 = instantiation self::A::foo1 <core::int*>
+ #C6 = instantiation self::A::foo2 <core::int*>
+ #C7 = static-tearoff self::A::bar1
+ #C8 = instantiation self::A::bar1 <core::int*>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart b/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart
index b668e20..ad3a27c 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart
+++ b/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart
@@ -19,4 +19,17 @@
testNewExtraArgs() => A<int, String>.new; // Error.
testBarExtraArgs() => A<int, String>.bar; // Error.
+method() {
+ var foo = A.foo; // Ok.
+ var fooArgs = A<int>.foo; // Ok.
+ var _new = A.new; // Ok.
+ var newArgs = A<int>.new; // Ok.
+ var bar = A.bar; // Ok.
+ var barArgs = A<int>.bar; // Ok.
+
+ var fooExtraArgs = A<int, String>.foo; // Error.
+ var newExtraArgs = A<int, String>.new; // Error.
+ var barExtraArgs = A<int, String>.bar; // Error.
+}
+
main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart.strong.expect
index b9ace2c..8aa8628 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart.strong.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart.strong.expect
@@ -17,6 +17,21 @@
// testBarExtraArgs() => A<int, String>.bar; // Error.
// ^
//
+// pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:30:22: Error: Too many type arguments: 1 allowed, but 2 found.
+// Try removing the extra type arguments.
+// var fooExtraArgs = A<int, String>.foo; // Error.
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:31:22: Error: Too many type arguments: 1 allowed, but 2 found.
+// Try removing the extra type arguments.
+// var newExtraArgs = A<int, String>.new; // Error.
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:32:22: Error: Too many type arguments: 1 allowed, but 2 found.
+// Try removing the extra type arguments.
+// var barExtraArgs = A<int, String>.bar; // Error.
+// ^
+//
import self as self;
import "dart:core" as core;
@@ -29,17 +44,17 @@
return new self::A::•<self::A::bar::X%>();
}
static method testFoo() → dynamic
- return self::A::foo;
+ return #C1;
static method testFooArgs() → dynamic
- return self::A::foo<core::int>;
+ return #C2;
static method testNew() → dynamic
- return self::A::•;
+ return #C3;
static method testNewArgs() → dynamic
- return self::A::•<core::int>;
+ return #C4;
static method testBar() → dynamic
- return self::A::bar;
+ return #C5;
static method testBarArgs() → dynamic
- return self::A::bar<core::int>;
+ return #C6;
static method testFooExtraArgs() → dynamic
return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:18:23: Error: Too many type arguments: 1 allowed, but 2 found.
Try removing the extra type arguments.
@@ -55,4 +70,33 @@
Try removing the extra type arguments.
testBarExtraArgs() => A<int, String>.bar; // Error.
^";
+static method method() → dynamic {
+ <X extends core::Object? = dynamic>() → self::A<X%> foo = #C1;
+ () → self::A<core::int> fooArgs = #C2;
+ <X extends core::Object? = dynamic>() → self::A<X%> _new = #C3;
+ () → self::A<core::int> newArgs = #C4;
+ <X extends core::Object? = dynamic>() → self::A<X%> bar = #C5;
+ () → self::A<core::int> barArgs = #C6;
+ invalid-type fooExtraArgs = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:30:22: Error: Too many type arguments: 1 allowed, but 2 found.
+Try removing the extra type arguments.
+ var fooExtraArgs = A<int, String>.foo; // Error.
+ ^";
+ invalid-type newExtraArgs = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:31:22: Error: Too many type arguments: 1 allowed, but 2 found.
+Try removing the extra type arguments.
+ var newExtraArgs = A<int, String>.new; // Error.
+ ^";
+ invalid-type barExtraArgs = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:32:22: Error: Too many type arguments: 1 allowed, but 2 found.
+Try removing the extra type arguments.
+ var barExtraArgs = A<int, String>.bar; // Error.
+ ^";
+}
static method main() → dynamic {}
+
+constants {
+ #C1 = constructor-tearoff self::A::foo
+ #C2 = instantiation self::A::foo <core::int>
+ #C3 = constructor-tearoff self::A::•
+ #C4 = instantiation self::A::• <core::int>
+ #C5 = static-tearoff self::A::bar
+ #C6 = instantiation self::A::bar <core::int>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart.strong.transformed.expect
index b9ace2c..8aa8628 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart.strong.transformed.expect
@@ -17,6 +17,21 @@
// testBarExtraArgs() => A<int, String>.bar; // Error.
// ^
//
+// pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:30:22: Error: Too many type arguments: 1 allowed, but 2 found.
+// Try removing the extra type arguments.
+// var fooExtraArgs = A<int, String>.foo; // Error.
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:31:22: Error: Too many type arguments: 1 allowed, but 2 found.
+// Try removing the extra type arguments.
+// var newExtraArgs = A<int, String>.new; // Error.
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:32:22: Error: Too many type arguments: 1 allowed, but 2 found.
+// Try removing the extra type arguments.
+// var barExtraArgs = A<int, String>.bar; // Error.
+// ^
+//
import self as self;
import "dart:core" as core;
@@ -29,17 +44,17 @@
return new self::A::•<self::A::bar::X%>();
}
static method testFoo() → dynamic
- return self::A::foo;
+ return #C1;
static method testFooArgs() → dynamic
- return self::A::foo<core::int>;
+ return #C2;
static method testNew() → dynamic
- return self::A::•;
+ return #C3;
static method testNewArgs() → dynamic
- return self::A::•<core::int>;
+ return #C4;
static method testBar() → dynamic
- return self::A::bar;
+ return #C5;
static method testBarArgs() → dynamic
- return self::A::bar<core::int>;
+ return #C6;
static method testFooExtraArgs() → dynamic
return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:18:23: Error: Too many type arguments: 1 allowed, but 2 found.
Try removing the extra type arguments.
@@ -55,4 +70,33 @@
Try removing the extra type arguments.
testBarExtraArgs() => A<int, String>.bar; // Error.
^";
+static method method() → dynamic {
+ <X extends core::Object? = dynamic>() → self::A<X%> foo = #C1;
+ () → self::A<core::int> fooArgs = #C2;
+ <X extends core::Object? = dynamic>() → self::A<X%> _new = #C3;
+ () → self::A<core::int> newArgs = #C4;
+ <X extends core::Object? = dynamic>() → self::A<X%> bar = #C5;
+ () → self::A<core::int> barArgs = #C6;
+ invalid-type fooExtraArgs = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:30:22: Error: Too many type arguments: 1 allowed, but 2 found.
+Try removing the extra type arguments.
+ var fooExtraArgs = A<int, String>.foo; // Error.
+ ^";
+ invalid-type newExtraArgs = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:31:22: Error: Too many type arguments: 1 allowed, but 2 found.
+Try removing the extra type arguments.
+ var newExtraArgs = A<int, String>.new; // Error.
+ ^";
+ invalid-type barExtraArgs = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:32:22: Error: Too many type arguments: 1 allowed, but 2 found.
+Try removing the extra type arguments.
+ var barExtraArgs = A<int, String>.bar; // Error.
+ ^";
+}
static method main() → dynamic {}
+
+constants {
+ #C1 = constructor-tearoff self::A::foo
+ #C2 = instantiation self::A::foo <core::int>
+ #C3 = constructor-tearoff self::A::•
+ #C4 = instantiation self::A::• <core::int>
+ #C5 = static-tearoff self::A::bar
+ #C6 = instantiation self::A::bar <core::int>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart.textual_outline.expect
index 4b026de..a5d04bf 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart.textual_outline.expect
@@ -12,4 +12,5 @@
testFooExtraArgs() => A<int, String>.foo;
testNewExtraArgs() => A<int, String>.new;
testBarExtraArgs() => A<int, String>.bar;
+method() {}
main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart.weak.expect
index b9ace2c..c49c929 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart.weak.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart.weak.expect
@@ -17,6 +17,21 @@
// testBarExtraArgs() => A<int, String>.bar; // Error.
// ^
//
+// pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:30:22: Error: Too many type arguments: 1 allowed, but 2 found.
+// Try removing the extra type arguments.
+// var fooExtraArgs = A<int, String>.foo; // Error.
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:31:22: Error: Too many type arguments: 1 allowed, but 2 found.
+// Try removing the extra type arguments.
+// var newExtraArgs = A<int, String>.new; // Error.
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:32:22: Error: Too many type arguments: 1 allowed, but 2 found.
+// Try removing the extra type arguments.
+// var barExtraArgs = A<int, String>.bar; // Error.
+// ^
+//
import self as self;
import "dart:core" as core;
@@ -29,17 +44,17 @@
return new self::A::•<self::A::bar::X%>();
}
static method testFoo() → dynamic
- return self::A::foo;
+ return #C1;
static method testFooArgs() → dynamic
- return self::A::foo<core::int>;
+ return #C2;
static method testNew() → dynamic
- return self::A::•;
+ return #C3;
static method testNewArgs() → dynamic
- return self::A::•<core::int>;
+ return #C4;
static method testBar() → dynamic
- return self::A::bar;
+ return #C5;
static method testBarArgs() → dynamic
- return self::A::bar<core::int>;
+ return #C6;
static method testFooExtraArgs() → dynamic
return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:18:23: Error: Too many type arguments: 1 allowed, but 2 found.
Try removing the extra type arguments.
@@ -55,4 +70,33 @@
Try removing the extra type arguments.
testBarExtraArgs() => A<int, String>.bar; // Error.
^";
+static method method() → dynamic {
+ <X extends core::Object? = dynamic>() → self::A<X%> foo = #C1;
+ () → self::A<core::int> fooArgs = #C2;
+ <X extends core::Object? = dynamic>() → self::A<X%> _new = #C3;
+ () → self::A<core::int> newArgs = #C4;
+ <X extends core::Object? = dynamic>() → self::A<X%> bar = #C5;
+ () → self::A<core::int> barArgs = #C6;
+ invalid-type fooExtraArgs = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:30:22: Error: Too many type arguments: 1 allowed, but 2 found.
+Try removing the extra type arguments.
+ var fooExtraArgs = A<int, String>.foo; // Error.
+ ^";
+ invalid-type newExtraArgs = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:31:22: Error: Too many type arguments: 1 allowed, but 2 found.
+Try removing the extra type arguments.
+ var newExtraArgs = A<int, String>.new; // Error.
+ ^";
+ invalid-type barExtraArgs = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:32:22: Error: Too many type arguments: 1 allowed, but 2 found.
+Try removing the extra type arguments.
+ var barExtraArgs = A<int, String>.bar; // Error.
+ ^";
+}
static method main() → dynamic {}
+
+constants {
+ #C1 = constructor-tearoff self::A::foo
+ #C2 = instantiation self::A::foo <core::int*>
+ #C3 = constructor-tearoff self::A::•
+ #C4 = instantiation self::A::• <core::int*>
+ #C5 = static-tearoff self::A::bar
+ #C6 = instantiation self::A::bar <core::int*>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart.weak.outline.expect
index e5848bc..928b5e1 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart.weak.outline.expect
@@ -28,5 +28,7 @@
;
static method testBarExtraArgs() → dynamic
;
+static method method() → dynamic
+ ;
static method main() → dynamic
;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart.weak.transformed.expect
index b9ace2c..c49c929 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart.weak.transformed.expect
@@ -17,6 +17,21 @@
// testBarExtraArgs() => A<int, String>.bar; // Error.
// ^
//
+// pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:30:22: Error: Too many type arguments: 1 allowed, but 2 found.
+// Try removing the extra type arguments.
+// var fooExtraArgs = A<int, String>.foo; // Error.
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:31:22: Error: Too many type arguments: 1 allowed, but 2 found.
+// Try removing the extra type arguments.
+// var newExtraArgs = A<int, String>.new; // Error.
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:32:22: Error: Too many type arguments: 1 allowed, but 2 found.
+// Try removing the extra type arguments.
+// var barExtraArgs = A<int, String>.bar; // Error.
+// ^
+//
import self as self;
import "dart:core" as core;
@@ -29,17 +44,17 @@
return new self::A::•<self::A::bar::X%>();
}
static method testFoo() → dynamic
- return self::A::foo;
+ return #C1;
static method testFooArgs() → dynamic
- return self::A::foo<core::int>;
+ return #C2;
static method testNew() → dynamic
- return self::A::•;
+ return #C3;
static method testNewArgs() → dynamic
- return self::A::•<core::int>;
+ return #C4;
static method testBar() → dynamic
- return self::A::bar;
+ return #C5;
static method testBarArgs() → dynamic
- return self::A::bar<core::int>;
+ return #C6;
static method testFooExtraArgs() → dynamic
return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:18:23: Error: Too many type arguments: 1 allowed, but 2 found.
Try removing the extra type arguments.
@@ -55,4 +70,33 @@
Try removing the extra type arguments.
testBarExtraArgs() => A<int, String>.bar; // Error.
^";
+static method method() → dynamic {
+ <X extends core::Object? = dynamic>() → self::A<X%> foo = #C1;
+ () → self::A<core::int> fooArgs = #C2;
+ <X extends core::Object? = dynamic>() → self::A<X%> _new = #C3;
+ () → self::A<core::int> newArgs = #C4;
+ <X extends core::Object? = dynamic>() → self::A<X%> bar = #C5;
+ () → self::A<core::int> barArgs = #C6;
+ invalid-type fooExtraArgs = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:30:22: Error: Too many type arguments: 1 allowed, but 2 found.
+Try removing the extra type arguments.
+ var fooExtraArgs = A<int, String>.foo; // Error.
+ ^";
+ invalid-type newExtraArgs = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:31:22: Error: Too many type arguments: 1 allowed, but 2 found.
+Try removing the extra type arguments.
+ var newExtraArgs = A<int, String>.new; // Error.
+ ^";
+ invalid-type barExtraArgs = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/generic_tearoff_without_context.dart:32:22: Error: Too many type arguments: 1 allowed, but 2 found.
+Try removing the extra type arguments.
+ var barExtraArgs = A<int, String>.bar; // Error.
+ ^";
+}
static method main() → dynamic {}
+
+constants {
+ #C1 = constructor-tearoff self::A::foo
+ #C2 = instantiation self::A::foo <core::int*>
+ #C3 = constructor-tearoff self::A::•
+ #C4 = instantiation self::A::• <core::int*>
+ #C5 = static-tearoff self::A::bar
+ #C6 = instantiation self::A::bar <core::int*>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart.strong.expect
index 8df289d3..5edad1d 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart.strong.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart.strong.expect
@@ -46,7 +46,7 @@
}
constants {
- #C1 = tearoff self::id
- #C2 = partial-instantiation self::id <core::int>
- #C3 = partial-instantiation self::id <core::String>
+ #C1 = static-tearoff self::id
+ #C2 = instantiation self::id <core::int>
+ #C3 = instantiation self::id <core::String>
}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart.strong.transformed.expect
index 3afa4cf..f2e9fea 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart.strong.transformed.expect
@@ -46,9 +46,9 @@
}
constants {
- #C1 = tearoff self::id
- #C2 = partial-instantiation self::id <core::int>
- #C3 = partial-instantiation self::id <core::String>
+ #C1 = static-tearoff self::id
+ #C2 = instantiation self::id <core::int>
+ #C3 = instantiation self::id <core::String>
}
Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart.weak.expect
index c33a355..7061d34 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart.weak.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart.weak.expect
@@ -46,7 +46,7 @@
}
constants {
- #C1 = tearoff self::id
- #C2 = partial-instantiation self::id <core::int*>
- #C3 = partial-instantiation self::id <core::String*>
+ #C1 = static-tearoff self::id
+ #C2 = instantiation self::id <core::int*>
+ #C3 = instantiation self::id <core::String*>
}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart.weak.transformed.expect
index 9cdfa3c..8923c73 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/identical_instantiated_function_tearoffs.dart.weak.transformed.expect
@@ -46,9 +46,9 @@
}
constants {
- #C1 = tearoff self::id
- #C2 = partial-instantiation self::id <core::int*>
- #C3 = partial-instantiation self::id <core::String*>
+ #C1 = static-tearoff self::id
+ #C2 = instantiation self::id <core::int*>
+ #C3 = instantiation self::id <core::String*>
}
Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart b/pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart
new file mode 100644
index 0000000..1750b68
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart
@@ -0,0 +1,76 @@
+// 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.
+
+final bool inSoundMode = <int?>[] is! List<int>;
+
+main() {
+ print('inSoundMode: $inSoundMode');
+ testInferred();
+}
+
+class Class1 {
+ int field;
+
+ Class1(this.field);
+}
+
+abstract class Interface2 {
+ int get field;
+}
+
+class Class2 implements Interface2 {
+ final field;
+
+ Class2(this.field);
+}
+
+var Class1_new = Class1.new;
+var Class2_new = Class2.new;
+
+testInferred() {
+ var f1a = Class1.new;
+ expect(true, f1a is Class1 Function(int));
+ expect(false, f1a is Class1 Function(String));
+ var c1a = f1a(0);
+ expect(true, c1a is Class1);
+ () {
+ f1a(''); // error
+ };
+
+ dynamic f1b = Class1.new;
+ var c1b = f1b(0);
+ expect(true, c1b is Class1);
+ throws(() => f1b(''));
+
+ var f2a = Class2.new;
+ expect(true, f2a is Class2 Function(int));
+ expect(false, f2a is Class2 Function(String));
+ var c2a = f2a(0);
+ expect(true, c2a is Class2);
+ () {
+ f2a(''); // error
+ };
+
+ dynamic f2b = Class2.new;
+ var c2b = f2b(0);
+ expect(true, c2b is Class2);
+ throws(() => f2b(''));
+}
+
+expect(expected, actual) {
+ if (expected != actual) throw 'Expected $expected, actual $actual';
+}
+
+throws(Function() f, {bool inSoundModeOnly: false}) {
+ try {
+ f();
+ } catch (e) {
+ print('Thrown: $e');
+ return;
+ }
+ if (!inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw 'Expected exception';
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart.strong.expect
new file mode 100644
index 0000000..e2692d7
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart.strong.expect
@@ -0,0 +1,93 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart:38:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+// f1a(''); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart:52:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+// f2a(''); // error
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+ field core::int field;
+ constructor •(core::int field) → self::Class1
+ : self::Class1::field = field, super core::Object::•()
+ ;
+}
+abstract class Interface2 extends core::Object {
+ synthetic constructor •() → self::Interface2
+ : super core::Object::•()
+ ;
+ abstract get field() → core::int;
+}
+class Class2 extends core::Object implements self::Interface2 {
+ final field core::int field;
+ constructor •(core::int field) → self::Class2
+ : self::Class2::field = field, super core::Object::•()
+ ;
+}
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static field (core::int) → self::Class1 Class1_new = #C1;
+static field (core::int) → self::Class2 Class2_new = #C2;
+static method main() → dynamic {
+ core::print("inSoundMode: ${self::inSoundMode}");
+ self::testInferred();
+}
+static method testInferred() → dynamic {
+ (core::int) → self::Class1 f1a = #C1;
+ self::expect(true, f1a is{ForNonNullableByDefault} (core::int) → self::Class1);
+ self::expect(false, f1a is{ForNonNullableByDefault} (core::String) → self::Class1);
+ self::Class1 c1a = f1a(0){(core::int) → self::Class1};
+ self::expect(true, c1a is{ForNonNullableByDefault} self::Class1);
+ () → Null {
+ f1a(let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart:38:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+ f1a(''); // error
+ ^" in "" as{TypeError,ForNonNullableByDefault} core::int){(core::int) → self::Class1};
+ };
+ dynamic f1b = #C1;
+ dynamic c1b = f1b{dynamic}.call(0);
+ self::expect(true, c1b is{ForNonNullableByDefault} self::Class1);
+ self::throws(() → dynamic => f1b{dynamic}.call(""));
+ (core::int) → self::Class2 f2a = #C2;
+ self::expect(true, f2a is{ForNonNullableByDefault} (core::int) → self::Class2);
+ self::expect(false, f2a is{ForNonNullableByDefault} (core::String) → self::Class2);
+ self::Class2 c2a = f2a(0){(core::int) → self::Class2};
+ self::expect(true, c2a is{ForNonNullableByDefault} self::Class2);
+ () → Null {
+ f2a(let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart:52:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+ f2a(''); // error
+ ^" in "" as{TypeError,ForNonNullableByDefault} core::int){(core::int) → self::Class2};
+ };
+ dynamic f2b = #C2;
+ dynamic c2b = f2b{dynamic}.call(0);
+ self::expect(true, c2b is{ForNonNullableByDefault} self::Class2);
+ self::throws(() → dynamic => f2b{dynamic}.call(""));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C3}) → dynamic {
+ try {
+ f(){() → dynamic};
+ }
+ on core::Object catch(final core::Object e) {
+ core::print("Thrown: ${e}");
+ return;
+ }
+ if(!self::inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw "Expected exception";
+}
+
+constants {
+ #C1 = constructor-tearoff self::Class1::•
+ #C2 = constructor-tearoff self::Class2::•
+ #C3 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart.strong.transformed.expect
new file mode 100644
index 0000000..6a6db60
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart.strong.transformed.expect
@@ -0,0 +1,93 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart:38:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+// f1a(''); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart:52:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+// f2a(''); // error
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+ field core::int field;
+ constructor •(core::int field) → self::Class1
+ : self::Class1::field = field, super core::Object::•()
+ ;
+}
+abstract class Interface2 extends core::Object {
+ synthetic constructor •() → self::Interface2
+ : super core::Object::•()
+ ;
+ abstract get field() → core::int;
+}
+class Class2 extends core::Object implements self::Interface2 {
+ final field core::int field;
+ constructor •(core::int field) → self::Class2
+ : self::Class2::field = field, super core::Object::•()
+ ;
+}
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static field (core::int) → self::Class1 Class1_new = #C1;
+static field (core::int) → self::Class2 Class2_new = #C2;
+static method main() → dynamic {
+ core::print("inSoundMode: ${self::inSoundMode}");
+ self::testInferred();
+}
+static method testInferred() → dynamic {
+ (core::int) → self::Class1 f1a = #C1;
+ self::expect(true, f1a is{ForNonNullableByDefault} (core::int) → self::Class1);
+ self::expect(false, f1a is{ForNonNullableByDefault} (core::String) → self::Class1);
+ self::Class1 c1a = f1a(0){(core::int) → self::Class1};
+ self::expect(true, c1a is{ForNonNullableByDefault} self::Class1);
+ () → Null {
+ f1a(let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart:38:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+ f1a(''); // error
+ ^" in "" as{TypeError,ForNonNullableByDefault} core::int){(core::int) → self::Class1};
+ };
+ dynamic f1b = #C1;
+ dynamic c1b = f1b{dynamic}.call(0);
+ self::expect(true, c1b is{ForNonNullableByDefault} self::Class1);
+ self::throws(() → dynamic => f1b{dynamic}.call(""));
+ (core::int) → self::Class2 f2a = #C2;
+ self::expect(true, f2a is{ForNonNullableByDefault} (core::int) → self::Class2);
+ self::expect(false, f2a is{ForNonNullableByDefault} (core::String) → self::Class2);
+ self::Class2 c2a = f2a(0){(core::int) → self::Class2};
+ self::expect(true, c2a is{ForNonNullableByDefault} self::Class2);
+ () → Null {
+ f2a(let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart:52:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+ f2a(''); // error
+ ^" in "" as{TypeError,ForNonNullableByDefault} core::int){(core::int) → self::Class2};
+ };
+ dynamic f2b = #C2;
+ dynamic c2b = f2b{dynamic}.call(0);
+ self::expect(true, c2b is{ForNonNullableByDefault} self::Class2);
+ self::throws(() → dynamic => f2b{dynamic}.call(""));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C3}) → dynamic {
+ try {
+ f(){() → dynamic};
+ }
+ on core::Object catch(final core::Object e) {
+ core::print("Thrown: ${e}");
+ return;
+ }
+ if(!self::inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw "Expected exception";
+}
+
+constants {
+ #C1 = constructor-tearoff self::Class1::•
+ #C2 = constructor-tearoff self::Class2::•
+ #C3 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart.textual_outline.expect
new file mode 100644
index 0000000..94115d1
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart.textual_outline.expect
@@ -0,0 +1,18 @@
+final bool inSoundMode = <int?>[] is! List<int>;
+main() {}
+class Class1 {
+ int field;
+ Class1(this.field);
+}
+abstract class Interface2 {
+ int get field;
+}
+class Class2 implements Interface2 {
+ final field;
+ Class2(this.field);
+}
+var Class1_new = Class1.new;
+var Class2_new = Class2.new;
+testInferred() {}
+expect(expected, actual) {}
+throws(Function() f, {bool inSoundModeOnly: false}) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart.weak.expect
new file mode 100644
index 0000000..e2692d7
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart.weak.expect
@@ -0,0 +1,93 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart:38:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+// f1a(''); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart:52:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+// f2a(''); // error
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+ field core::int field;
+ constructor •(core::int field) → self::Class1
+ : self::Class1::field = field, super core::Object::•()
+ ;
+}
+abstract class Interface2 extends core::Object {
+ synthetic constructor •() → self::Interface2
+ : super core::Object::•()
+ ;
+ abstract get field() → core::int;
+}
+class Class2 extends core::Object implements self::Interface2 {
+ final field core::int field;
+ constructor •(core::int field) → self::Class2
+ : self::Class2::field = field, super core::Object::•()
+ ;
+}
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static field (core::int) → self::Class1 Class1_new = #C1;
+static field (core::int) → self::Class2 Class2_new = #C2;
+static method main() → dynamic {
+ core::print("inSoundMode: ${self::inSoundMode}");
+ self::testInferred();
+}
+static method testInferred() → dynamic {
+ (core::int) → self::Class1 f1a = #C1;
+ self::expect(true, f1a is{ForNonNullableByDefault} (core::int) → self::Class1);
+ self::expect(false, f1a is{ForNonNullableByDefault} (core::String) → self::Class1);
+ self::Class1 c1a = f1a(0){(core::int) → self::Class1};
+ self::expect(true, c1a is{ForNonNullableByDefault} self::Class1);
+ () → Null {
+ f1a(let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart:38:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+ f1a(''); // error
+ ^" in "" as{TypeError,ForNonNullableByDefault} core::int){(core::int) → self::Class1};
+ };
+ dynamic f1b = #C1;
+ dynamic c1b = f1b{dynamic}.call(0);
+ self::expect(true, c1b is{ForNonNullableByDefault} self::Class1);
+ self::throws(() → dynamic => f1b{dynamic}.call(""));
+ (core::int) → self::Class2 f2a = #C2;
+ self::expect(true, f2a is{ForNonNullableByDefault} (core::int) → self::Class2);
+ self::expect(false, f2a is{ForNonNullableByDefault} (core::String) → self::Class2);
+ self::Class2 c2a = f2a(0){(core::int) → self::Class2};
+ self::expect(true, c2a is{ForNonNullableByDefault} self::Class2);
+ () → Null {
+ f2a(let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart:52:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+ f2a(''); // error
+ ^" in "" as{TypeError,ForNonNullableByDefault} core::int){(core::int) → self::Class2};
+ };
+ dynamic f2b = #C2;
+ dynamic c2b = f2b{dynamic}.call(0);
+ self::expect(true, c2b is{ForNonNullableByDefault} self::Class2);
+ self::throws(() → dynamic => f2b{dynamic}.call(""));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C3}) → dynamic {
+ try {
+ f(){() → dynamic};
+ }
+ on core::Object catch(final core::Object e) {
+ core::print("Thrown: ${e}");
+ return;
+ }
+ if(!self::inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw "Expected exception";
+}
+
+constants {
+ #C1 = constructor-tearoff self::Class1::•
+ #C2 = constructor-tearoff self::Class2::•
+ #C3 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart.weak.outline.expect
new file mode 100644
index 0000000..73a2bca
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart.weak.outline.expect
@@ -0,0 +1,30 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+ field core::int field;
+ constructor •(core::int field) → self::Class1
+ ;
+}
+abstract class Interface2 extends core::Object {
+ synthetic constructor •() → self::Interface2
+ ;
+ abstract get field() → core::int;
+}
+class Class2 extends core::Object implements self::Interface2 {
+ final field core::int field;
+ constructor •(core::int field) → self::Class2
+ ;
+}
+static final field core::bool inSoundMode;
+static field (core::int) → self::Class1 Class1_new;
+static field (core::int) → self::Class2 Class2_new;
+static method main() → dynamic
+ ;
+static method testInferred() → dynamic
+ ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+ ;
+static method throws(() → dynamic f, {core::bool inSoundModeOnly}) → dynamic
+ ;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart.weak.transformed.expect
new file mode 100644
index 0000000..6a6db60
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart.weak.transformed.expect
@@ -0,0 +1,93 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart:38:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+// f1a(''); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart:52:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+// f2a(''); // error
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+ field core::int field;
+ constructor •(core::int field) → self::Class1
+ : self::Class1::field = field, super core::Object::•()
+ ;
+}
+abstract class Interface2 extends core::Object {
+ synthetic constructor •() → self::Interface2
+ : super core::Object::•()
+ ;
+ abstract get field() → core::int;
+}
+class Class2 extends core::Object implements self::Interface2 {
+ final field core::int field;
+ constructor •(core::int field) → self::Class2
+ : self::Class2::field = field, super core::Object::•()
+ ;
+}
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static field (core::int) → self::Class1 Class1_new = #C1;
+static field (core::int) → self::Class2 Class2_new = #C2;
+static method main() → dynamic {
+ core::print("inSoundMode: ${self::inSoundMode}");
+ self::testInferred();
+}
+static method testInferred() → dynamic {
+ (core::int) → self::Class1 f1a = #C1;
+ self::expect(true, f1a is{ForNonNullableByDefault} (core::int) → self::Class1);
+ self::expect(false, f1a is{ForNonNullableByDefault} (core::String) → self::Class1);
+ self::Class1 c1a = f1a(0){(core::int) → self::Class1};
+ self::expect(true, c1a is{ForNonNullableByDefault} self::Class1);
+ () → Null {
+ f1a(let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart:38:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+ f1a(''); // error
+ ^" in "" as{TypeError,ForNonNullableByDefault} core::int){(core::int) → self::Class1};
+ };
+ dynamic f1b = #C1;
+ dynamic c1b = f1b{dynamic}.call(0);
+ self::expect(true, c1b is{ForNonNullableByDefault} self::Class1);
+ self::throws(() → dynamic => f1b{dynamic}.call(""));
+ (core::int) → self::Class2 f2a = #C2;
+ self::expect(true, f2a is{ForNonNullableByDefault} (core::int) → self::Class2);
+ self::expect(false, f2a is{ForNonNullableByDefault} (core::String) → self::Class2);
+ self::Class2 c2a = f2a(0){(core::int) → self::Class2};
+ self::expect(true, c2a is{ForNonNullableByDefault} self::Class2);
+ () → Null {
+ f2a(let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/inferred_constructor_tear_off.dart:52:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+ f2a(''); // error
+ ^" in "" as{TypeError,ForNonNullableByDefault} core::int){(core::int) → self::Class2};
+ };
+ dynamic f2b = #C2;
+ dynamic c2b = f2b{dynamic}.call(0);
+ self::expect(true, c2b is{ForNonNullableByDefault} self::Class2);
+ self::throws(() → dynamic => f2b{dynamic}.call(""));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C3}) → dynamic {
+ try {
+ f(){() → dynamic};
+ }
+ on core::Object catch(final core::Object e) {
+ core::print("Thrown: ${e}");
+ return;
+ }
+ if(!self::inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw "Expected exception";
+}
+
+constants {
+ #C1 = constructor-tearoff self::Class1::•
+ #C2 = constructor-tearoff self::Class2::•
+ #C3 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart b/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart
new file mode 100644
index 0000000..601da2a
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart
@@ -0,0 +1,73 @@
+// 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.
+
+final bool inSoundMode = <int?>[] is! List<int>;
+
+class A<T> {}
+
+typedef F<X extends num> = A<X>;
+typedef G<Y> = A<int>;
+typedef H<X, Y> = A<X>;
+
+const f1a = A<int>.new;
+const f1b = F<int>.new;
+const A<int> Function() f1c = F.new;
+
+const g1a = A<int>.new;
+const g1b = G<String>.new;
+const A<int> Function() g1c = G.new;
+
+const h1a = A<int>.new;
+const h1b = H<int, String>.new;
+const A<int> Function() h1c = H.new;
+
+main() {
+ test<int>();
+
+ identical(f1a, f1b);
+ identical(f1a, f1c);
+
+ identical(g1a, g1b);
+ identical(g1a, g1c);
+
+ identical(h1a, h1b);
+ identical(h1a, h1c);
+}
+
+test<T extends num>() {
+ var f2a = A<T>.new;
+ var f2b = F<T>.new;
+ A<T> Function() f2c = F.new;
+
+ var g2a = A<int>.new;
+ var g2b = G<T>.new;
+ A<int> Function() g2c = G.new;
+
+ var h2a = A<T>.new;
+ var h2b = H<T, String>.new;
+ A<T> Function() h2c = H.new;
+
+ // TODO(johnniwinther): Enable these if structural equality is supported at
+ // runtime.
+ /*expect(f1a, f2a);
+ expect(f2a, f2b);
+ expect(f2a, f2c);*/
+
+ expect(g1a, g2a);
+ expect(g2a, g2b);
+ if (inSoundMode) {
+ // In weak mode type arguments of constants are weakened.
+ expect(g2a, g2c);
+ }
+
+ // TODO(johnniwinther): Enable these if structural equality is supported at
+ // runtime.
+ /*expect(h1a, h2a);
+ expect(h2a, h2b);
+ expect(h2a, h2c);*/
+}
+
+expect(expected, actual) {
+ if (expected != actual) throw 'Expected $expected, actual $actual';
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.strong.expect
new file mode 100644
index 0000000..ce055a4
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.strong.expect
@@ -0,0 +1,56 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F<X extends core::num> = self::A<X>;
+typedef G<unrelated Y extends core::Object? = dynamic> = self::A<core::int>;
+typedef H<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic> = self::A<X%>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::A<self::A::T%>
+ : super core::Object::•()
+ ;
+}
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static const field () → self::A<core::int> f1a = #C2;
+static const field () → self::A<core::int> f1b = #C2;
+static const field () → self::A<core::int> f1c = #C2;
+static const field () → self::A<core::int> g1a = #C2;
+static const field () → self::A<core::int> g1b = #C2;
+static const field () → self::A<core::int> g1c = #C2;
+static const field () → self::A<core::int> h1a = #C2;
+static const field () → self::A<core::int> h1b = #C2;
+static const field () → self::A<core::int> h1c = #C2;
+static method main() → dynamic {
+ self::test<core::int>();
+ core::identical(#C2, #C2);
+ core::identical(#C2, #C2);
+ core::identical(#C2, #C2);
+ core::identical(#C2, #C2);
+ core::identical(#C2, #C2);
+ core::identical(#C2, #C2);
+}
+static method test<T extends core::num>() → dynamic {
+ () → self::A<self::test::T> f2a = #C1<self::test::T>;
+ () → self::A<self::test::T> f2b = #C1<self::test::T>;
+ () → self::A<self::test::T> f2c = #C1<self::test::T>;
+ () → self::A<core::int> g2a = #C2;
+ () → self::A<core::int> g2b = #C2;
+ () → self::A<core::int> g2c = #C2;
+ () → self::A<self::test::T> h2a = #C1<self::test::T>;
+ () → self::A<self::test::T> h2b = #C1<self::test::T>;
+ () → self::A<self::test::T> h2c = #C1<self::test::T>;
+ self::expect(#C2, g2a);
+ self::expect(g2a, g2b);
+ if(self::inSoundMode) {
+ self::expect(g2a, g2c);
+ }
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+
+constants {
+ #C1 = constructor-tearoff self::A::•
+ #C2 = instantiation self::A::• <core::int>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.strong.transformed.expect
new file mode 100644
index 0000000..0f0953f
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.strong.transformed.expect
@@ -0,0 +1,65 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F<X extends core::num> = self::A<X>;
+typedef G<unrelated Y extends core::Object? = dynamic> = self::A<core::int>;
+typedef H<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic> = self::A<X%>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::A<self::A::T%>
+ : super core::Object::•()
+ ;
+}
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static const field () → self::A<core::int> f1a = #C2;
+static const field () → self::A<core::int> f1b = #C2;
+static const field () → self::A<core::int> f1c = #C2;
+static const field () → self::A<core::int> g1a = #C2;
+static const field () → self::A<core::int> g1b = #C2;
+static const field () → self::A<core::int> g1c = #C2;
+static const field () → self::A<core::int> h1a = #C2;
+static const field () → self::A<core::int> h1b = #C2;
+static const field () → self::A<core::int> h1c = #C2;
+static method main() → dynamic {
+ self::test<core::int>();
+ core::identical(#C2, #C2);
+ core::identical(#C2, #C2);
+ core::identical(#C2, #C2);
+ core::identical(#C2, #C2);
+ core::identical(#C2, #C2);
+ core::identical(#C2, #C2);
+}
+static method test<T extends core::num>() → dynamic {
+ () → self::A<self::test::T> f2a = #C1<self::test::T>;
+ () → self::A<self::test::T> f2b = #C1<self::test::T>;
+ () → self::A<self::test::T> f2c = #C1<self::test::T>;
+ () → self::A<core::int> g2a = #C2;
+ () → self::A<core::int> g2b = #C2;
+ () → self::A<core::int> g2c = #C2;
+ () → self::A<self::test::T> h2a = #C1<self::test::T>;
+ () → self::A<self::test::T> h2b = #C1<self::test::T>;
+ () → self::A<self::test::T> h2c = #C1<self::test::T>;
+ self::expect(#C2, g2a);
+ self::expect(g2a, g2b);
+ if(self::inSoundMode) {
+ self::expect(g2a, g2c);
+ }
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+
+constants {
+ #C1 = constructor-tearoff self::A::•
+ #C2 = instantiation self::A::• <core::int>
+}
+
+Extra constant evaluation status:
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:28:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:29:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:31:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:32:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:34:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:35:3 -> BoolConstant(true)
+Extra constant evaluation: evaluated: 33, effectively constant: 6
diff --git a/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.textual_outline.expect
new file mode 100644
index 0000000..71dbef8
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.textual_outline.expect
@@ -0,0 +1,17 @@
+final bool inSoundMode = <int?>[] is! List<int>;
+class A<T> {}
+typedef F<X extends num> = A<X>;
+typedef G<Y> = A<int>;
+typedef H<X, Y> = A<X>;
+const f1a = A<int>.new;
+const f1b = F<int>.new;
+const A<int> Function() f1c = F.new;
+const g1a = A<int>.new;
+const g1b = G<String>.new;
+const A<int> Function() g1c = G.new;
+const h1a = A<int>.new;
+const h1b = H<int, String>.new;
+const A<int> Function() h1c = H.new;
+main() {}
+test<T extends num>() {}
+expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.weak.expect
new file mode 100644
index 0000000..7f08054
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.weak.expect
@@ -0,0 +1,57 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F<X extends core::num> = self::A<X>;
+typedef G<unrelated Y extends core::Object? = dynamic> = self::A<core::int>;
+typedef H<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic> = self::A<X%>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::A<self::A::T%>
+ : super core::Object::•()
+ ;
+}
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static const field () → self::A<core::int> f1a = #C2;
+static const field () → self::A<core::int> f1b = #C2;
+static const field () → self::A<core::int> f1c = #C2;
+static const field () → self::A<core::int> g1a = #C2;
+static const field () → self::A<core::int> g1b = #C2;
+static const field () → self::A<core::int> g1c = #C3;
+static const field () → self::A<core::int> h1a = #C2;
+static const field () → self::A<core::int> h1b = #C2;
+static const field () → self::A<core::int> h1c = #C2;
+static method main() → dynamic {
+ self::test<core::int>();
+ core::identical(#C2, #C2);
+ core::identical(#C2, #C2);
+ core::identical(#C2, #C2);
+ core::identical(#C2, #C3);
+ core::identical(#C2, #C2);
+ core::identical(#C2, #C2);
+}
+static method test<T extends core::num>() → dynamic {
+ () → self::A<self::test::T> f2a = #C1<self::test::T>;
+ () → self::A<self::test::T> f2b = #C1<self::test::T>;
+ () → self::A<self::test::T> f2c = #C1<self::test::T>;
+ () → self::A<core::int> g2a = #C2;
+ () → self::A<core::int> g2b = #C2;
+ () → self::A<core::int> g2c = #C3;
+ () → self::A<self::test::T> h2a = #C1<self::test::T>;
+ () → self::A<self::test::T> h2b = #C1<self::test::T>;
+ () → self::A<self::test::T> h2c = #C1<self::test::T>;
+ self::expect(#C2, g2a);
+ self::expect(g2a, g2b);
+ if(self::inSoundMode) {
+ self::expect(g2a, g2c);
+ }
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+
+constants {
+ #C1 = constructor-tearoff self::A::•
+ #C2 = instantiation self::A::• <core::int*>
+ #C3 = instantiation self::A::• <core::int>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.weak.outline.expect
new file mode 100644
index 0000000..54daed1
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.weak.outline.expect
@@ -0,0 +1,40 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F<X extends core::num> = self::A<X>;
+typedef G<unrelated Y extends core::Object? = dynamic> = self::A<core::int>;
+typedef H<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic> = self::A<X%>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::A<self::A::T%>
+ ;
+}
+static final field core::bool inSoundMode;
+static const field () → self::A<core::int> f1a = self::A::•<core::int>;
+static const field () → self::A<core::int> f1b = self::A::•<core::int>;
+static const field () → self::A<core::int> f1c = <X extends core::num>.(self::A::•<X>)<core::int>;
+static const field () → self::A<core::int> g1a = self::A::•<core::int>;
+static const field () → self::A<core::int> g1b = self::A::•<core::int>;
+static const field () → self::A<core::int> g1c = <unrelated Y extends core::Object? = dynamic>.(self::A::•<core::int>)<dynamic>;
+static const field () → self::A<core::int> h1a = self::A::•<core::int>;
+static const field () → self::A<core::int> h1b = self::A::•<core::int>;
+static const field () → self::A<core::int> h1c = <X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic>.(self::A::•<X%>)<core::int, dynamic>;
+static method main() → dynamic
+ ;
+static method test<T extends core::num>() → dynamic
+ ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+ ;
+
+
+Extra constant evaluation status:
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:13:13 -> InstantiationConstant(A.<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:14:13 -> InstantiationConstant(A.<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:15:31 -> InstantiationConstant(A.<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:17:13 -> InstantiationConstant(A.<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:18:13 -> InstantiationConstant(A.<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:19:31 -> InstantiationConstant(A.<int>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:21:13 -> InstantiationConstant(A.<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:22:13 -> InstantiationConstant(A.<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:23:31 -> InstantiationConstant(A.<int*>)
+Extra constant evaluation: evaluated: 9, effectively constant: 9
diff --git a/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.weak.transformed.expect
new file mode 100644
index 0000000..4b8f00e
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/inferred_non_proper_rename.dart.weak.transformed.expect
@@ -0,0 +1,66 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F<X extends core::num> = self::A<X>;
+typedef G<unrelated Y extends core::Object? = dynamic> = self::A<core::int>;
+typedef H<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic> = self::A<X%>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::A<self::A::T%>
+ : super core::Object::•()
+ ;
+}
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static const field () → self::A<core::int> f1a = #C2;
+static const field () → self::A<core::int> f1b = #C2;
+static const field () → self::A<core::int> f1c = #C2;
+static const field () → self::A<core::int> g1a = #C2;
+static const field () → self::A<core::int> g1b = #C2;
+static const field () → self::A<core::int> g1c = #C3;
+static const field () → self::A<core::int> h1a = #C2;
+static const field () → self::A<core::int> h1b = #C2;
+static const field () → self::A<core::int> h1c = #C2;
+static method main() → dynamic {
+ self::test<core::int>();
+ core::identical(#C2, #C2);
+ core::identical(#C2, #C2);
+ core::identical(#C2, #C2);
+ core::identical(#C2, #C3);
+ core::identical(#C2, #C2);
+ core::identical(#C2, #C2);
+}
+static method test<T extends core::num>() → dynamic {
+ () → self::A<self::test::T> f2a = #C1<self::test::T>;
+ () → self::A<self::test::T> f2b = #C1<self::test::T>;
+ () → self::A<self::test::T> f2c = #C1<self::test::T>;
+ () → self::A<core::int> g2a = #C2;
+ () → self::A<core::int> g2b = #C2;
+ () → self::A<core::int> g2c = #C3;
+ () → self::A<self::test::T> h2a = #C1<self::test::T>;
+ () → self::A<self::test::T> h2b = #C1<self::test::T>;
+ () → self::A<self::test::T> h2c = #C1<self::test::T>;
+ self::expect(#C2, g2a);
+ self::expect(g2a, g2b);
+ if(self::inSoundMode) {
+ self::expect(g2a, g2c);
+ }
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+
+constants {
+ #C1 = constructor-tearoff self::A::•
+ #C2 = instantiation self::A::• <core::int*>
+ #C3 = instantiation self::A::• <core::int>
+}
+
+Extra constant evaluation status:
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:28:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:29:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:31:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:32:3 -> BoolConstant(false)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:34:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:35:3 -> BoolConstant(true)
+Extra constant evaluation: evaluated: 33, effectively constant: 6
diff --git a/pkg/front_end/testcases/constructor_tearoffs/instantiation.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/instantiation.dart.strong.expect
index 33ffc2b..547e506 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/instantiation.dart.strong.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/instantiation.dart.strong.expect
@@ -7,18 +7,12 @@
// Try specifying type arguments explicitly so that they conform to the bounds.
// A<dynamic> Function(String) test5() => A.foo; // Error.
// ^
-// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
-// class A<X extends num> {
-// ^
//
// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:17:40: Error: Inferred type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'A<X> Function<X extends num>(X)'.
// - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/instantiation.dart'.
// Try specifying type arguments explicitly so that they conform to the bounds.
// A<dynamic> Function(String) test6() => A.new; // Error.
// ^
-// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
-// class A<X extends num> {
-// ^
//
// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:23:41: Error: Inferred type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'A<X> Function<X extends num>(X)'.
// - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/instantiation.dart'.
@@ -38,27 +32,42 @@
return new self::A::•<self::A::bar::X>(x);
}
static method test1() → (core::num) → self::A<core::num>
- return self::A::foo<core::num>;
+ return #C2;
static method test2() → (core::int) → self::A<core::int>
- return self::A::foo<core::int>;
+ return #C3;
static method test3() → (core::num) → self::A<core::num>
- return self::A::•<core::num>;
+ return #C5;
static method test4() → (core::int) → self::A<core::int>
- return self::A::•<core::int>;
+ return #C6;
static method test5() → (core::String) → self::A<dynamic>
- return self::A::foo<core::String>;
+ return #C7;
static method test6() → (core::String) → self::A<dynamic>
- return self::A::•<core::String>;
+ return #C8;
static method test7() → (core::num) → self::A<dynamic>
- return self::A::foo<core::num>;
+ return #C2;
static method test8() → (core::num) → self::A<dynamic>
- return self::A::•<core::num>;
+ return #C5;
static method test9() → (core::num) → self::A<core::num>
- return self::A::bar<core::num>;
+ return #C10;
static method test10() → (core::int) → self::A<core::int>
- return self::A::bar<core::int>;
+ return #C11;
static method test11() → (core::String) → self::A<dynamic>
- return self::A::bar<core::String>;
+ return #C12;
static method test12() → (core::num) → self::A<dynamic>
- return self::A::bar<core::num>;
+ return #C10;
static method main() → dynamic {}
+
+constants {
+ #C1 = constructor-tearoff self::A::foo
+ #C2 = instantiation self::A::foo <core::num>
+ #C3 = instantiation self::A::foo <core::int>
+ #C4 = constructor-tearoff self::A::•
+ #C5 = instantiation self::A::• <core::num>
+ #C6 = instantiation self::A::• <core::int>
+ #C7 = instantiation self::A::foo <core::String>
+ #C8 = instantiation self::A::• <core::String>
+ #C9 = static-tearoff self::A::bar
+ #C10 = instantiation self::A::bar <core::num>
+ #C11 = instantiation self::A::bar <core::int>
+ #C12 = instantiation self::A::bar <core::String>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/instantiation.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/instantiation.dart.strong.transformed.expect
index 3bcaa2b..547e506 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/instantiation.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/instantiation.dart.strong.transformed.expect
@@ -2,37 +2,23 @@
//
// Problems in library:
//
-// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:10:35: Error: Getter not found: 'foo'.
-// A<num> Function(num) test1() => A.foo; // Ok.
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:11:35: Error: Getter not found: 'foo'.
-// A<int> Function(int) test2() => A.foo; // Ok.
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:12:35: Error: Getter not found: 'new'.
-// A<num> Function(num) test3() => A.new; // Ok.
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:13:35: Error: Getter not found: 'new'.
-// A<int> Function(int) test4() => A.new; // Ok.
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:15:42: Error: Getter not found: 'foo'.
+// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:16:40: Error: Inferred type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'A<X> Function<X extends num>(X)'.
+// - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/instantiation.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
// A<dynamic> Function(String) test5() => A.foo; // Error.
-// ^^^
+// ^
//
-// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:16:42: Error: Getter not found: 'new'.
+// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:17:40: Error: Inferred type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'A<X> Function<X extends num>(X)'.
+// - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/instantiation.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
// A<dynamic> Function(String) test6() => A.new; // Error.
-// ^^^
+// ^
//
-// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:17:44: Error: Getter not found: 'foo'.
-// A<dynamic> Function(num) test7() => A<num>.foo; // Error.
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:18:44: Error: Getter not found: 'new'.
-// A<dynamic> Function(num) test8() => A<num>.new; // Error.
-// ^^^
+// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:23:41: Error: Inferred type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'A<X> Function<X extends num>(X)'.
+// - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/instantiation.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// A<dynamic> Function(String) test11() => A.bar; // Error.
+// ^
//
import self as self;
import "dart:core" as core;
@@ -42,37 +28,46 @@
: super core::Object::•() {}
constructor •(self::A::X x) → self::A<self::A::X>
: super core::Object::•() {}
+ static factory bar<X extends core::num>(self::A::bar::X x) → self::A<self::A::bar::X>
+ return new self::A::•<self::A::bar::X>(x);
}
static method test1() → (core::num) → self::A<core::num>
- return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:10:35: Error: Getter not found: 'foo'.
-A<num> Function(num) test1() => A.foo; // Ok.
- ^^^";
+ return #C2;
static method test2() → (core::int) → self::A<core::int>
- return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:11:35: Error: Getter not found: 'foo'.
-A<int> Function(int) test2() => A.foo; // Ok.
- ^^^";
+ return #C3;
static method test3() → (core::num) → self::A<core::num>
- return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:12:35: Error: Getter not found: 'new'.
-A<num> Function(num) test3() => A.new; // Ok.
- ^^^";
+ return #C5;
static method test4() → (core::int) → self::A<core::int>
- return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:13:35: Error: Getter not found: 'new'.
-A<int> Function(int) test4() => A.new; // Ok.
- ^^^";
+ return #C6;
static method test5() → (core::String) → self::A<dynamic>
- return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:15:42: Error: Getter not found: 'foo'.
-A<dynamic> Function(String) test5() => A.foo; // Error.
- ^^^";
+ return #C7;
static method test6() → (core::String) → self::A<dynamic>
- return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:16:42: Error: Getter not found: 'new'.
-A<dynamic> Function(String) test6() => A.new; // Error.
- ^^^";
+ return #C8;
static method test7() → (core::num) → self::A<dynamic>
- return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:17:44: Error: Getter not found: 'foo'.
-A<dynamic> Function(num) test7() => A<num>.foo; // Error.
- ^^^";
+ return #C2;
static method test8() → (core::num) → self::A<dynamic>
- return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:18:44: Error: Getter not found: 'new'.
-A<dynamic> Function(num) test8() => A<num>.new; // Error.
- ^^^";
+ return #C5;
+static method test9() → (core::num) → self::A<core::num>
+ return #C10;
+static method test10() → (core::int) → self::A<core::int>
+ return #C11;
+static method test11() → (core::String) → self::A<dynamic>
+ return #C12;
+static method test12() → (core::num) → self::A<dynamic>
+ return #C10;
static method main() → dynamic {}
+
+constants {
+ #C1 = constructor-tearoff self::A::foo
+ #C2 = instantiation self::A::foo <core::num>
+ #C3 = instantiation self::A::foo <core::int>
+ #C4 = constructor-tearoff self::A::•
+ #C5 = instantiation self::A::• <core::num>
+ #C6 = instantiation self::A::• <core::int>
+ #C7 = instantiation self::A::foo <core::String>
+ #C8 = instantiation self::A::• <core::String>
+ #C9 = static-tearoff self::A::bar
+ #C10 = instantiation self::A::bar <core::num>
+ #C11 = instantiation self::A::bar <core::int>
+ #C12 = instantiation self::A::bar <core::String>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/instantiation.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/instantiation.dart.weak.expect
index 33ffc2b..8f0ed57 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/instantiation.dart.weak.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/instantiation.dart.weak.expect
@@ -7,18 +7,12 @@
// Try specifying type arguments explicitly so that they conform to the bounds.
// A<dynamic> Function(String) test5() => A.foo; // Error.
// ^
-// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
-// class A<X extends num> {
-// ^
//
// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:17:40: Error: Inferred type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'A<X> Function<X extends num>(X)'.
// - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/instantiation.dart'.
// Try specifying type arguments explicitly so that they conform to the bounds.
// A<dynamic> Function(String) test6() => A.new; // Error.
// ^
-// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
-// class A<X extends num> {
-// ^
//
// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:23:41: Error: Inferred type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'A<X> Function<X extends num>(X)'.
// - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/instantiation.dart'.
@@ -38,27 +32,42 @@
return new self::A::•<self::A::bar::X>(x);
}
static method test1() → (core::num) → self::A<core::num>
- return self::A::foo<core::num>;
+ return #C2;
static method test2() → (core::int) → self::A<core::int>
- return self::A::foo<core::int>;
+ return #C3;
static method test3() → (core::num) → self::A<core::num>
- return self::A::•<core::num>;
+ return #C5;
static method test4() → (core::int) → self::A<core::int>
- return self::A::•<core::int>;
+ return #C6;
static method test5() → (core::String) → self::A<dynamic>
- return self::A::foo<core::String>;
+ return #C7;
static method test6() → (core::String) → self::A<dynamic>
- return self::A::•<core::String>;
+ return #C8;
static method test7() → (core::num) → self::A<dynamic>
- return self::A::foo<core::num>;
+ return #C2;
static method test8() → (core::num) → self::A<dynamic>
- return self::A::•<core::num>;
+ return #C5;
static method test9() → (core::num) → self::A<core::num>
- return self::A::bar<core::num>;
+ return #C10;
static method test10() → (core::int) → self::A<core::int>
- return self::A::bar<core::int>;
+ return #C11;
static method test11() → (core::String) → self::A<dynamic>
- return self::A::bar<core::String>;
+ return #C12;
static method test12() → (core::num) → self::A<dynamic>
- return self::A::bar<core::num>;
+ return #C10;
static method main() → dynamic {}
+
+constants {
+ #C1 = constructor-tearoff self::A::foo
+ #C2 = instantiation self::A::foo <core::num*>
+ #C3 = instantiation self::A::foo <core::int*>
+ #C4 = constructor-tearoff self::A::•
+ #C5 = instantiation self::A::• <core::num*>
+ #C6 = instantiation self::A::• <core::int*>
+ #C7 = instantiation self::A::foo <core::String*>
+ #C8 = instantiation self::A::• <core::String*>
+ #C9 = static-tearoff self::A::bar
+ #C10 = instantiation self::A::bar <core::num*>
+ #C11 = instantiation self::A::bar <core::int*>
+ #C12 = instantiation self::A::bar <core::String*>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/instantiation.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/instantiation.dart.weak.transformed.expect
index 3bcaa2b..8f0ed57 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/instantiation.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/instantiation.dart.weak.transformed.expect
@@ -2,37 +2,23 @@
//
// Problems in library:
//
-// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:10:35: Error: Getter not found: 'foo'.
-// A<num> Function(num) test1() => A.foo; // Ok.
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:11:35: Error: Getter not found: 'foo'.
-// A<int> Function(int) test2() => A.foo; // Ok.
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:12:35: Error: Getter not found: 'new'.
-// A<num> Function(num) test3() => A.new; // Ok.
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:13:35: Error: Getter not found: 'new'.
-// A<int> Function(int) test4() => A.new; // Ok.
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:15:42: Error: Getter not found: 'foo'.
+// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:16:40: Error: Inferred type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'A<X> Function<X extends num>(X)'.
+// - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/instantiation.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
// A<dynamic> Function(String) test5() => A.foo; // Error.
-// ^^^
+// ^
//
-// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:16:42: Error: Getter not found: 'new'.
+// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:17:40: Error: Inferred type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'A<X> Function<X extends num>(X)'.
+// - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/instantiation.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
// A<dynamic> Function(String) test6() => A.new; // Error.
-// ^^^
+// ^
//
-// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:17:44: Error: Getter not found: 'foo'.
-// A<dynamic> Function(num) test7() => A<num>.foo; // Error.
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:18:44: Error: Getter not found: 'new'.
-// A<dynamic> Function(num) test8() => A<num>.new; // Error.
-// ^^^
+// pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:23:41: Error: Inferred type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'A<X> Function<X extends num>(X)'.
+// - 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/instantiation.dart'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// A<dynamic> Function(String) test11() => A.bar; // Error.
+// ^
//
import self as self;
import "dart:core" as core;
@@ -42,37 +28,46 @@
: super core::Object::•() {}
constructor •(self::A::X x) → self::A<self::A::X>
: super core::Object::•() {}
+ static factory bar<X extends core::num>(self::A::bar::X x) → self::A<self::A::bar::X>
+ return new self::A::•<self::A::bar::X>(x);
}
static method test1() → (core::num) → self::A<core::num>
- return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:10:35: Error: Getter not found: 'foo'.
-A<num> Function(num) test1() => A.foo; // Ok.
- ^^^";
+ return #C2;
static method test2() → (core::int) → self::A<core::int>
- return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:11:35: Error: Getter not found: 'foo'.
-A<int> Function(int) test2() => A.foo; // Ok.
- ^^^";
+ return #C3;
static method test3() → (core::num) → self::A<core::num>
- return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:12:35: Error: Getter not found: 'new'.
-A<num> Function(num) test3() => A.new; // Ok.
- ^^^";
+ return #C5;
static method test4() → (core::int) → self::A<core::int>
- return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:13:35: Error: Getter not found: 'new'.
-A<int> Function(int) test4() => A.new; // Ok.
- ^^^";
+ return #C6;
static method test5() → (core::String) → self::A<dynamic>
- return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:15:42: Error: Getter not found: 'foo'.
-A<dynamic> Function(String) test5() => A.foo; // Error.
- ^^^";
+ return #C7;
static method test6() → (core::String) → self::A<dynamic>
- return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:16:42: Error: Getter not found: 'new'.
-A<dynamic> Function(String) test6() => A.new; // Error.
- ^^^";
+ return #C8;
static method test7() → (core::num) → self::A<dynamic>
- return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:17:44: Error: Getter not found: 'foo'.
-A<dynamic> Function(num) test7() => A<num>.foo; // Error.
- ^^^";
+ return #C2;
static method test8() → (core::num) → self::A<dynamic>
- return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/instantiation.dart:18:44: Error: Getter not found: 'new'.
-A<dynamic> Function(num) test8() => A<num>.new; // Error.
- ^^^";
+ return #C5;
+static method test9() → (core::num) → self::A<core::num>
+ return #C10;
+static method test10() → (core::int) → self::A<core::int>
+ return #C11;
+static method test11() → (core::String) → self::A<dynamic>
+ return #C12;
+static method test12() → (core::num) → self::A<dynamic>
+ return #C10;
static method main() → dynamic {}
+
+constants {
+ #C1 = constructor-tearoff self::A::foo
+ #C2 = instantiation self::A::foo <core::num*>
+ #C3 = instantiation self::A::foo <core::int*>
+ #C4 = constructor-tearoff self::A::•
+ #C5 = instantiation self::A::• <core::num*>
+ #C6 = instantiation self::A::• <core::int*>
+ #C7 = instantiation self::A::foo <core::String*>
+ #C8 = instantiation self::A::• <core::String*>
+ #C9 = static-tearoff self::A::bar
+ #C10 = instantiation self::A::bar <core::num*>
+ #C11 = instantiation self::A::bar <core::int*>
+ #C12 = instantiation self::A::bar <core::String*>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off.dart.strong.expect
index ecc6126..2dac5ed 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off.dart.strong.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off.dart.strong.expect
@@ -220,11 +220,11 @@
constants {
#C1 = null
- #C2 = tearoff self::Class1::_#new#tearOff
- #C3 = tearoff self::Class2::_#named#tearOff
- #C4 = tearoff self::Class3::_#new#tearOff
- #C5 = tearoff self::Class4::_#new#tearOff
- #C6 = tearoff self::Class5::_#new#tearOff
- #C7 = tearoff self::Class6::_#new#tearOff
+ #C2 = static-tearoff self::Class1::_#new#tearOff
+ #C3 = static-tearoff self::Class2::_#named#tearOff
+ #C4 = static-tearoff self::Class3::_#new#tearOff
+ #C5 = static-tearoff self::Class4::_#new#tearOff
+ #C6 = static-tearoff self::Class5::_#new#tearOff
+ #C7 = static-tearoff self::Class6::_#new#tearOff
#C8 = false
}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off.dart.strong.transformed.expect
index 49aa5ce..67d30a7 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off.dart.strong.transformed.expect
@@ -220,11 +220,11 @@
constants {
#C1 = null
- #C2 = tearoff self::Class1::_#new#tearOff
- #C3 = tearoff self::Class2::_#named#tearOff
- #C4 = tearoff self::Class3::_#new#tearOff
- #C5 = tearoff self::Class4::_#new#tearOff
- #C6 = tearoff self::Class5::_#new#tearOff
- #C7 = tearoff self::Class6::_#new#tearOff
+ #C2 = static-tearoff self::Class1::_#new#tearOff
+ #C3 = static-tearoff self::Class2::_#named#tearOff
+ #C4 = static-tearoff self::Class3::_#new#tearOff
+ #C5 = static-tearoff self::Class4::_#new#tearOff
+ #C6 = static-tearoff self::Class5::_#new#tearOff
+ #C7 = static-tearoff self::Class6::_#new#tearOff
#C8 = false
}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off.dart.weak.expect
index ecc6126..2dac5ed 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off.dart.weak.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off.dart.weak.expect
@@ -220,11 +220,11 @@
constants {
#C1 = null
- #C2 = tearoff self::Class1::_#new#tearOff
- #C3 = tearoff self::Class2::_#named#tearOff
- #C4 = tearoff self::Class3::_#new#tearOff
- #C5 = tearoff self::Class4::_#new#tearOff
- #C6 = tearoff self::Class5::_#new#tearOff
- #C7 = tearoff self::Class6::_#new#tearOff
+ #C2 = static-tearoff self::Class1::_#new#tearOff
+ #C3 = static-tearoff self::Class2::_#named#tearOff
+ #C4 = static-tearoff self::Class3::_#new#tearOff
+ #C5 = static-tearoff self::Class4::_#new#tearOff
+ #C6 = static-tearoff self::Class5::_#new#tearOff
+ #C7 = static-tearoff self::Class6::_#new#tearOff
#C8 = false
}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off.dart.weak.transformed.expect
index 49aa5ce..67d30a7 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off.dart.weak.transformed.expect
@@ -220,11 +220,11 @@
constants {
#C1 = null
- #C2 = tearoff self::Class1::_#new#tearOff
- #C3 = tearoff self::Class2::_#named#tearOff
- #C4 = tearoff self::Class3::_#new#tearOff
- #C5 = tearoff self::Class4::_#new#tearOff
- #C6 = tearoff self::Class5::_#new#tearOff
- #C7 = tearoff self::Class6::_#new#tearOff
+ #C2 = static-tearoff self::Class1::_#new#tearOff
+ #C3 = static-tearoff self::Class2::_#named#tearOff
+ #C4 = static-tearoff self::Class3::_#new#tearOff
+ #C5 = static-tearoff self::Class4::_#new#tearOff
+ #C6 = static-tearoff self::Class5::_#new#tearOff
+ #C7 = static-tearoff self::Class6::_#new#tearOff
#C8 = false
}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart
index 80b72e45..dda860c 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart
@@ -15,6 +15,12 @@
Class1([this.field = 42]);
}
+class Class2 {
+ final int field;
+
+ Class2({this.field: 42});
+}
+
void testDefaultValues() {
var f1a = Class1.new;
var c1a = f1a();
@@ -31,6 +37,22 @@
var c1d = f1b(87);
expect(87, c1d.field);
throws(() => f1b(42, 87));
+
+ var f2a = Class2.new;
+ var c2a = f2a();
+ expect(42, c2a.field);
+ var c2b = f2a(field: 87);
+ expect(87, c2b.field);
+ () {
+ f2a(87); // error
+ };
+
+ dynamic f2b = Class2.new;
+ var c2c = f2b();
+ expect(42, c2c.field);
+ var c2d = f2b(field: 87);
+ expect(87, c2d.field);
+ throws(() => f2b(87));
}
expect(expected, actual) {
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.strong.expect
index 9c7ebb5..066aa724 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.strong.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.strong.expect
@@ -2,11 +2,16 @@
//
// Problems in library:
//
-// pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart:25:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart:31:8: Error: Too many positional arguments: 1 allowed, but 2 found.
// Try removing the extra positional arguments.
// f1a(42, 87); // error
// ^
//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart:47:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+// f2a(87); // error
+// ^
+//
import self as self;
import "dart:core" as core;
@@ -18,6 +23,14 @@
static method _#new#tearOff([core::int field = #C1]) → self::Class1
return new self::Class1::•(field);
}
+class Class2 extends core::Object {
+ final field core::int field;
+ constructor •({core::int field = #C1}) → self::Class2
+ : self::Class2::field = field, super core::Object::•()
+ ;
+ static method _#new#tearOff({core::int field = #C1}) → self::Class2
+ return new self::Class2::•(field: field);
+}
static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
static method main() → dynamic {
core::print("inSoundMode: ${self::inSoundMode}");
@@ -30,7 +43,7 @@
self::Class1 c1b = f1a(87){([core::int]) → self::Class1};
self::expect(87, c1b.{self::Class1::field}{core::int});
() → Null {
- let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart:25:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+ let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart:31:8: Error: Too many positional arguments: 1 allowed, but 2 found.
Try removing the extra positional arguments.
f1a(42, 87); // error
^" in f1a{<inapplicable>}.(42, 87);
@@ -41,12 +54,29 @@
dynamic c1d = f1b{dynamic}.call(87);
self::expect(87, c1d{dynamic}.field);
self::throws(() → dynamic => f1b{dynamic}.call(42, 87));
+ ({field: core::int}) → self::Class2 f2a = #C3;
+ self::Class2 c2a = f2a(){({field: core::int}) → self::Class2};
+ self::expect(42, c2a.{self::Class2::field}{core::int});
+ self::Class2 c2b = f2a(field: 87){({field: core::int}) → self::Class2};
+ self::expect(87, c2b.{self::Class2::field}{core::int});
+ () → Null {
+ let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart:47:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+ f2a(87); // error
+ ^" in f2a{<inapplicable>}.(87);
+ };
+ dynamic f2b = #C3;
+ dynamic c2c = f2b{dynamic}.call();
+ self::expect(42, c2c{dynamic}.field);
+ dynamic c2d = f2b{dynamic}.call(field: 87);
+ self::expect(87, c2d{dynamic}.field);
+ self::throws(() → dynamic => f2b{dynamic}.call(87));
}
static method expect(dynamic expected, dynamic actual) → dynamic {
if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
throw "Expected ${expected}, actual ${actual}";
}
-static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C3}) → dynamic {
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C4}) → dynamic {
try {
f(){() → dynamic};
}
@@ -62,6 +92,7 @@
constants {
#C1 = 42
- #C2 = tearoff self::Class1::_#new#tearOff
- #C3 = false
+ #C2 = static-tearoff self::Class1::_#new#tearOff
+ #C3 = static-tearoff self::Class2::_#new#tearOff
+ #C4 = false
}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.strong.transformed.expect
index dfe46c0..c76d239 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.strong.transformed.expect
@@ -2,11 +2,16 @@
//
// Problems in library:
//
-// pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart:25:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart:31:8: Error: Too many positional arguments: 1 allowed, but 2 found.
// Try removing the extra positional arguments.
// f1a(42, 87); // error
// ^
//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart:47:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+// f2a(87); // error
+// ^
+//
import self as self;
import "dart:core" as core;
@@ -18,6 +23,14 @@
static method _#new#tearOff([core::int field = #C1]) → self::Class1
return new self::Class1::•(field);
}
+class Class2 extends core::Object {
+ final field core::int field;
+ constructor •({core::int field = #C1}) → self::Class2
+ : self::Class2::field = field, super core::Object::•()
+ ;
+ static method _#new#tearOff({core::int field = #C1}) → self::Class2
+ return new self::Class2::•(field: field);
+}
static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
static method main() → dynamic {
core::print("inSoundMode: ${self::inSoundMode}");
@@ -30,7 +43,7 @@
self::Class1 c1b = f1a(87){([core::int]) → self::Class1};
self::expect(87, c1b.{self::Class1::field}{core::int});
() → Null {
- let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart:25:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+ let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart:31:8: Error: Too many positional arguments: 1 allowed, but 2 found.
Try removing the extra positional arguments.
f1a(42, 87); // error
^" in f1a{<inapplicable>}.(42, 87);
@@ -41,12 +54,29 @@
dynamic c1d = f1b{dynamic}.call(87);
self::expect(87, c1d{dynamic}.field);
self::throws(() → dynamic => f1b{dynamic}.call(42, 87));
+ ({field: core::int}) → self::Class2 f2a = #C3;
+ self::Class2 c2a = f2a(){({field: core::int}) → self::Class2};
+ self::expect(42, c2a.{self::Class2::field}{core::int});
+ self::Class2 c2b = f2a(field: 87){({field: core::int}) → self::Class2};
+ self::expect(87, c2b.{self::Class2::field}{core::int});
+ () → Null {
+ let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart:47:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+ f2a(87); // error
+ ^" in f2a{<inapplicable>}.(87);
+ };
+ dynamic f2b = #C3;
+ dynamic c2c = f2b{dynamic}.call();
+ self::expect(42, c2c{dynamic}.field);
+ dynamic c2d = f2b{dynamic}.call(field: 87);
+ self::expect(87, c2d{dynamic}.field);
+ self::throws(() → dynamic => f2b{dynamic}.call(87));
}
static method expect(dynamic expected, dynamic actual) → dynamic {
if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
throw "Expected ${expected}, actual ${actual}";
}
-static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C3}) → dynamic {
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C4}) → dynamic {
try {
f(){() → dynamic};
}
@@ -62,6 +92,7 @@
constants {
#C1 = 42
- #C2 = tearoff self::Class1::_#new#tearOff
- #C3 = false
+ #C2 = static-tearoff self::Class1::_#new#tearOff
+ #C3 = static-tearoff self::Class2::_#new#tearOff
+ #C4 = false
}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.textual_outline.expect
index cd95744..8aff8da 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.textual_outline.expect
@@ -6,6 +6,11 @@
Class1([this.field = 42]);
}
+class Class2 {
+ final int field;
+ Class2({this.field: 42});
+}
+
void testDefaultValues() {}
expect(expected, actual) {}
throws(Function() f, {bool inSoundModeOnly: false}) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.textual_outline_modelled.expect
index 0426153..ecb692c 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.textual_outline_modelled.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.textual_outline_modelled.expect
@@ -3,6 +3,11 @@
final int field;
}
+class Class2 {
+ Class2({this.field: 42});
+ final int field;
+}
+
expect(expected, actual) {}
final bool inSoundMode = <int?>[] is! List<int>;
main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.weak.expect
index 9c7ebb5..066aa724 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.weak.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.weak.expect
@@ -2,11 +2,16 @@
//
// Problems in library:
//
-// pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart:25:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart:31:8: Error: Too many positional arguments: 1 allowed, but 2 found.
// Try removing the extra positional arguments.
// f1a(42, 87); // error
// ^
//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart:47:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+// f2a(87); // error
+// ^
+//
import self as self;
import "dart:core" as core;
@@ -18,6 +23,14 @@
static method _#new#tearOff([core::int field = #C1]) → self::Class1
return new self::Class1::•(field);
}
+class Class2 extends core::Object {
+ final field core::int field;
+ constructor •({core::int field = #C1}) → self::Class2
+ : self::Class2::field = field, super core::Object::•()
+ ;
+ static method _#new#tearOff({core::int field = #C1}) → self::Class2
+ return new self::Class2::•(field: field);
+}
static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
static method main() → dynamic {
core::print("inSoundMode: ${self::inSoundMode}");
@@ -30,7 +43,7 @@
self::Class1 c1b = f1a(87){([core::int]) → self::Class1};
self::expect(87, c1b.{self::Class1::field}{core::int});
() → Null {
- let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart:25:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+ let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart:31:8: Error: Too many positional arguments: 1 allowed, but 2 found.
Try removing the extra positional arguments.
f1a(42, 87); // error
^" in f1a{<inapplicable>}.(42, 87);
@@ -41,12 +54,29 @@
dynamic c1d = f1b{dynamic}.call(87);
self::expect(87, c1d{dynamic}.field);
self::throws(() → dynamic => f1b{dynamic}.call(42, 87));
+ ({field: core::int}) → self::Class2 f2a = #C3;
+ self::Class2 c2a = f2a(){({field: core::int}) → self::Class2};
+ self::expect(42, c2a.{self::Class2::field}{core::int});
+ self::Class2 c2b = f2a(field: 87){({field: core::int}) → self::Class2};
+ self::expect(87, c2b.{self::Class2::field}{core::int});
+ () → Null {
+ let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart:47:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+ f2a(87); // error
+ ^" in f2a{<inapplicable>}.(87);
+ };
+ dynamic f2b = #C3;
+ dynamic c2c = f2b{dynamic}.call();
+ self::expect(42, c2c{dynamic}.field);
+ dynamic c2d = f2b{dynamic}.call(field: 87);
+ self::expect(87, c2d{dynamic}.field);
+ self::throws(() → dynamic => f2b{dynamic}.call(87));
}
static method expect(dynamic expected, dynamic actual) → dynamic {
if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
throw "Expected ${expected}, actual ${actual}";
}
-static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C3}) → dynamic {
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C4}) → dynamic {
try {
f(){() → dynamic};
}
@@ -62,6 +92,7 @@
constants {
#C1 = 42
- #C2 = tearoff self::Class1::_#new#tearOff
- #C3 = false
+ #C2 = static-tearoff self::Class1::_#new#tearOff
+ #C3 = static-tearoff self::Class2::_#new#tearOff
+ #C4 = false
}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.weak.outline.expect
index 7554ec1..128018d 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.weak.outline.expect
@@ -9,6 +9,13 @@
static method _#new#tearOff([core::int field]) → self::Class1
return new self::Class1::•(field);
}
+class Class2 extends core::Object {
+ final field core::int field;
+ constructor •({core::int field}) → self::Class2
+ ;
+ static method _#new#tearOff({core::int field}) → self::Class2
+ return new self::Class2::•(field: field);
+}
static final field core::bool inSoundMode;
static method main() → dynamic
;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.weak.transformed.expect
index dfe46c0..c76d239 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart.weak.transformed.expect
@@ -2,11 +2,16 @@
//
// Problems in library:
//
-// pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart:25:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart:31:8: Error: Too many positional arguments: 1 allowed, but 2 found.
// Try removing the extra positional arguments.
// f1a(42, 87); // error
// ^
//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart:47:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+// f2a(87); // error
+// ^
+//
import self as self;
import "dart:core" as core;
@@ -18,6 +23,14 @@
static method _#new#tearOff([core::int field = #C1]) → self::Class1
return new self::Class1::•(field);
}
+class Class2 extends core::Object {
+ final field core::int field;
+ constructor •({core::int field = #C1}) → self::Class2
+ : self::Class2::field = field, super core::Object::•()
+ ;
+ static method _#new#tearOff({core::int field = #C1}) → self::Class2
+ return new self::Class2::•(field: field);
+}
static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
static method main() → dynamic {
core::print("inSoundMode: ${self::inSoundMode}");
@@ -30,7 +43,7 @@
self::Class1 c1b = f1a(87){([core::int]) → self::Class1};
self::expect(87, c1b.{self::Class1::field}{core::int});
() → Null {
- let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart:25:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+ let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart:31:8: Error: Too many positional arguments: 1 allowed, but 2 found.
Try removing the extra positional arguments.
f1a(42, 87); // error
^" in f1a{<inapplicable>}.(42, 87);
@@ -41,12 +54,29 @@
dynamic c1d = f1b{dynamic}.call(87);
self::expect(87, c1d{dynamic}.field);
self::throws(() → dynamic => f1b{dynamic}.call(42, 87));
+ ({field: core::int}) → self::Class2 f2a = #C3;
+ self::Class2 c2a = f2a(){({field: core::int}) → self::Class2};
+ self::expect(42, c2a.{self::Class2::field}{core::int});
+ self::Class2 c2b = f2a(field: 87){({field: core::int}) → self::Class2};
+ self::expect(87, c2b.{self::Class2::field}{core::int});
+ () → Null {
+ let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_default_values.dart:47:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+ f2a(87); // error
+ ^" in f2a{<inapplicable>}.(87);
+ };
+ dynamic f2b = #C3;
+ dynamic c2c = f2b{dynamic}.call();
+ self::expect(42, c2c{dynamic}.field);
+ dynamic c2d = f2b{dynamic}.call(field: 87);
+ self::expect(87, c2d{dynamic}.field);
+ self::throws(() → dynamic => f2b{dynamic}.call(87));
}
static method expect(dynamic expected, dynamic actual) → dynamic {
if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
throw "Expected ${expected}, actual ${actual}";
}
-static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C3}) → dynamic {
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C4}) → dynamic {
try {
f(){() → dynamic};
}
@@ -62,6 +92,7 @@
constants {
#C1 = 42
- #C2 = tearoff self::Class1::_#new#tearOff
- #C3 = false
+ #C2 = static-tearoff self::Class1::_#new#tearOff
+ #C3 = static-tearoff self::Class2::_#new#tearOff
+ #C4 = false
}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart
new file mode 100644
index 0000000..d268773
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart
@@ -0,0 +1,7 @@
+// 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.
+
+part 'constructor_tear_off_uri_part.dart';
+
+main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.strong.expect
new file mode 100644
index 0000000..007285e
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.strong.expect
@@ -0,0 +1,31 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri_part.dart:8:27: Error: A value of type 'Class Function()' can't be assigned to a variable of type 'Class Function(int)'.
+// - 'Class' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart'.
+// Class Function(int) f = Class.new;
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+part constructor_tear_off_uri_part.dart;
+class Class extends core::Object { // from org-dartlang-testcase:///constructor_tear_off_uri_part.dart
+ synthetic constructor •() → self::Class
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff() → self::Class
+ return new self::Class::•();
+}
+static method main() → dynamic {}
+static method /* from org-dartlang-testcase:///constructor_tear_off_uri_part.dart */ test() → dynamic {
+ (core::int) → self::Class f = let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri_part.dart:8:27: Error: A value of type 'Class Function()' can't be assigned to a variable of type 'Class Function(int)'.
+ - 'Class' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart'.
+ Class Function(int) f = Class.new;
+ ^" in (#C1) as{TypeError,ForNonNullableByDefault} (core::int) → self::Class;
+}
+
+constants {
+ #C1 = static-tearoff self::Class::_#new#tearOff
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.strong.transformed.expect
new file mode 100644
index 0000000..007285e
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.strong.transformed.expect
@@ -0,0 +1,31 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri_part.dart:8:27: Error: A value of type 'Class Function()' can't be assigned to a variable of type 'Class Function(int)'.
+// - 'Class' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart'.
+// Class Function(int) f = Class.new;
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+part constructor_tear_off_uri_part.dart;
+class Class extends core::Object { // from org-dartlang-testcase:///constructor_tear_off_uri_part.dart
+ synthetic constructor •() → self::Class
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff() → self::Class
+ return new self::Class::•();
+}
+static method main() → dynamic {}
+static method /* from org-dartlang-testcase:///constructor_tear_off_uri_part.dart */ test() → dynamic {
+ (core::int) → self::Class f = let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri_part.dart:8:27: Error: A value of type 'Class Function()' can't be assigned to a variable of type 'Class Function(int)'.
+ - 'Class' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart'.
+ Class Function(int) f = Class.new;
+ ^" in (#C1) as{TypeError,ForNonNullableByDefault} (core::int) → self::Class;
+}
+
+constants {
+ #C1 = static-tearoff self::Class::_#new#tearOff
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.textual_outline.expect
new file mode 100644
index 0000000..428e3bc
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.textual_outline.expect
@@ -0,0 +1,3 @@
+part 'constructor_tear_off_uri_part.dart';
+
+main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..428e3bc
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.textual_outline_modelled.expect
@@ -0,0 +1,3 @@
+part 'constructor_tear_off_uri_part.dart';
+
+main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.weak.expect
new file mode 100644
index 0000000..007285e
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.weak.expect
@@ -0,0 +1,31 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri_part.dart:8:27: Error: A value of type 'Class Function()' can't be assigned to a variable of type 'Class Function(int)'.
+// - 'Class' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart'.
+// Class Function(int) f = Class.new;
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+part constructor_tear_off_uri_part.dart;
+class Class extends core::Object { // from org-dartlang-testcase:///constructor_tear_off_uri_part.dart
+ synthetic constructor •() → self::Class
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff() → self::Class
+ return new self::Class::•();
+}
+static method main() → dynamic {}
+static method /* from org-dartlang-testcase:///constructor_tear_off_uri_part.dart */ test() → dynamic {
+ (core::int) → self::Class f = let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri_part.dart:8:27: Error: A value of type 'Class Function()' can't be assigned to a variable of type 'Class Function(int)'.
+ - 'Class' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart'.
+ Class Function(int) f = Class.new;
+ ^" in (#C1) as{TypeError,ForNonNullableByDefault} (core::int) → self::Class;
+}
+
+constants {
+ #C1 = static-tearoff self::Class::_#new#tearOff
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.weak.outline.expect
new file mode 100644
index 0000000..90a7e36
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.weak.outline.expect
@@ -0,0 +1,15 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+part constructor_tear_off_uri_part.dart;
+class Class extends core::Object { // from org-dartlang-testcase:///constructor_tear_off_uri_part.dart
+ synthetic constructor •() → self::Class
+ ;
+ static method _#new#tearOff() → self::Class
+ return new self::Class::•();
+}
+static method main() → dynamic
+ ;
+static method /* from org-dartlang-testcase:///constructor_tear_off_uri_part.dart */ test() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.weak.transformed.expect
new file mode 100644
index 0000000..007285e
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart.weak.transformed.expect
@@ -0,0 +1,31 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri_part.dart:8:27: Error: A value of type 'Class Function()' can't be assigned to a variable of type 'Class Function(int)'.
+// - 'Class' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart'.
+// Class Function(int) f = Class.new;
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+part constructor_tear_off_uri_part.dart;
+class Class extends core::Object { // from org-dartlang-testcase:///constructor_tear_off_uri_part.dart
+ synthetic constructor •() → self::Class
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff() → self::Class
+ return new self::Class::•();
+}
+static method main() → dynamic {}
+static method /* from org-dartlang-testcase:///constructor_tear_off_uri_part.dart */ test() → dynamic {
+ (core::int) → self::Class f = let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri_part.dart:8:27: Error: A value of type 'Class Function()' can't be assigned to a variable of type 'Class Function(int)'.
+ - 'Class' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri.dart'.
+ Class Function(int) f = Class.new;
+ ^" in (#C1) as{TypeError,ForNonNullableByDefault} (core::int) → self::Class;
+}
+
+constants {
+ #C1 = static-tearoff self::Class::_#new#tearOff
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri_part.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri_part.dart
new file mode 100644
index 0000000..042cb62
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/constructor_tear_off_uri_part.dart
@@ -0,0 +1,23 @@
+// 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.
+
+part of 'constructor_tear_off_uri.dart';
+
+test() {
+ Class Function(int) f = Class.new;
+}
+
+// Long comment to increase file offset of Class
+// Long comment to increase file offset of Class
+// Long comment to increase file offset of Class
+// Long comment to increase file offset of Class
+// Long comment to increase file offset of Class
+// Long comment to increase file offset of Class
+// Long comment to increase file offset of Class
+// Long comment to increase file offset of Class
+// Long comment to increase file offset of Class
+// Long comment to increase file offset of Class
+// Long comment to increase file offset of Class
+
+class Class {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart
new file mode 100644
index 0000000..9c6ef02
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart
@@ -0,0 +1,163 @@
+// 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.
+
+final bool inSoundMode = <int?>[] is! List<int>;
+
+main() {
+ print('inSoundMode: $inSoundMode');
+ testNoArgs();
+ testArgs();
+}
+
+class Class1 {
+ Class1._();
+ factory Class1() => new Class1._();
+}
+
+class Class2 {
+ Class2._();
+ factory Class2.named() => new Class2._();
+}
+
+testNoArgs() {
+ var f1a = Class1.new;
+ var c1a = f1a();
+ expect(true, c1a is Class1);
+
+ dynamic f1b = Class1.new;
+ var c1b = f1b();
+ expect(true, c1b is Class1);
+
+ expect(true, identical(f1a, f1b));
+
+ var f2a = Class2.named;
+ var c2a = f2a();
+ expect(true, c2a is Class2);
+
+ dynamic f2b = Class2.named;
+ var c2b = f2b();
+ expect(true, c2b is Class2);
+
+ expect(true, identical(f2a, f2b));
+}
+
+class Class3 {
+ final int field;
+
+ Class3._(this.field);
+ factory Class3(int field) => new Class3._(field);
+}
+
+class Class4 {
+ final int? field;
+
+ Class4._([this.field]);
+ factory Class4([int? field]) => new Class4._(field);
+}
+
+class Class5 {
+ final int field1;
+ final int? field2;
+
+ Class5._(this.field1, [this.field2]);
+ factory Class5(int field1, [int? field2]) => new Class5._(field1, field2);
+}
+
+class Class6 {
+ final int field1;
+ final int? field2;
+ final int field3;
+
+ Class6._(this.field1, {this.field2, required this.field3});
+ factory Class6(int field1, {int? field2, required int field3}) =>
+ new Class6._(field1, field2: field2, field3: field3);
+}
+
+testArgs() {
+ var f3a = Class3.new;
+ var c3a = f3a(42);
+ expect(42, c3a.field);
+ () {
+ f3a(); // error
+ f3a(42, 87); // error
+ };
+
+ dynamic f3b = Class3.new;
+ var c3b = f3b(87);
+ expect(87, c3b.field);
+ throws(() => f3b());
+ throws(() => f3b(42, 87));
+
+ var f4a = Class4.new;
+ var c4a = f4a();
+ expect(null, c4a.field);
+ var c4b = f4a(42);
+ expect(42, c4b.field);
+ () {
+ f4a(42, 87); // error
+ };
+ dynamic f4b = Class4.new;
+ throws(() => f4b(42, 87));
+
+
+ var f5a = Class5.new;
+ var c5a = f5a(42);
+ expect(42, c5a.field1);
+ expect(null, c5a.field2);
+ var c5b = f5a(87, 42);
+ expect(87, c5b.field1);
+ expect(42, c5b.field2);
+ () {
+ f5a(); // error
+ f5a(42, 87, 123); // error
+ };
+ dynamic f5b = Class5.new;
+ throws(() => f5b());
+ throws(() => f5b(42, 87, 123));
+
+ var f6a = Class6.new;
+ var c6a = f6a(42, field3: 87);
+ expect(42, c6a.field1);
+ expect(null, c6a.field2);
+ expect(87, c6a.field3);
+ () {
+ f6a(); // error
+ f6a(42); // error
+ f6a(42, 87); // error
+ f6a(field1: 87, field2: 87); // error
+ };
+
+ var c6b = f6a(42, field2: 123, field3: 87);
+ expect(42, c6b.field1);
+ expect(123, c6b.field2);
+ expect(87, c6b.field3);
+
+ var c6c = f6a(87, field3: 42, field2: 123);
+ expect(87, c6c.field1);
+ expect(123, c6c.field2);
+ expect(42, c6c.field3);
+
+ dynamic f6b = Class6.new;
+ throws(() => f6b());
+ throws(() => f6b(42), inSoundModeOnly: true);
+ throws(() => f6b(42, 87), inSoundModeOnly: true);
+ throws(() => f6b(field1: 87, field2: 87));
+}
+
+expect(expected, actual) {
+ if (expected != actual) throw 'Expected $expected, actual $actual';
+}
+
+throws(Function() f, {bool inSoundModeOnly: false}) {
+ try {
+ f();
+ } catch (e) {
+ print('Thrown: $e');
+ return;
+ }
+ if (!inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw 'Expected exception';
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart.strong.expect
new file mode 100644
index 0000000..7c14634
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart.strong.expect
@@ -0,0 +1,254 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:82:8: Error: Too few positional arguments: 1 required, 0 given.
+// f3a(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:83:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f3a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:98:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f4a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:112:8: Error: Too few positional arguments: 1 required, 0 given.
+// f5a(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:113:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+// Try removing the extra positional arguments.
+// f5a(42, 87, 123); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:125:8: Error: Too few positional arguments: 1 required, 0 given.
+// f6a(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:126:8: Error: Required named parameter 'field3' must be provided.
+// f6a(42); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:127:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f6a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:128:8: Error: Too few positional arguments: 1 required, 0 given.
+// f6a(field1: 87, field2: 87); // error
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+ constructor _() → self::Class1
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff() → self::Class1
+ return new self::Class1::_();
+ static factory •() → self::Class1
+ return new self::Class1::_();
+ static method _#new#tearOff() → self::Class1
+ return self::Class1::•();
+}
+class Class2 extends core::Object {
+ constructor _() → self::Class2
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff() → self::Class2
+ return new self::Class2::_();
+ static factory named() → self::Class2
+ return new self::Class2::_();
+ static method _#named#tearOff() → self::Class2
+ return self::Class2::named();
+}
+class Class3 extends core::Object {
+ final field core::int field;
+ constructor _(core::int field) → self::Class3
+ : self::Class3::field = field, super core::Object::•()
+ ;
+ static method _#_#tearOff(core::int field) → self::Class3
+ return new self::Class3::_(field);
+ static factory •(core::int field) → self::Class3
+ return new self::Class3::_(field);
+ static method _#new#tearOff(core::int field) → self::Class3
+ return self::Class3::•(field);
+}
+class Class4 extends core::Object {
+ final field core::int? field;
+ constructor _([core::int? field = #C1]) → self::Class4
+ : self::Class4::field = field, super core::Object::•()
+ ;
+ static method _#_#tearOff([core::int? field = #C1]) → self::Class4
+ return new self::Class4::_(field);
+ static factory •([core::int? field = #C1]) → self::Class4
+ return new self::Class4::_(field);
+ static method _#new#tearOff([core::int? field = #C1]) → self::Class4
+ return self::Class4::•(field);
+}
+class Class5 extends core::Object {
+ final field core::int field1;
+ final field core::int? field2;
+ constructor _(core::int field1, [core::int? field2 = #C1]) → self::Class5
+ : self::Class5::field1 = field1, self::Class5::field2 = field2, super core::Object::•()
+ ;
+ static method _#_#tearOff(core::int field1, [core::int? field2 = #C1]) → self::Class5
+ return new self::Class5::_(field1, field2);
+ static factory •(core::int field1, [core::int? field2 = #C1]) → self::Class5
+ return new self::Class5::_(field1, field2);
+ static method _#new#tearOff(core::int field1, [core::int? field2 = #C1]) → self::Class5
+ return self::Class5::•(field1, field2);
+}
+class Class6 extends core::Object {
+ final field core::int field1;
+ final field core::int? field2;
+ final field core::int field3;
+ constructor _(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+ : self::Class6::field1 = field1, self::Class6::field2 = field2, self::Class6::field3 = field3, super core::Object::•()
+ ;
+ static method _#_#tearOff(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+ return new self::Class6::_(field1, field2: field2, field3: field3);
+ static factory •(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+ return new self::Class6::_(field1, field2: field2, field3: field3);
+ static method _#new#tearOff(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+ return self::Class6::•(field1, field2: field2, field3: field3);
+}
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+ core::print("inSoundMode: ${self::inSoundMode}");
+ self::testNoArgs();
+ self::testArgs();
+}
+static method testNoArgs() → dynamic {
+ () → self::Class1 f1a = #C2;
+ self::Class1 c1a = f1a(){() → self::Class1};
+ self::expect(true, c1a is{ForNonNullableByDefault} self::Class1);
+ dynamic f1b = #C2;
+ dynamic c1b = f1b{dynamic}.call();
+ self::expect(true, c1b is{ForNonNullableByDefault} self::Class1);
+ self::expect(true, core::identical(f1a, f1b));
+ () → self::Class2 f2a = #C3;
+ self::Class2 c2a = f2a(){() → self::Class2};
+ self::expect(true, c2a is{ForNonNullableByDefault} self::Class2);
+ dynamic f2b = #C3;
+ dynamic c2b = f2b{dynamic}.call();
+ self::expect(true, c2b is{ForNonNullableByDefault} self::Class2);
+ self::expect(true, core::identical(f2a, f2b));
+}
+static method testArgs() → dynamic {
+ (core::int) → self::Class3 f3a = #C4;
+ self::Class3 c3a = f3a(42){(core::int) → self::Class3};
+ self::expect(42, c3a.{self::Class3::field}{core::int});
+ () → Null {
+ let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:82:8: Error: Too few positional arguments: 1 required, 0 given.
+ f3a(); // error
+ ^" in f3a{<inapplicable>}.();
+ let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:83:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f3a(42, 87); // error
+ ^" in f3a{<inapplicable>}.(42, 87);
+ };
+ dynamic f3b = #C4;
+ dynamic c3b = f3b{dynamic}.call(87);
+ self::expect(87, c3b{dynamic}.field);
+ self::throws(() → dynamic => f3b{dynamic}.call());
+ self::throws(() → dynamic => f3b{dynamic}.call(42, 87));
+ ([core::int?]) → self::Class4 f4a = #C5;
+ self::Class4 c4a = f4a(){([core::int?]) → self::Class4};
+ self::expect(null, c4a.{self::Class4::field}{core::int?});
+ self::Class4 c4b = f4a(42){([core::int?]) → self::Class4};
+ self::expect(42, c4b.{self::Class4::field}{core::int?});
+ () → Null {
+ let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:98:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f4a(42, 87); // error
+ ^" in f4a{<inapplicable>}.(42, 87);
+ };
+ dynamic f4b = #C5;
+ self::throws(() → dynamic => f4b{dynamic}.call(42, 87));
+ (core::int, [core::int?]) → self::Class5 f5a = #C6;
+ self::Class5 c5a = f5a(42){(core::int, [core::int?]) → self::Class5};
+ self::expect(42, c5a.{self::Class5::field1}{core::int});
+ self::expect(null, c5a.{self::Class5::field2}{core::int?});
+ self::Class5 c5b = f5a(87, 42){(core::int, [core::int?]) → self::Class5};
+ self::expect(87, c5b.{self::Class5::field1}{core::int});
+ self::expect(42, c5b.{self::Class5::field2}{core::int?});
+ () → Null {
+ let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:112:8: Error: Too few positional arguments: 1 required, 0 given.
+ f5a(); // error
+ ^" in f5a{<inapplicable>}.();
+ let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:113:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+Try removing the extra positional arguments.
+ f5a(42, 87, 123); // error
+ ^" in f5a{<inapplicable>}.(42, 87, 123);
+ };
+ dynamic f5b = #C6;
+ self::throws(() → dynamic => f5b{dynamic}.call());
+ self::throws(() → dynamic => f5b{dynamic}.call(42, 87, 123));
+ (core::int, {field2: core::int?, required field3: core::int}) → self::Class6 f6a = #C7;
+ self::Class6 c6a = f6a(42, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+ self::expect(42, c6a.{self::Class6::field1}{core::int});
+ self::expect(null, c6a.{self::Class6::field2}{core::int?});
+ self::expect(87, c6a.{self::Class6::field3}{core::int});
+ () → Null {
+ let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:125:8: Error: Too few positional arguments: 1 required, 0 given.
+ f6a(); // error
+ ^" in f6a{<inapplicable>}.();
+ let final Never #t7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:126:8: Error: Required named parameter 'field3' must be provided.
+ f6a(42); // error
+ ^" in f6a{<inapplicable>}.(42);
+ let final Never #t8 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:127:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f6a(42, 87); // error
+ ^" in f6a{<inapplicable>}.(42, 87);
+ let final Never #t9 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:128:8: Error: Too few positional arguments: 1 required, 0 given.
+ f6a(field1: 87, field2: 87); // error
+ ^" in f6a{<inapplicable>}.(field1: 87, field2: 87);
+ };
+ self::Class6 c6b = f6a(42, field2: 123, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+ self::expect(42, c6b.{self::Class6::field1}{core::int});
+ self::expect(123, c6b.{self::Class6::field2}{core::int?});
+ self::expect(87, c6b.{self::Class6::field3}{core::int});
+ self::Class6 c6c = f6a(87, field3: 42, field2: 123){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+ self::expect(87, c6c.{self::Class6::field1}{core::int});
+ self::expect(123, c6c.{self::Class6::field2}{core::int?});
+ self::expect(42, c6c.{self::Class6::field3}{core::int});
+ dynamic f6b = #C7;
+ self::throws(() → dynamic => f6b{dynamic}.call());
+ self::throws(() → dynamic => f6b{dynamic}.call(42), inSoundModeOnly: true);
+ self::throws(() → dynamic => f6b{dynamic}.call(42, 87), inSoundModeOnly: true);
+ self::throws(() → dynamic => f6b{dynamic}.call(field1: 87, field2: 87));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C8}) → dynamic {
+ try {
+ f(){() → dynamic};
+ }
+ on core::Object catch(final core::Object e) {
+ core::print("Thrown: ${e}");
+ return;
+ }
+ if(!self::inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw "Expected exception";
+}
+
+constants {
+ #C1 = null
+ #C2 = static-tearoff self::Class1::_#new#tearOff
+ #C3 = static-tearoff self::Class2::_#named#tearOff
+ #C4 = static-tearoff self::Class3::_#new#tearOff
+ #C5 = static-tearoff self::Class4::_#new#tearOff
+ #C6 = static-tearoff self::Class5::_#new#tearOff
+ #C7 = static-tearoff self::Class6::_#new#tearOff
+ #C8 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart.strong.transformed.expect
new file mode 100644
index 0000000..ebe5432
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart.strong.transformed.expect
@@ -0,0 +1,254 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:82:8: Error: Too few positional arguments: 1 required, 0 given.
+// f3a(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:83:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f3a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:98:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f4a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:112:8: Error: Too few positional arguments: 1 required, 0 given.
+// f5a(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:113:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+// Try removing the extra positional arguments.
+// f5a(42, 87, 123); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:125:8: Error: Too few positional arguments: 1 required, 0 given.
+// f6a(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:126:8: Error: Required named parameter 'field3' must be provided.
+// f6a(42); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:127:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f6a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:128:8: Error: Too few positional arguments: 1 required, 0 given.
+// f6a(field1: 87, field2: 87); // error
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+ constructor _() → self::Class1
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff() → self::Class1
+ return new self::Class1::_();
+ static factory •() → self::Class1
+ return new self::Class1::_();
+ static method _#new#tearOff() → self::Class1
+ return self::Class1::•();
+}
+class Class2 extends core::Object {
+ constructor _() → self::Class2
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff() → self::Class2
+ return new self::Class2::_();
+ static factory named() → self::Class2
+ return new self::Class2::_();
+ static method _#named#tearOff() → self::Class2
+ return self::Class2::named();
+}
+class Class3 extends core::Object {
+ final field core::int field;
+ constructor _(core::int field) → self::Class3
+ : self::Class3::field = field, super core::Object::•()
+ ;
+ static method _#_#tearOff(core::int field) → self::Class3
+ return new self::Class3::_(field);
+ static factory •(core::int field) → self::Class3
+ return new self::Class3::_(field);
+ static method _#new#tearOff(core::int field) → self::Class3
+ return self::Class3::•(field);
+}
+class Class4 extends core::Object {
+ final field core::int? field;
+ constructor _([core::int? field = #C1]) → self::Class4
+ : self::Class4::field = field, super core::Object::•()
+ ;
+ static method _#_#tearOff([core::int? field = #C1]) → self::Class4
+ return new self::Class4::_(field);
+ static factory •([core::int? field = #C1]) → self::Class4
+ return new self::Class4::_(field);
+ static method _#new#tearOff([core::int? field = #C1]) → self::Class4
+ return self::Class4::•(field);
+}
+class Class5 extends core::Object {
+ final field core::int field1;
+ final field core::int? field2;
+ constructor _(core::int field1, [core::int? field2 = #C1]) → self::Class5
+ : self::Class5::field1 = field1, self::Class5::field2 = field2, super core::Object::•()
+ ;
+ static method _#_#tearOff(core::int field1, [core::int? field2 = #C1]) → self::Class5
+ return new self::Class5::_(field1, field2);
+ static factory •(core::int field1, [core::int? field2 = #C1]) → self::Class5
+ return new self::Class5::_(field1, field2);
+ static method _#new#tearOff(core::int field1, [core::int? field2 = #C1]) → self::Class5
+ return self::Class5::•(field1, field2);
+}
+class Class6 extends core::Object {
+ final field core::int field1;
+ final field core::int? field2;
+ final field core::int field3;
+ constructor _(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+ : self::Class6::field1 = field1, self::Class6::field2 = field2, self::Class6::field3 = field3, super core::Object::•()
+ ;
+ static method _#_#tearOff(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+ return new self::Class6::_(field1, field2: field2, field3: field3);
+ static factory •(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+ return new self::Class6::_(field1, field2: field2, field3: field3);
+ static method _#new#tearOff(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+ return self::Class6::•(field1, field2: field2, field3: field3);
+}
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+ core::print("inSoundMode: ${self::inSoundMode}");
+ self::testNoArgs();
+ self::testArgs();
+}
+static method testNoArgs() → dynamic {
+ () → self::Class1 f1a = #C2;
+ self::Class1 c1a = f1a(){() → self::Class1};
+ self::expect(true, c1a is{ForNonNullableByDefault} self::Class1);
+ dynamic f1b = #C2;
+ dynamic c1b = f1b{dynamic}.call();
+ self::expect(true, c1b is{ForNonNullableByDefault} self::Class1);
+ self::expect(true, core::identical(f1a, f1b));
+ () → self::Class2 f2a = #C3;
+ self::Class2 c2a = f2a(){() → self::Class2};
+ self::expect(true, c2a is{ForNonNullableByDefault} self::Class2);
+ dynamic f2b = #C3;
+ dynamic c2b = f2b{dynamic}.call();
+ self::expect(true, c2b is{ForNonNullableByDefault} self::Class2);
+ self::expect(true, core::identical(f2a, f2b));
+}
+static method testArgs() → dynamic {
+ (core::int) → self::Class3 f3a = #C4;
+ self::Class3 c3a = f3a(42){(core::int) → self::Class3};
+ self::expect(42, c3a.{self::Class3::field}{core::int});
+ () → Null {
+ let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:82:8: Error: Too few positional arguments: 1 required, 0 given.
+ f3a(); // error
+ ^" in f3a{<inapplicable>}.();
+ let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:83:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f3a(42, 87); // error
+ ^" in f3a{<inapplicable>}.(42, 87);
+ };
+ dynamic f3b = #C4;
+ dynamic c3b = f3b{dynamic}.call(87);
+ self::expect(87, c3b{dynamic}.field);
+ self::throws(() → dynamic => f3b{dynamic}.call());
+ self::throws(() → dynamic => f3b{dynamic}.call(42, 87));
+ ([core::int?]) → self::Class4 f4a = #C5;
+ self::Class4 c4a = f4a(){([core::int?]) → self::Class4};
+ self::expect(null, c4a.{self::Class4::field}{core::int?});
+ self::Class4 c4b = f4a(42){([core::int?]) → self::Class4};
+ self::expect(42, c4b.{self::Class4::field}{core::int?});
+ () → Null {
+ let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:98:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f4a(42, 87); // error
+ ^" in f4a{<inapplicable>}.(42, 87);
+ };
+ dynamic f4b = #C5;
+ self::throws(() → dynamic => f4b{dynamic}.call(42, 87));
+ (core::int, [core::int?]) → self::Class5 f5a = #C6;
+ self::Class5 c5a = f5a(42){(core::int, [core::int?]) → self::Class5};
+ self::expect(42, c5a.{self::Class5::field1}{core::int});
+ self::expect(null, c5a.{self::Class5::field2}{core::int?});
+ self::Class5 c5b = f5a(87, 42){(core::int, [core::int?]) → self::Class5};
+ self::expect(87, c5b.{self::Class5::field1}{core::int});
+ self::expect(42, c5b.{self::Class5::field2}{core::int?});
+ () → Null {
+ let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:112:8: Error: Too few positional arguments: 1 required, 0 given.
+ f5a(); // error
+ ^" in f5a{<inapplicable>}.();
+ let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:113:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+Try removing the extra positional arguments.
+ f5a(42, 87, 123); // error
+ ^" in f5a{<inapplicable>}.(42, 87, 123);
+ };
+ dynamic f5b = #C6;
+ self::throws(() → dynamic => f5b{dynamic}.call());
+ self::throws(() → dynamic => f5b{dynamic}.call(42, 87, 123));
+ (core::int, {field2: core::int?, required field3: core::int}) → self::Class6 f6a = #C7;
+ self::Class6 c6a = f6a(42, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+ self::expect(42, c6a.{self::Class6::field1}{core::int});
+ self::expect(null, c6a.{self::Class6::field2}{core::int?});
+ self::expect(87, c6a.{self::Class6::field3}{core::int});
+ () → Null {
+ let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:125:8: Error: Too few positional arguments: 1 required, 0 given.
+ f6a(); // error
+ ^" in f6a{<inapplicable>}.();
+ let final Never #t7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:126:8: Error: Required named parameter 'field3' must be provided.
+ f6a(42); // error
+ ^" in f6a{<inapplicable>}.(42);
+ let final Never #t8 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:127:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f6a(42, 87); // error
+ ^" in f6a{<inapplicable>}.(42, 87);
+ let final Never #t9 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:128:8: Error: Too few positional arguments: 1 required, 0 given.
+ f6a(field1: 87, field2: 87); // error
+ ^" in f6a{<inapplicable>}.(field1: 87, field2: 87);
+ };
+ self::Class6 c6b = f6a(42, field2: 123, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+ self::expect(42, c6b.{self::Class6::field1}{core::int});
+ self::expect(123, c6b.{self::Class6::field2}{core::int?});
+ self::expect(87, c6b.{self::Class6::field3}{core::int});
+ self::Class6 c6c = f6a(87, field3: 42, field2: 123){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+ self::expect(87, c6c.{self::Class6::field1}{core::int});
+ self::expect(123, c6c.{self::Class6::field2}{core::int?});
+ self::expect(42, c6c.{self::Class6::field3}{core::int});
+ dynamic f6b = #C7;
+ self::throws(() → dynamic => f6b{dynamic}.call());
+ self::throws(() → dynamic => f6b{dynamic}.call(42), inSoundModeOnly: true);
+ self::throws(() → dynamic => f6b{dynamic}.call(42, 87), inSoundModeOnly: true);
+ self::throws(() → dynamic => f6b{dynamic}.call(field1: 87, field2: 87));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C8}) → dynamic {
+ try {
+ f(){() → dynamic};
+ }
+ on core::Object catch(final core::Object e) {
+ core::print("Thrown: ${e}");
+ return;
+ }
+ if(!self::inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw "Expected exception";
+}
+
+constants {
+ #C1 = null
+ #C2 = static-tearoff self::Class1::_#new#tearOff
+ #C3 = static-tearoff self::Class2::_#named#tearOff
+ #C4 = static-tearoff self::Class3::_#new#tearOff
+ #C5 = static-tearoff self::Class4::_#new#tearOff
+ #C6 = static-tearoff self::Class5::_#new#tearOff
+ #C7 = static-tearoff self::Class6::_#new#tearOff
+ #C8 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart.textual_outline.expect
new file mode 100644
index 0000000..e4d0e54
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart.textual_outline.expect
@@ -0,0 +1,46 @@
+final bool inSoundMode = <int?>[] is! List<int>;
+main() {}
+
+class Class1 {
+ Class1._();
+ factory Class1() => new Class1._();
+}
+
+class Class2 {
+ Class2._();
+ factory Class2.named() => new Class2._();
+}
+
+testNoArgs() {}
+
+class Class3 {
+ final int field;
+ Class3._(this.field);
+ factory Class3(int field) => new Class3._(field);
+}
+
+class Class4 {
+ final int? field;
+ Class4._([this.field]);
+ factory Class4([int? field]) => new Class4._(field);
+}
+
+class Class5 {
+ final int field1;
+ final int? field2;
+ Class5._(this.field1, [this.field2]);
+ factory Class5(int field1, [int? field2]) => new Class5._(field1, field2);
+}
+
+class Class6 {
+ final int field1;
+ final int? field2;
+ final int field3;
+ Class6._(this.field1, {this.field2, required this.field3});
+ factory Class6(int field1, {int? field2, required int field3}) =>
+ new Class6._(field1, field2: field2, field3: field3);
+}
+
+testArgs() {}
+expect(expected, actual) {}
+throws(Function() f, {bool inSoundModeOnly: false}) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..0e60ce8
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart.textual_outline_modelled.expect
@@ -0,0 +1,44 @@
+class Class1 {
+ Class1._();
+ factory Class1() => new Class1._();
+}
+
+class Class2 {
+ Class2._();
+ factory Class2.named() => new Class2._();
+}
+
+class Class3 {
+ Class3._(this.field);
+ factory Class3(int field) => new Class3._(field);
+ final int field;
+}
+
+class Class4 {
+ Class4._([this.field]);
+ factory Class4([int? field]) => new Class4._(field);
+ final int? field;
+}
+
+class Class5 {
+ Class5._(this.field1, [this.field2]);
+ factory Class5(int field1, [int? field2]) => new Class5._(field1, field2);
+ final int? field2;
+ final int field1;
+}
+
+class Class6 {
+ Class6._(this.field1, {this.field2, required this.field3});
+ factory Class6(int field1, {int? field2, required int field3}) =>
+ new Class6._(field1, field2: field2, field3: field3);
+ final int? field2;
+ final int field1;
+ final int field3;
+}
+
+expect(expected, actual) {}
+final bool inSoundMode = <int?>[] is! List<int>;
+main() {}
+testArgs() {}
+testNoArgs() {}
+throws(Function() f, {bool inSoundModeOnly: false}) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart.weak.expect
new file mode 100644
index 0000000..7c14634
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart.weak.expect
@@ -0,0 +1,254 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:82:8: Error: Too few positional arguments: 1 required, 0 given.
+// f3a(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:83:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f3a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:98:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f4a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:112:8: Error: Too few positional arguments: 1 required, 0 given.
+// f5a(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:113:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+// Try removing the extra positional arguments.
+// f5a(42, 87, 123); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:125:8: Error: Too few positional arguments: 1 required, 0 given.
+// f6a(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:126:8: Error: Required named parameter 'field3' must be provided.
+// f6a(42); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:127:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f6a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:128:8: Error: Too few positional arguments: 1 required, 0 given.
+// f6a(field1: 87, field2: 87); // error
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+ constructor _() → self::Class1
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff() → self::Class1
+ return new self::Class1::_();
+ static factory •() → self::Class1
+ return new self::Class1::_();
+ static method _#new#tearOff() → self::Class1
+ return self::Class1::•();
+}
+class Class2 extends core::Object {
+ constructor _() → self::Class2
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff() → self::Class2
+ return new self::Class2::_();
+ static factory named() → self::Class2
+ return new self::Class2::_();
+ static method _#named#tearOff() → self::Class2
+ return self::Class2::named();
+}
+class Class3 extends core::Object {
+ final field core::int field;
+ constructor _(core::int field) → self::Class3
+ : self::Class3::field = field, super core::Object::•()
+ ;
+ static method _#_#tearOff(core::int field) → self::Class3
+ return new self::Class3::_(field);
+ static factory •(core::int field) → self::Class3
+ return new self::Class3::_(field);
+ static method _#new#tearOff(core::int field) → self::Class3
+ return self::Class3::•(field);
+}
+class Class4 extends core::Object {
+ final field core::int? field;
+ constructor _([core::int? field = #C1]) → self::Class4
+ : self::Class4::field = field, super core::Object::•()
+ ;
+ static method _#_#tearOff([core::int? field = #C1]) → self::Class4
+ return new self::Class4::_(field);
+ static factory •([core::int? field = #C1]) → self::Class4
+ return new self::Class4::_(field);
+ static method _#new#tearOff([core::int? field = #C1]) → self::Class4
+ return self::Class4::•(field);
+}
+class Class5 extends core::Object {
+ final field core::int field1;
+ final field core::int? field2;
+ constructor _(core::int field1, [core::int? field2 = #C1]) → self::Class5
+ : self::Class5::field1 = field1, self::Class5::field2 = field2, super core::Object::•()
+ ;
+ static method _#_#tearOff(core::int field1, [core::int? field2 = #C1]) → self::Class5
+ return new self::Class5::_(field1, field2);
+ static factory •(core::int field1, [core::int? field2 = #C1]) → self::Class5
+ return new self::Class5::_(field1, field2);
+ static method _#new#tearOff(core::int field1, [core::int? field2 = #C1]) → self::Class5
+ return self::Class5::•(field1, field2);
+}
+class Class6 extends core::Object {
+ final field core::int field1;
+ final field core::int? field2;
+ final field core::int field3;
+ constructor _(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+ : self::Class6::field1 = field1, self::Class6::field2 = field2, self::Class6::field3 = field3, super core::Object::•()
+ ;
+ static method _#_#tearOff(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+ return new self::Class6::_(field1, field2: field2, field3: field3);
+ static factory •(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+ return new self::Class6::_(field1, field2: field2, field3: field3);
+ static method _#new#tearOff(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+ return self::Class6::•(field1, field2: field2, field3: field3);
+}
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+ core::print("inSoundMode: ${self::inSoundMode}");
+ self::testNoArgs();
+ self::testArgs();
+}
+static method testNoArgs() → dynamic {
+ () → self::Class1 f1a = #C2;
+ self::Class1 c1a = f1a(){() → self::Class1};
+ self::expect(true, c1a is{ForNonNullableByDefault} self::Class1);
+ dynamic f1b = #C2;
+ dynamic c1b = f1b{dynamic}.call();
+ self::expect(true, c1b is{ForNonNullableByDefault} self::Class1);
+ self::expect(true, core::identical(f1a, f1b));
+ () → self::Class2 f2a = #C3;
+ self::Class2 c2a = f2a(){() → self::Class2};
+ self::expect(true, c2a is{ForNonNullableByDefault} self::Class2);
+ dynamic f2b = #C3;
+ dynamic c2b = f2b{dynamic}.call();
+ self::expect(true, c2b is{ForNonNullableByDefault} self::Class2);
+ self::expect(true, core::identical(f2a, f2b));
+}
+static method testArgs() → dynamic {
+ (core::int) → self::Class3 f3a = #C4;
+ self::Class3 c3a = f3a(42){(core::int) → self::Class3};
+ self::expect(42, c3a.{self::Class3::field}{core::int});
+ () → Null {
+ let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:82:8: Error: Too few positional arguments: 1 required, 0 given.
+ f3a(); // error
+ ^" in f3a{<inapplicable>}.();
+ let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:83:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f3a(42, 87); // error
+ ^" in f3a{<inapplicable>}.(42, 87);
+ };
+ dynamic f3b = #C4;
+ dynamic c3b = f3b{dynamic}.call(87);
+ self::expect(87, c3b{dynamic}.field);
+ self::throws(() → dynamic => f3b{dynamic}.call());
+ self::throws(() → dynamic => f3b{dynamic}.call(42, 87));
+ ([core::int?]) → self::Class4 f4a = #C5;
+ self::Class4 c4a = f4a(){([core::int?]) → self::Class4};
+ self::expect(null, c4a.{self::Class4::field}{core::int?});
+ self::Class4 c4b = f4a(42){([core::int?]) → self::Class4};
+ self::expect(42, c4b.{self::Class4::field}{core::int?});
+ () → Null {
+ let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:98:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f4a(42, 87); // error
+ ^" in f4a{<inapplicable>}.(42, 87);
+ };
+ dynamic f4b = #C5;
+ self::throws(() → dynamic => f4b{dynamic}.call(42, 87));
+ (core::int, [core::int?]) → self::Class5 f5a = #C6;
+ self::Class5 c5a = f5a(42){(core::int, [core::int?]) → self::Class5};
+ self::expect(42, c5a.{self::Class5::field1}{core::int});
+ self::expect(null, c5a.{self::Class5::field2}{core::int?});
+ self::Class5 c5b = f5a(87, 42){(core::int, [core::int?]) → self::Class5};
+ self::expect(87, c5b.{self::Class5::field1}{core::int});
+ self::expect(42, c5b.{self::Class5::field2}{core::int?});
+ () → Null {
+ let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:112:8: Error: Too few positional arguments: 1 required, 0 given.
+ f5a(); // error
+ ^" in f5a{<inapplicable>}.();
+ let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:113:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+Try removing the extra positional arguments.
+ f5a(42, 87, 123); // error
+ ^" in f5a{<inapplicable>}.(42, 87, 123);
+ };
+ dynamic f5b = #C6;
+ self::throws(() → dynamic => f5b{dynamic}.call());
+ self::throws(() → dynamic => f5b{dynamic}.call(42, 87, 123));
+ (core::int, {field2: core::int?, required field3: core::int}) → self::Class6 f6a = #C7;
+ self::Class6 c6a = f6a(42, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+ self::expect(42, c6a.{self::Class6::field1}{core::int});
+ self::expect(null, c6a.{self::Class6::field2}{core::int?});
+ self::expect(87, c6a.{self::Class6::field3}{core::int});
+ () → Null {
+ let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:125:8: Error: Too few positional arguments: 1 required, 0 given.
+ f6a(); // error
+ ^" in f6a{<inapplicable>}.();
+ let final Never #t7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:126:8: Error: Required named parameter 'field3' must be provided.
+ f6a(42); // error
+ ^" in f6a{<inapplicable>}.(42);
+ let final Never #t8 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:127:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f6a(42, 87); // error
+ ^" in f6a{<inapplicable>}.(42, 87);
+ let final Never #t9 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:128:8: Error: Too few positional arguments: 1 required, 0 given.
+ f6a(field1: 87, field2: 87); // error
+ ^" in f6a{<inapplicable>}.(field1: 87, field2: 87);
+ };
+ self::Class6 c6b = f6a(42, field2: 123, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+ self::expect(42, c6b.{self::Class6::field1}{core::int});
+ self::expect(123, c6b.{self::Class6::field2}{core::int?});
+ self::expect(87, c6b.{self::Class6::field3}{core::int});
+ self::Class6 c6c = f6a(87, field3: 42, field2: 123){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+ self::expect(87, c6c.{self::Class6::field1}{core::int});
+ self::expect(123, c6c.{self::Class6::field2}{core::int?});
+ self::expect(42, c6c.{self::Class6::field3}{core::int});
+ dynamic f6b = #C7;
+ self::throws(() → dynamic => f6b{dynamic}.call());
+ self::throws(() → dynamic => f6b{dynamic}.call(42), inSoundModeOnly: true);
+ self::throws(() → dynamic => f6b{dynamic}.call(42, 87), inSoundModeOnly: true);
+ self::throws(() → dynamic => f6b{dynamic}.call(field1: 87, field2: 87));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C8}) → dynamic {
+ try {
+ f(){() → dynamic};
+ }
+ on core::Object catch(final core::Object e) {
+ core::print("Thrown: ${e}");
+ return;
+ }
+ if(!self::inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw "Expected exception";
+}
+
+constants {
+ #C1 = null
+ #C2 = static-tearoff self::Class1::_#new#tearOff
+ #C3 = static-tearoff self::Class2::_#named#tearOff
+ #C4 = static-tearoff self::Class3::_#new#tearOff
+ #C5 = static-tearoff self::Class4::_#new#tearOff
+ #C6 = static-tearoff self::Class5::_#new#tearOff
+ #C7 = static-tearoff self::Class6::_#new#tearOff
+ #C8 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart.weak.outline.expect
new file mode 100644
index 0000000..5366579f
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart.weak.outline.expect
@@ -0,0 +1,82 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+ constructor _() → self::Class1
+ ;
+ static method _#_#tearOff() → self::Class1
+ return new self::Class1::_();
+ static factory •() → self::Class1
+ ;
+ static method _#new#tearOff() → self::Class1
+ return self::Class1::•();
+}
+class Class2 extends core::Object {
+ constructor _() → self::Class2
+ ;
+ static method _#_#tearOff() → self::Class2
+ return new self::Class2::_();
+ static factory named() → self::Class2
+ ;
+ static method _#named#tearOff() → self::Class2
+ return self::Class2::named();
+}
+class Class3 extends core::Object {
+ final field core::int field;
+ constructor _(core::int field) → self::Class3
+ ;
+ static method _#_#tearOff(core::int field) → self::Class3
+ return new self::Class3::_(field);
+ static factory •(core::int field) → self::Class3
+ ;
+ static method _#new#tearOff(core::int field) → self::Class3
+ return self::Class3::•(field);
+}
+class Class4 extends core::Object {
+ final field core::int? field;
+ constructor _([core::int? field]) → self::Class4
+ ;
+ static method _#_#tearOff([core::int? field]) → self::Class4
+ return new self::Class4::_(field);
+ static factory •([core::int? field]) → self::Class4
+ ;
+ static method _#new#tearOff([core::int? field]) → self::Class4
+ return self::Class4::•(field);
+}
+class Class5 extends core::Object {
+ final field core::int field1;
+ final field core::int? field2;
+ constructor _(core::int field1, [core::int? field2]) → self::Class5
+ ;
+ static method _#_#tearOff(core::int field1, [core::int? field2]) → self::Class5
+ return new self::Class5::_(field1, field2);
+ static factory •(core::int field1, [core::int? field2]) → self::Class5
+ ;
+ static method _#new#tearOff(core::int field1, [core::int? field2]) → self::Class5
+ return self::Class5::•(field1, field2);
+}
+class Class6 extends core::Object {
+ final field core::int field1;
+ final field core::int? field2;
+ final field core::int field3;
+ constructor _(core::int field1, {core::int? field2, required core::int field3}) → self::Class6
+ ;
+ static method _#_#tearOff(core::int field1, {core::int? field2, required core::int field3}) → self::Class6
+ return new self::Class6::_(field1, field2: field2, field3: field3);
+ static factory •(core::int field1, {core::int? field2, required core::int field3}) → self::Class6
+ ;
+ static method _#new#tearOff(core::int field1, {core::int? field2, required core::int field3}) → self::Class6
+ return self::Class6::•(field1, field2: field2, field3: field3);
+}
+static final field core::bool inSoundMode;
+static method main() → dynamic
+ ;
+static method testNoArgs() → dynamic
+ ;
+static method testArgs() → dynamic
+ ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+ ;
+static method throws(() → dynamic f, {core::bool inSoundModeOnly}) → dynamic
+ ;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart.weak.transformed.expect
new file mode 100644
index 0000000..ebe5432
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart.weak.transformed.expect
@@ -0,0 +1,254 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:82:8: Error: Too few positional arguments: 1 required, 0 given.
+// f3a(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:83:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f3a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:98:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f4a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:112:8: Error: Too few positional arguments: 1 required, 0 given.
+// f5a(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:113:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+// Try removing the extra positional arguments.
+// f5a(42, 87, 123); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:125:8: Error: Too few positional arguments: 1 required, 0 given.
+// f6a(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:126:8: Error: Required named parameter 'field3' must be provided.
+// f6a(42); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:127:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f6a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:128:8: Error: Too few positional arguments: 1 required, 0 given.
+// f6a(field1: 87, field2: 87); // error
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+ constructor _() → self::Class1
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff() → self::Class1
+ return new self::Class1::_();
+ static factory •() → self::Class1
+ return new self::Class1::_();
+ static method _#new#tearOff() → self::Class1
+ return self::Class1::•();
+}
+class Class2 extends core::Object {
+ constructor _() → self::Class2
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff() → self::Class2
+ return new self::Class2::_();
+ static factory named() → self::Class2
+ return new self::Class2::_();
+ static method _#named#tearOff() → self::Class2
+ return self::Class2::named();
+}
+class Class3 extends core::Object {
+ final field core::int field;
+ constructor _(core::int field) → self::Class3
+ : self::Class3::field = field, super core::Object::•()
+ ;
+ static method _#_#tearOff(core::int field) → self::Class3
+ return new self::Class3::_(field);
+ static factory •(core::int field) → self::Class3
+ return new self::Class3::_(field);
+ static method _#new#tearOff(core::int field) → self::Class3
+ return self::Class3::•(field);
+}
+class Class4 extends core::Object {
+ final field core::int? field;
+ constructor _([core::int? field = #C1]) → self::Class4
+ : self::Class4::field = field, super core::Object::•()
+ ;
+ static method _#_#tearOff([core::int? field = #C1]) → self::Class4
+ return new self::Class4::_(field);
+ static factory •([core::int? field = #C1]) → self::Class4
+ return new self::Class4::_(field);
+ static method _#new#tearOff([core::int? field = #C1]) → self::Class4
+ return self::Class4::•(field);
+}
+class Class5 extends core::Object {
+ final field core::int field1;
+ final field core::int? field2;
+ constructor _(core::int field1, [core::int? field2 = #C1]) → self::Class5
+ : self::Class5::field1 = field1, self::Class5::field2 = field2, super core::Object::•()
+ ;
+ static method _#_#tearOff(core::int field1, [core::int? field2 = #C1]) → self::Class5
+ return new self::Class5::_(field1, field2);
+ static factory •(core::int field1, [core::int? field2 = #C1]) → self::Class5
+ return new self::Class5::_(field1, field2);
+ static method _#new#tearOff(core::int field1, [core::int? field2 = #C1]) → self::Class5
+ return self::Class5::•(field1, field2);
+}
+class Class6 extends core::Object {
+ final field core::int field1;
+ final field core::int? field2;
+ final field core::int field3;
+ constructor _(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+ : self::Class6::field1 = field1, self::Class6::field2 = field2, self::Class6::field3 = field3, super core::Object::•()
+ ;
+ static method _#_#tearOff(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+ return new self::Class6::_(field1, field2: field2, field3: field3);
+ static factory •(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+ return new self::Class6::_(field1, field2: field2, field3: field3);
+ static method _#new#tearOff(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+ return self::Class6::•(field1, field2: field2, field3: field3);
+}
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+ core::print("inSoundMode: ${self::inSoundMode}");
+ self::testNoArgs();
+ self::testArgs();
+}
+static method testNoArgs() → dynamic {
+ () → self::Class1 f1a = #C2;
+ self::Class1 c1a = f1a(){() → self::Class1};
+ self::expect(true, c1a is{ForNonNullableByDefault} self::Class1);
+ dynamic f1b = #C2;
+ dynamic c1b = f1b{dynamic}.call();
+ self::expect(true, c1b is{ForNonNullableByDefault} self::Class1);
+ self::expect(true, core::identical(f1a, f1b));
+ () → self::Class2 f2a = #C3;
+ self::Class2 c2a = f2a(){() → self::Class2};
+ self::expect(true, c2a is{ForNonNullableByDefault} self::Class2);
+ dynamic f2b = #C3;
+ dynamic c2b = f2b{dynamic}.call();
+ self::expect(true, c2b is{ForNonNullableByDefault} self::Class2);
+ self::expect(true, core::identical(f2a, f2b));
+}
+static method testArgs() → dynamic {
+ (core::int) → self::Class3 f3a = #C4;
+ self::Class3 c3a = f3a(42){(core::int) → self::Class3};
+ self::expect(42, c3a.{self::Class3::field}{core::int});
+ () → Null {
+ let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:82:8: Error: Too few positional arguments: 1 required, 0 given.
+ f3a(); // error
+ ^" in f3a{<inapplicable>}.();
+ let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:83:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f3a(42, 87); // error
+ ^" in f3a{<inapplicable>}.(42, 87);
+ };
+ dynamic f3b = #C4;
+ dynamic c3b = f3b{dynamic}.call(87);
+ self::expect(87, c3b{dynamic}.field);
+ self::throws(() → dynamic => f3b{dynamic}.call());
+ self::throws(() → dynamic => f3b{dynamic}.call(42, 87));
+ ([core::int?]) → self::Class4 f4a = #C5;
+ self::Class4 c4a = f4a(){([core::int?]) → self::Class4};
+ self::expect(null, c4a.{self::Class4::field}{core::int?});
+ self::Class4 c4b = f4a(42){([core::int?]) → self::Class4};
+ self::expect(42, c4b.{self::Class4::field}{core::int?});
+ () → Null {
+ let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:98:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f4a(42, 87); // error
+ ^" in f4a{<inapplicable>}.(42, 87);
+ };
+ dynamic f4b = #C5;
+ self::throws(() → dynamic => f4b{dynamic}.call(42, 87));
+ (core::int, [core::int?]) → self::Class5 f5a = #C6;
+ self::Class5 c5a = f5a(42){(core::int, [core::int?]) → self::Class5};
+ self::expect(42, c5a.{self::Class5::field1}{core::int});
+ self::expect(null, c5a.{self::Class5::field2}{core::int?});
+ self::Class5 c5b = f5a(87, 42){(core::int, [core::int?]) → self::Class5};
+ self::expect(87, c5b.{self::Class5::field1}{core::int});
+ self::expect(42, c5b.{self::Class5::field2}{core::int?});
+ () → Null {
+ let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:112:8: Error: Too few positional arguments: 1 required, 0 given.
+ f5a(); // error
+ ^" in f5a{<inapplicable>}.();
+ let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:113:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+Try removing the extra positional arguments.
+ f5a(42, 87, 123); // error
+ ^" in f5a{<inapplicable>}.(42, 87, 123);
+ };
+ dynamic f5b = #C6;
+ self::throws(() → dynamic => f5b{dynamic}.call());
+ self::throws(() → dynamic => f5b{dynamic}.call(42, 87, 123));
+ (core::int, {field2: core::int?, required field3: core::int}) → self::Class6 f6a = #C7;
+ self::Class6 c6a = f6a(42, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+ self::expect(42, c6a.{self::Class6::field1}{core::int});
+ self::expect(null, c6a.{self::Class6::field2}{core::int?});
+ self::expect(87, c6a.{self::Class6::field3}{core::int});
+ () → Null {
+ let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:125:8: Error: Too few positional arguments: 1 required, 0 given.
+ f6a(); // error
+ ^" in f6a{<inapplicable>}.();
+ let final Never #t7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:126:8: Error: Required named parameter 'field3' must be provided.
+ f6a(42); // error
+ ^" in f6a{<inapplicable>}.(42);
+ let final Never #t8 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:127:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f6a(42, 87); // error
+ ^" in f6a{<inapplicable>}.(42, 87);
+ let final Never #t9 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off.dart:128:8: Error: Too few positional arguments: 1 required, 0 given.
+ f6a(field1: 87, field2: 87); // error
+ ^" in f6a{<inapplicable>}.(field1: 87, field2: 87);
+ };
+ self::Class6 c6b = f6a(42, field2: 123, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+ self::expect(42, c6b.{self::Class6::field1}{core::int});
+ self::expect(123, c6b.{self::Class6::field2}{core::int?});
+ self::expect(87, c6b.{self::Class6::field3}{core::int});
+ self::Class6 c6c = f6a(87, field3: 42, field2: 123){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+ self::expect(87, c6c.{self::Class6::field1}{core::int});
+ self::expect(123, c6c.{self::Class6::field2}{core::int?});
+ self::expect(42, c6c.{self::Class6::field3}{core::int});
+ dynamic f6b = #C7;
+ self::throws(() → dynamic => f6b{dynamic}.call());
+ self::throws(() → dynamic => f6b{dynamic}.call(42), inSoundModeOnly: true);
+ self::throws(() → dynamic => f6b{dynamic}.call(42, 87), inSoundModeOnly: true);
+ self::throws(() → dynamic => f6b{dynamic}.call(field1: 87, field2: 87));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C8}) → dynamic {
+ try {
+ f(){() → dynamic};
+ }
+ on core::Object catch(final core::Object e) {
+ core::print("Thrown: ${e}");
+ return;
+ }
+ if(!self::inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw "Expected exception";
+}
+
+constants {
+ #C1 = null
+ #C2 = static-tearoff self::Class1::_#new#tearOff
+ #C3 = static-tearoff self::Class2::_#named#tearOff
+ #C4 = static-tearoff self::Class3::_#new#tearOff
+ #C5 = static-tearoff self::Class4::_#new#tearOff
+ #C6 = static-tearoff self::Class5::_#new#tearOff
+ #C7 = static-tearoff self::Class6::_#new#tearOff
+ #C8 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart
new file mode 100644
index 0000000..f966b5b
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart
@@ -0,0 +1,75 @@
+// 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.
+
+final bool inSoundMode = <int?>[] is! List<int>;
+
+main() {
+ print('inSoundMode: $inSoundMode');
+ testDefaultValues();
+}
+
+class Class1 {
+ final int field;
+
+ Class1._(this.field);
+ factory Class1([int field = 42]) => new Class1._(field);
+}
+
+class Class2 {
+ final int field;
+
+ Class2._(this.field);
+ factory Class2({int field: 42}) => new Class2._(field);
+}
+
+void testDefaultValues() {
+ var f1a = Class1.new;
+ var c1a = f1a();
+ expect(42, c1a.field);
+ var c1b = f1a(87);
+ expect(87, c1b.field);
+ () {
+ f1a(42, 87); // error
+ };
+
+ dynamic f1b = Class1.new;
+ var c1c = f1b();
+ expect(42, c1c.field);
+ var c1d = f1b(87);
+ expect(87, c1d.field);
+ throws(() => f1b(42, 87));
+
+ var f2a = Class2.new;
+ var c2a = f2a();
+ expect(42, c2a.field);
+ var c2b = f2a(field: 87);
+ expect(87, c2b.field);
+ () {
+ f2a(87); // error
+ };
+
+ dynamic f2b = Class2.new;
+ var c2c = f2b();
+ expect(42, c2c.field);
+ var c2d = f2b(field: 87);
+ expect(87, c2d.field);
+ throws(() => f2b(87));
+}
+
+expect(expected, actual) {
+ if (expected != actual) throw 'Expected $expected, actual $actual';
+}
+
+throws(Function() f, {bool inSoundModeOnly: false}) {
+ try {
+ f();
+ } catch (e) {
+ print('Thrown: $e');
+ return;
+ }
+ if (!inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw 'Expected exception';
+}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart.strong.expect
new file mode 100644
index 0000000..bcc5942
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart.strong.expect
@@ -0,0 +1,106 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart:33:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f1a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart:49:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+// f2a(87); // error
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+ final field core::int field;
+ constructor _(core::int field) → self::Class1
+ : self::Class1::field = field, super core::Object::•()
+ ;
+ static method _#_#tearOff(core::int field) → self::Class1
+ return new self::Class1::_(field);
+ static factory •([core::int field = #C1]) → self::Class1
+ return new self::Class1::_(field);
+ static method _#new#tearOff([core::int field = #C1]) → self::Class1
+ return self::Class1::•(field);
+}
+class Class2 extends core::Object {
+ final field core::int field;
+ constructor _(core::int field) → self::Class2
+ : self::Class2::field = field, super core::Object::•()
+ ;
+ static method _#_#tearOff(core::int field) → self::Class2
+ return new self::Class2::_(field);
+ static factory •({core::int field = #C1}) → self::Class2
+ return new self::Class2::_(field);
+ static method _#new#tearOff({core::int field = #C1}) → self::Class2
+ return self::Class2::•(field: field);
+}
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+ core::print("inSoundMode: ${self::inSoundMode}");
+ self::testDefaultValues();
+}
+static method testDefaultValues() → void {
+ ([core::int]) → self::Class1 f1a = #C2;
+ self::Class1 c1a = f1a(){([core::int]) → self::Class1};
+ self::expect(42, c1a.{self::Class1::field}{core::int});
+ self::Class1 c1b = f1a(87){([core::int]) → self::Class1};
+ self::expect(87, c1b.{self::Class1::field}{core::int});
+ () → Null {
+ let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart:33:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f1a(42, 87); // error
+ ^" in f1a{<inapplicable>}.(42, 87);
+ };
+ dynamic f1b = #C2;
+ dynamic c1c = f1b{dynamic}.call();
+ self::expect(42, c1c{dynamic}.field);
+ dynamic c1d = f1b{dynamic}.call(87);
+ self::expect(87, c1d{dynamic}.field);
+ self::throws(() → dynamic => f1b{dynamic}.call(42, 87));
+ ({field: core::int}) → self::Class2 f2a = #C3;
+ self::Class2 c2a = f2a(){({field: core::int}) → self::Class2};
+ self::expect(42, c2a.{self::Class2::field}{core::int});
+ self::Class2 c2b = f2a(field: 87){({field: core::int}) → self::Class2};
+ self::expect(87, c2b.{self::Class2::field}{core::int});
+ () → Null {
+ let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart:49:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+ f2a(87); // error
+ ^" in f2a{<inapplicable>}.(87);
+ };
+ dynamic f2b = #C3;
+ dynamic c2c = f2b{dynamic}.call();
+ self::expect(42, c2c{dynamic}.field);
+ dynamic c2d = f2b{dynamic}.call(field: 87);
+ self::expect(87, c2d{dynamic}.field);
+ self::throws(() → dynamic => f2b{dynamic}.call(87));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C4}) → dynamic {
+ try {
+ f(){() → dynamic};
+ }
+ on core::Object catch(final core::Object e) {
+ core::print("Thrown: ${e}");
+ return;
+ }
+ if(!self::inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw "Expected exception";
+}
+
+constants {
+ #C1 = 42
+ #C2 = static-tearoff self::Class1::_#new#tearOff
+ #C3 = static-tearoff self::Class2::_#new#tearOff
+ #C4 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart.strong.transformed.expect
new file mode 100644
index 0000000..db9b0fa
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart.strong.transformed.expect
@@ -0,0 +1,106 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart:33:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f1a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart:49:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+// f2a(87); // error
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+ final field core::int field;
+ constructor _(core::int field) → self::Class1
+ : self::Class1::field = field, super core::Object::•()
+ ;
+ static method _#_#tearOff(core::int field) → self::Class1
+ return new self::Class1::_(field);
+ static factory •([core::int field = #C1]) → self::Class1
+ return new self::Class1::_(field);
+ static method _#new#tearOff([core::int field = #C1]) → self::Class1
+ return self::Class1::•(field);
+}
+class Class2 extends core::Object {
+ final field core::int field;
+ constructor _(core::int field) → self::Class2
+ : self::Class2::field = field, super core::Object::•()
+ ;
+ static method _#_#tearOff(core::int field) → self::Class2
+ return new self::Class2::_(field);
+ static factory •({core::int field = #C1}) → self::Class2
+ return new self::Class2::_(field);
+ static method _#new#tearOff({core::int field = #C1}) → self::Class2
+ return self::Class2::•(field: field);
+}
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+ core::print("inSoundMode: ${self::inSoundMode}");
+ self::testDefaultValues();
+}
+static method testDefaultValues() → void {
+ ([core::int]) → self::Class1 f1a = #C2;
+ self::Class1 c1a = f1a(){([core::int]) → self::Class1};
+ self::expect(42, c1a.{self::Class1::field}{core::int});
+ self::Class1 c1b = f1a(87){([core::int]) → self::Class1};
+ self::expect(87, c1b.{self::Class1::field}{core::int});
+ () → Null {
+ let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart:33:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f1a(42, 87); // error
+ ^" in f1a{<inapplicable>}.(42, 87);
+ };
+ dynamic f1b = #C2;
+ dynamic c1c = f1b{dynamic}.call();
+ self::expect(42, c1c{dynamic}.field);
+ dynamic c1d = f1b{dynamic}.call(87);
+ self::expect(87, c1d{dynamic}.field);
+ self::throws(() → dynamic => f1b{dynamic}.call(42, 87));
+ ({field: core::int}) → self::Class2 f2a = #C3;
+ self::Class2 c2a = f2a(){({field: core::int}) → self::Class2};
+ self::expect(42, c2a.{self::Class2::field}{core::int});
+ self::Class2 c2b = f2a(field: 87){({field: core::int}) → self::Class2};
+ self::expect(87, c2b.{self::Class2::field}{core::int});
+ () → Null {
+ let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart:49:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+ f2a(87); // error
+ ^" in f2a{<inapplicable>}.(87);
+ };
+ dynamic f2b = #C3;
+ dynamic c2c = f2b{dynamic}.call();
+ self::expect(42, c2c{dynamic}.field);
+ dynamic c2d = f2b{dynamic}.call(field: 87);
+ self::expect(87, c2d{dynamic}.field);
+ self::throws(() → dynamic => f2b{dynamic}.call(87));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C4}) → dynamic {
+ try {
+ f(){() → dynamic};
+ }
+ on core::Object catch(final core::Object e) {
+ core::print("Thrown: ${e}");
+ return;
+ }
+ if(!self::inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw "Expected exception";
+}
+
+constants {
+ #C1 = 42
+ #C2 = static-tearoff self::Class1::_#new#tearOff
+ #C3 = static-tearoff self::Class2::_#new#tearOff
+ #C4 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart.textual_outline.expect
new file mode 100644
index 0000000..99a80f2
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart.textual_outline.expect
@@ -0,0 +1,18 @@
+final bool inSoundMode = <int?>[] is! List<int>;
+main() {}
+
+class Class1 {
+ final int field;
+ Class1._(this.field);
+ factory Class1([int field = 42]) => new Class1._(field);
+}
+
+class Class2 {
+ final int field;
+ Class2._(this.field);
+ factory Class2({int field: 42}) => new Class2._(field);
+}
+
+void testDefaultValues() {}
+expect(expected, actual) {}
+throws(Function() f, {bool inSoundModeOnly: false}) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..4f18568
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart.textual_outline_modelled.expect
@@ -0,0 +1,17 @@
+class Class1 {
+ Class1._(this.field);
+ factory Class1([int field = 42]) => new Class1._(field);
+ final int field;
+}
+
+class Class2 {
+ Class2._(this.field);
+ factory Class2({int field: 42}) => new Class2._(field);
+ final int field;
+}
+
+expect(expected, actual) {}
+final bool inSoundMode = <int?>[] is! List<int>;
+main() {}
+throws(Function() f, {bool inSoundModeOnly: false}) {}
+void testDefaultValues() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart.weak.expect
new file mode 100644
index 0000000..bcc5942
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart.weak.expect
@@ -0,0 +1,106 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart:33:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f1a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart:49:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+// f2a(87); // error
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+ final field core::int field;
+ constructor _(core::int field) → self::Class1
+ : self::Class1::field = field, super core::Object::•()
+ ;
+ static method _#_#tearOff(core::int field) → self::Class1
+ return new self::Class1::_(field);
+ static factory •([core::int field = #C1]) → self::Class1
+ return new self::Class1::_(field);
+ static method _#new#tearOff([core::int field = #C1]) → self::Class1
+ return self::Class1::•(field);
+}
+class Class2 extends core::Object {
+ final field core::int field;
+ constructor _(core::int field) → self::Class2
+ : self::Class2::field = field, super core::Object::•()
+ ;
+ static method _#_#tearOff(core::int field) → self::Class2
+ return new self::Class2::_(field);
+ static factory •({core::int field = #C1}) → self::Class2
+ return new self::Class2::_(field);
+ static method _#new#tearOff({core::int field = #C1}) → self::Class2
+ return self::Class2::•(field: field);
+}
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+ core::print("inSoundMode: ${self::inSoundMode}");
+ self::testDefaultValues();
+}
+static method testDefaultValues() → void {
+ ([core::int]) → self::Class1 f1a = #C2;
+ self::Class1 c1a = f1a(){([core::int]) → self::Class1};
+ self::expect(42, c1a.{self::Class1::field}{core::int});
+ self::Class1 c1b = f1a(87){([core::int]) → self::Class1};
+ self::expect(87, c1b.{self::Class1::field}{core::int});
+ () → Null {
+ let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart:33:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f1a(42, 87); // error
+ ^" in f1a{<inapplicable>}.(42, 87);
+ };
+ dynamic f1b = #C2;
+ dynamic c1c = f1b{dynamic}.call();
+ self::expect(42, c1c{dynamic}.field);
+ dynamic c1d = f1b{dynamic}.call(87);
+ self::expect(87, c1d{dynamic}.field);
+ self::throws(() → dynamic => f1b{dynamic}.call(42, 87));
+ ({field: core::int}) → self::Class2 f2a = #C3;
+ self::Class2 c2a = f2a(){({field: core::int}) → self::Class2};
+ self::expect(42, c2a.{self::Class2::field}{core::int});
+ self::Class2 c2b = f2a(field: 87){({field: core::int}) → self::Class2};
+ self::expect(87, c2b.{self::Class2::field}{core::int});
+ () → Null {
+ let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart:49:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+ f2a(87); // error
+ ^" in f2a{<inapplicable>}.(87);
+ };
+ dynamic f2b = #C3;
+ dynamic c2c = f2b{dynamic}.call();
+ self::expect(42, c2c{dynamic}.field);
+ dynamic c2d = f2b{dynamic}.call(field: 87);
+ self::expect(87, c2d{dynamic}.field);
+ self::throws(() → dynamic => f2b{dynamic}.call(87));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C4}) → dynamic {
+ try {
+ f(){() → dynamic};
+ }
+ on core::Object catch(final core::Object e) {
+ core::print("Thrown: ${e}");
+ return;
+ }
+ if(!self::inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw "Expected exception";
+}
+
+constants {
+ #C1 = 42
+ #C2 = static-tearoff self::Class1::_#new#tearOff
+ #C3 = static-tearoff self::Class2::_#new#tearOff
+ #C4 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart.weak.outline.expect
new file mode 100644
index 0000000..da300f3
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart.weak.outline.expect
@@ -0,0 +1,35 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+ final field core::int field;
+ constructor _(core::int field) → self::Class1
+ ;
+ static method _#_#tearOff(core::int field) → self::Class1
+ return new self::Class1::_(field);
+ static factory •([core::int field]) → self::Class1
+ ;
+ static method _#new#tearOff([core::int field]) → self::Class1
+ return self::Class1::•(field);
+}
+class Class2 extends core::Object {
+ final field core::int field;
+ constructor _(core::int field) → self::Class2
+ ;
+ static method _#_#tearOff(core::int field) → self::Class2
+ return new self::Class2::_(field);
+ static factory •({core::int field}) → self::Class2
+ ;
+ static method _#new#tearOff({core::int field}) → self::Class2
+ return self::Class2::•(field: field);
+}
+static final field core::bool inSoundMode;
+static method main() → dynamic
+ ;
+static method testDefaultValues() → void
+ ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+ ;
+static method throws(() → dynamic f, {core::bool inSoundModeOnly}) → dynamic
+ ;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart.weak.transformed.expect
new file mode 100644
index 0000000..db9b0fa
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart.weak.transformed.expect
@@ -0,0 +1,106 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart:33:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f1a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart:49:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+// f2a(87); // error
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+ final field core::int field;
+ constructor _(core::int field) → self::Class1
+ : self::Class1::field = field, super core::Object::•()
+ ;
+ static method _#_#tearOff(core::int field) → self::Class1
+ return new self::Class1::_(field);
+ static factory •([core::int field = #C1]) → self::Class1
+ return new self::Class1::_(field);
+ static method _#new#tearOff([core::int field = #C1]) → self::Class1
+ return self::Class1::•(field);
+}
+class Class2 extends core::Object {
+ final field core::int field;
+ constructor _(core::int field) → self::Class2
+ : self::Class2::field = field, super core::Object::•()
+ ;
+ static method _#_#tearOff(core::int field) → self::Class2
+ return new self::Class2::_(field);
+ static factory •({core::int field = #C1}) → self::Class2
+ return new self::Class2::_(field);
+ static method _#new#tearOff({core::int field = #C1}) → self::Class2
+ return self::Class2::•(field: field);
+}
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+ core::print("inSoundMode: ${self::inSoundMode}");
+ self::testDefaultValues();
+}
+static method testDefaultValues() → void {
+ ([core::int]) → self::Class1 f1a = #C2;
+ self::Class1 c1a = f1a(){([core::int]) → self::Class1};
+ self::expect(42, c1a.{self::Class1::field}{core::int});
+ self::Class1 c1b = f1a(87){([core::int]) → self::Class1};
+ self::expect(87, c1b.{self::Class1::field}{core::int});
+ () → Null {
+ let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart:33:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f1a(42, 87); // error
+ ^" in f1a{<inapplicable>}.(42, 87);
+ };
+ dynamic f1b = #C2;
+ dynamic c1c = f1b{dynamic}.call();
+ self::expect(42, c1c{dynamic}.field);
+ dynamic c1d = f1b{dynamic}.call(87);
+ self::expect(87, c1d{dynamic}.field);
+ self::throws(() → dynamic => f1b{dynamic}.call(42, 87));
+ ({field: core::int}) → self::Class2 f2a = #C3;
+ self::Class2 c2a = f2a(){({field: core::int}) → self::Class2};
+ self::expect(42, c2a.{self::Class2::field}{core::int});
+ self::Class2 c2b = f2a(field: 87){({field: core::int}) → self::Class2};
+ self::expect(87, c2b.{self::Class2::field}{core::int});
+ () → Null {
+ let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/factory_tear_off_default_values.dart:49:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+ f2a(87); // error
+ ^" in f2a{<inapplicable>}.(87);
+ };
+ dynamic f2b = #C3;
+ dynamic c2c = f2b{dynamic}.call();
+ self::expect(42, c2c{dynamic}.field);
+ dynamic c2d = f2b{dynamic}.call(field: 87);
+ self::expect(87, c2d{dynamic}.field);
+ self::throws(() → dynamic => f2b{dynamic}.call(87));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C4}) → dynamic {
+ try {
+ f(){() → dynamic};
+ }
+ on core::Object catch(final core::Object e) {
+ core::print("Thrown: ${e}");
+ return;
+ }
+ if(!self::inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw "Expected exception";
+}
+
+constants {
+ #C1 = 42
+ #C2 = static-tearoff self::Class1::_#new#tearOff
+ #C3 = static-tearoff self::Class2::_#new#tearOff
+ #C4 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart
new file mode 100644
index 0000000..ff03d6e
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart
@@ -0,0 +1,142 @@
+// 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.
+
+import 'main_lib.dart';
+
+final bool inSoundMode = <int?>[] is! List<int>;
+
+main() {
+ var f1a = Class1.new;
+ var c1a = f1a();
+ expect(true, c1a is Class1);
+
+ dynamic f1b = Class1.new;
+ var c1b = f1b();
+ expect(true, c1b is Class1);
+
+ expect(true, identical(f1a, f1b));
+
+ var f2a = Class2.named;
+ var c2a = f2a();
+ expect(true, c2a is Class2);
+
+ dynamic f2b = Class2.named;
+ var c2b = f2b();
+ expect(true, c2b is Class2);
+
+ expect(true, identical(f2a, f2b));
+
+ var f2c = Class2.redirect;
+ var c2c = f2c();
+ expect(true, c2c is Class2);
+
+ dynamic f2d = Class2.redirect;
+ var c2d = f2d();
+ expect(true, c2d is Class2);
+
+ expect(true, identical(f2c, f2d));
+
+ var f3a = Class3.new;
+ var c3a = f3a(42);
+ expect(42, c3a.field);
+ () {
+ f3a(); // error
+ f3a(42, 87); // error
+ };
+
+ dynamic f3b = Class3.new;
+ var c3b = f3b(87);
+ expect(87, c3b.field);
+ throws(() => f3b());
+ throws(() => f3b(42, 87));
+
+ var f4a = Class4.new;
+ var c4a = f4a();
+ expect(true, c4a is Class4<dynamic>);
+ expect(false, c4a is Class4<int>);
+ var c4b = f4a<int>();
+ expect(true, c4b is Class4<int>);
+ expect(false, c4b is Class4<String>);
+ () {
+ f4a<int, String>(); // error
+ };
+
+ var f4b = f4a<int>;
+ var c4c = f4b();
+ expect(true, c4c is Class4<int>);
+ expect(false, c4c is Class4<String>);
+ () {
+ f4b<int>(); // error
+ };
+
+ dynamic f4c = Class4.new;
+ var c4d = f4c();
+ expect(true, c4d is Class4<dynamic>);
+ expect(false, c4d is Class4<int>);
+ throws(() => f4c<int, String>());
+
+ var f4d = Class4.redirect;
+ var c4e = f4d();
+ expect(true, c4e is Class4<dynamic>);
+ expect(false, c4e is Class4<int>);
+ var c4f = f4d<int>();
+ expect(true, c4f is Class4<int>);
+ expect(false, c4f is Class4<String>);
+ () {
+ f4d<int, String>(); // error
+ };
+
+ var f4e = f4d<int>;
+ var c4g = f4e();
+ expect(true, c4g is Class4<int>);
+ expect(false, c4g is Class4<String>);
+ () {
+ f4e<int>(); // error
+ };
+
+ dynamic f4f = Class4.redirect;
+ var c4h = f4f();
+ expect(true, c4h is Class4<dynamic>);
+ expect(false, c4h is Class4<int>);
+ throws(() => f4f<int, String>());
+
+ var f5a = Class5.new;
+ var c5a = f5a();
+ expect(true, c5a is Class5<num>);
+ expect(false, c5a is Class5<int>);
+ var c5b = f5a<int>();
+ expect(true, c5b is Class5<int>);
+ expect(false, c5b is Class5<double>);
+ () {
+ f5a<String>(); // error
+ f5a<int, String>(); // error
+ };
+
+ dynamic f5b = Class5.new;
+ var c5c = f5b();
+ expect(true, c5c is Class5<num>);
+ expect(false, c5c is Class5<int>);
+ var c5d = f5b<int>();
+ expect(true, c5d is Class5<int>);
+ expect(false, c5d is Class5<double>);
+ throws(() => f5b<String>());
+ throws(() => f5b<int, String>());
+}
+
+expect(expected, actual) {
+ if (expected != actual) throw 'Expected $expected, actual $actual';
+}
+
+throws(Function() f, {bool inSoundModeOnly: false}) {
+ try {
+ f();
+ } catch (e) {
+ print('Thrown: $e');
+ return;
+ }
+ if (!inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw 'Expected exception';
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart.strong.expect
new file mode 100644
index 0000000..1806fdc
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart.strong.expect
@@ -0,0 +1,246 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:44:8: Error: Too few positional arguments: 1 required, 0 given.
+// f3a(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:45:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f3a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:62:8: Error: Expected 1 type arguments.
+// f4a<int, String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:70:8: Error: Expected 0 type arguments.
+// f4b<int>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:87:8: Error: Expected 1 type arguments.
+// f4d<int, String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:95:8: Error: Expected 0 type arguments.
+// f4e<int>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:112:8: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'T' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+// f5a<String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:113:8: Error: Expected 1 type arguments.
+// f5a<int, String>(); // error
+// ^
+//
+import self as self;
+import "main_lib.dart" as mai;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///main_lib.dart";
+
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+ () → mai::Class1 f1a = #C1;
+ mai::Class1 c1a = f1a(){() → mai::Class1};
+ self::expect(true, c1a is{ForNonNullableByDefault} mai::Class1);
+ dynamic f1b = #C1;
+ dynamic c1b = f1b{dynamic}.call();
+ self::expect(true, c1b is{ForNonNullableByDefault} mai::Class1);
+ self::expect(true, core::identical(f1a, f1b));
+ () → mai::Class2 f2a = #C2;
+ mai::Class2 c2a = f2a(){() → mai::Class2};
+ self::expect(true, c2a is{ForNonNullableByDefault} mai::Class2);
+ dynamic f2b = #C2;
+ dynamic c2b = f2b{dynamic}.call();
+ self::expect(true, c2b is{ForNonNullableByDefault} mai::Class2);
+ self::expect(true, core::identical(f2a, f2b));
+ () → mai::Class2 f2c = #C3;
+ mai::Class2 c2c = f2c(){() → mai::Class2};
+ self::expect(true, c2c is{ForNonNullableByDefault} mai::Class2);
+ dynamic f2d = #C3;
+ dynamic c2d = f2d{dynamic}.call();
+ self::expect(true, c2d is{ForNonNullableByDefault} mai::Class2);
+ self::expect(true, core::identical(f2c, f2d));
+ (core::int) → mai::Class3 f3a = #C4;
+ mai::Class3 c3a = f3a(42){(core::int) → mai::Class3};
+ self::expect(42, c3a.{mai::Class3::field}{core::int});
+ () → Null {
+ let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:44:8: Error: Too few positional arguments: 1 required, 0 given.
+ f3a(); // error
+ ^" in f3a{<inapplicable>}.();
+ let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:45:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f3a(42, 87); // error
+ ^" in f3a{<inapplicable>}.(42, 87);
+ };
+ dynamic f3b = #C4;
+ dynamic c3b = f3b{dynamic}.call(87);
+ self::expect(87, c3b{dynamic}.field);
+ self::throws(() → dynamic => f3b{dynamic}.call());
+ self::throws(() → dynamic => f3b{dynamic}.call(42, 87));
+ <T extends core::Object? = dynamic>() → mai::Class4<T%> f4a = #C5;
+ mai::Class4<dynamic> c4a = f4a<dynamic>(){() → mai::Class4<dynamic>};
+ self::expect(true, c4a is{ForNonNullableByDefault} mai::Class4<dynamic>);
+ self::expect(false, c4a is{ForNonNullableByDefault} mai::Class4<core::int>);
+ mai::Class4<core::int> c4b = f4a<core::int>(){() → mai::Class4<core::int>};
+ self::expect(true, c4b is{ForNonNullableByDefault} mai::Class4<core::int>);
+ self::expect(false, c4b is{ForNonNullableByDefault} mai::Class4<core::String>);
+ () → Null {
+ let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:62:8: Error: Expected 1 type arguments.
+ f4a<int, String>(); // error
+ ^" in f4a{<inapplicable>}.<core::int, core::String>();
+ };
+ () → mai::Class4<core::int> f4b = f4a<core::int>;
+ mai::Class4<core::int> c4c = f4b(){() → mai::Class4<core::int>};
+ self::expect(true, c4c is{ForNonNullableByDefault} mai::Class4<core::int>);
+ self::expect(false, c4c is{ForNonNullableByDefault} mai::Class4<core::String>);
+ () → Null {
+ let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:70:8: Error: Expected 0 type arguments.
+ f4b<int>(); // error
+ ^" in f4b{<inapplicable>}.<core::int>();
+ };
+ dynamic f4c = #C5;
+ dynamic c4d = f4c{dynamic}.call();
+ self::expect(true, c4d is{ForNonNullableByDefault} mai::Class4<dynamic>);
+ self::expect(false, c4d is{ForNonNullableByDefault} mai::Class4<core::int>);
+ self::throws(() → dynamic => f4c{dynamic}.call<core::int, core::String>());
+ <T extends core::Object? = dynamic>() → mai::Class4<T%> f4d = #C6;
+ mai::Class4<dynamic> c4e = f4d<dynamic>(){() → mai::Class4<dynamic>};
+ self::expect(true, c4e is{ForNonNullableByDefault} mai::Class4<dynamic>);
+ self::expect(false, c4e is{ForNonNullableByDefault} mai::Class4<core::int>);
+ mai::Class4<core::int> c4f = f4d<core::int>(){() → mai::Class4<core::int>};
+ self::expect(true, c4f is{ForNonNullableByDefault} mai::Class4<core::int>);
+ self::expect(false, c4f is{ForNonNullableByDefault} mai::Class4<core::String>);
+ () → Null {
+ let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:87:8: Error: Expected 1 type arguments.
+ f4d<int, String>(); // error
+ ^" in f4d{<inapplicable>}.<core::int, core::String>();
+ };
+ () → mai::Class4<core::int> f4e = f4d<core::int>;
+ mai::Class4<core::int> c4g = f4e(){() → mai::Class4<core::int>};
+ self::expect(true, c4g is{ForNonNullableByDefault} mai::Class4<core::int>);
+ self::expect(false, c4g is{ForNonNullableByDefault} mai::Class4<core::String>);
+ () → Null {
+ let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:95:8: Error: Expected 0 type arguments.
+ f4e<int>(); // error
+ ^" in f4e{<inapplicable>}.<core::int>();
+ };
+ dynamic f4f = #C6;
+ dynamic c4h = f4f{dynamic}.call();
+ self::expect(true, c4h is{ForNonNullableByDefault} mai::Class4<dynamic>);
+ self::expect(false, c4h is{ForNonNullableByDefault} mai::Class4<core::int>);
+ self::throws(() → dynamic => f4f{dynamic}.call<core::int, core::String>());
+ <T extends core::num>() → mai::Class5<T> f5a = #C7;
+ mai::Class5<core::num> c5a = f5a<core::num>(){() → mai::Class5<core::num>};
+ self::expect(true, c5a is{ForNonNullableByDefault} mai::Class5<core::num>);
+ self::expect(false, c5a is{ForNonNullableByDefault} mai::Class5<core::int>);
+ mai::Class5<core::int> c5b = f5a<core::int>(){() → mai::Class5<core::int>};
+ self::expect(true, c5b is{ForNonNullableByDefault} mai::Class5<core::int>);
+ self::expect(false, c5b is{ForNonNullableByDefault} mai::Class5<core::double>);
+ () → Null {
+ f5a<core::String>(){() → mai::Class5<core::String>};
+ let final Never #t7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:113:8: Error: Expected 1 type arguments.
+ f5a<int, String>(); // error
+ ^" in f5a{<inapplicable>}.<core::int, core::String>();
+ };
+ dynamic f5b = #C7;
+ dynamic c5c = f5b{dynamic}.call();
+ self::expect(true, c5c is{ForNonNullableByDefault} mai::Class5<core::num>);
+ self::expect(false, c5c is{ForNonNullableByDefault} mai::Class5<core::int>);
+ dynamic c5d = f5b{dynamic}.call<core::int>();
+ self::expect(true, c5d is{ForNonNullableByDefault} mai::Class5<core::int>);
+ self::expect(false, c5d is{ForNonNullableByDefault} mai::Class5<core::double>);
+ self::throws(() → dynamic => f5b{dynamic}.call<core::String>());
+ self::throws(() → dynamic => f5b{dynamic}.call<core::int, core::String>());
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C8}) → dynamic {
+ try {
+ f(){() → dynamic};
+ }
+ on core::Object catch(final core::Object e) {
+ core::print("Thrown: ${e}");
+ return;
+ }
+ if(!self::inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw "Expected exception";
+}
+
+library /*isNonNullableByDefault*/;
+import self as mai;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+ synthetic constructor •() → mai::Class1
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff() → mai::Class1
+ return new mai::Class1::•();
+}
+class Class2 extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[mai::Class2::redirect]/*isLegacy*/;
+ constructor named() → mai::Class2
+ : super core::Object::•()
+ ;
+ static method _#named#tearOff() → mai::Class2
+ return new mai::Class2::named();
+ static factory redirect() → mai::Class2
+ let dynamic #redirecting_factory = mai::Class2::named in invalid-expression;
+ static method _#redirect#tearOff() → mai::Class2
+ return new mai::Class2::named();
+}
+class Class3 extends core::Object {
+ final field core::int field;
+ constructor •(core::int field) → mai::Class3
+ : mai::Class3::field = field, super core::Object::•()
+ ;
+ static method _#new#tearOff(core::int field) → mai::Class3
+ return new mai::Class3::•(field);
+}
+class Class4<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[mai::Class4::redirect]/*isLegacy*/;
+ constructor _() → mai::Class4<mai::Class4::T%>
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff<T extends core::Object? = dynamic>() → mai::Class4<mai::Class4::_#_#tearOff::T%>
+ return new mai::Class4::_<mai::Class4::_#_#tearOff::T%>();
+ static factory •<T extends core::Object? = dynamic>() → mai::Class4<mai::Class4::•::T%>
+ return new mai::Class4::_<mai::Class4::•::T%>();
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → mai::Class4<mai::Class4::_#new#tearOff::T%>
+ return mai::Class4::•<mai::Class4::_#new#tearOff::T%>();
+ static factory redirect<T extends core::Object? = dynamic>() → mai::Class4<mai::Class4::redirect::T%>
+ let dynamic #redirecting_factory = mai::Class4::_ in let mai::Class4::redirect::T% #typeArg0 = null in invalid-expression;
+ static method _#redirect#tearOff<T extends core::Object? = dynamic>() → mai::Class4<mai::Class4::_#redirect#tearOff::T%>
+ return new mai::Class4::_<mai::Class4::_#redirect#tearOff::T%>();
+}
+class Class5<T extends core::num> extends core::Object {
+ constructor _() → mai::Class5<mai::Class5::T>
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff<T extends core::num>() → mai::Class5<mai::Class5::_#_#tearOff::T>
+ return new mai::Class5::_<mai::Class5::_#_#tearOff::T>();
+ static factory •<T extends core::num>() → mai::Class5<mai::Class5::•::T>
+ return new mai::Class5::_<mai::Class5::•::T>();
+ static method _#new#tearOff<T extends core::num>() → mai::Class5<mai::Class5::_#new#tearOff::T>
+ return mai::Class5::•<mai::Class5::_#new#tearOff::T>();
+}
+
+constants {
+ #C1 = static-tearoff mai::Class1::_#new#tearOff
+ #C2 = static-tearoff mai::Class2::_#named#tearOff
+ #C3 = static-tearoff mai::Class2::_#redirect#tearOff
+ #C4 = static-tearoff mai::Class3::_#new#tearOff
+ #C5 = static-tearoff mai::Class4::_#new#tearOff
+ #C6 = static-tearoff mai::Class4::_#redirect#tearOff
+ #C7 = static-tearoff mai::Class5::_#new#tearOff
+ #C8 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart.strong.transformed.expect
new file mode 100644
index 0000000..9edd33a
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart.strong.transformed.expect
@@ -0,0 +1,246 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:44:8: Error: Too few positional arguments: 1 required, 0 given.
+// f3a(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:45:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f3a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:62:8: Error: Expected 1 type arguments.
+// f4a<int, String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:70:8: Error: Expected 0 type arguments.
+// f4b<int>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:87:8: Error: Expected 1 type arguments.
+// f4d<int, String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:95:8: Error: Expected 0 type arguments.
+// f4e<int>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:112:8: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'T' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+// f5a<String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:113:8: Error: Expected 1 type arguments.
+// f5a<int, String>(); // error
+// ^
+//
+import self as self;
+import "main_lib.dart" as mai;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///main_lib.dart";
+
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+ () → mai::Class1 f1a = #C1;
+ mai::Class1 c1a = f1a(){() → mai::Class1};
+ self::expect(true, c1a is{ForNonNullableByDefault} mai::Class1);
+ dynamic f1b = #C1;
+ dynamic c1b = f1b{dynamic}.call();
+ self::expect(true, c1b is{ForNonNullableByDefault} mai::Class1);
+ self::expect(true, core::identical(f1a, f1b));
+ () → mai::Class2 f2a = #C2;
+ mai::Class2 c2a = f2a(){() → mai::Class2};
+ self::expect(true, c2a is{ForNonNullableByDefault} mai::Class2);
+ dynamic f2b = #C2;
+ dynamic c2b = f2b{dynamic}.call();
+ self::expect(true, c2b is{ForNonNullableByDefault} mai::Class2);
+ self::expect(true, core::identical(f2a, f2b));
+ () → mai::Class2 f2c = #C3;
+ mai::Class2 c2c = f2c(){() → mai::Class2};
+ self::expect(true, c2c is{ForNonNullableByDefault} mai::Class2);
+ dynamic f2d = #C3;
+ dynamic c2d = f2d{dynamic}.call();
+ self::expect(true, c2d is{ForNonNullableByDefault} mai::Class2);
+ self::expect(true, core::identical(f2c, f2d));
+ (core::int) → mai::Class3 f3a = #C4;
+ mai::Class3 c3a = f3a(42){(core::int) → mai::Class3};
+ self::expect(42, c3a.{mai::Class3::field}{core::int});
+ () → Null {
+ let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:44:8: Error: Too few positional arguments: 1 required, 0 given.
+ f3a(); // error
+ ^" in f3a{<inapplicable>}.();
+ let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:45:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f3a(42, 87); // error
+ ^" in f3a{<inapplicable>}.(42, 87);
+ };
+ dynamic f3b = #C4;
+ dynamic c3b = f3b{dynamic}.call(87);
+ self::expect(87, c3b{dynamic}.field);
+ self::throws(() → dynamic => f3b{dynamic}.call());
+ self::throws(() → dynamic => f3b{dynamic}.call(42, 87));
+ <T extends core::Object? = dynamic>() → mai::Class4<T%> f4a = #C5;
+ mai::Class4<dynamic> c4a = f4a<dynamic>(){() → mai::Class4<dynamic>};
+ self::expect(true, c4a is{ForNonNullableByDefault} mai::Class4<dynamic>);
+ self::expect(false, c4a is{ForNonNullableByDefault} mai::Class4<core::int>);
+ mai::Class4<core::int> c4b = f4a<core::int>(){() → mai::Class4<core::int>};
+ self::expect(true, c4b is{ForNonNullableByDefault} mai::Class4<core::int>);
+ self::expect(false, c4b is{ForNonNullableByDefault} mai::Class4<core::String>);
+ () → Null {
+ let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:62:8: Error: Expected 1 type arguments.
+ f4a<int, String>(); // error
+ ^" in f4a{<inapplicable>}.<core::int, core::String>();
+ };
+ () → mai::Class4<core::int> f4b = f4a<core::int>;
+ mai::Class4<core::int> c4c = f4b(){() → mai::Class4<core::int>};
+ self::expect(true, c4c is{ForNonNullableByDefault} mai::Class4<core::int>);
+ self::expect(false, c4c is{ForNonNullableByDefault} mai::Class4<core::String>);
+ () → Null {
+ let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:70:8: Error: Expected 0 type arguments.
+ f4b<int>(); // error
+ ^" in f4b{<inapplicable>}.<core::int>();
+ };
+ dynamic f4c = #C5;
+ dynamic c4d = f4c{dynamic}.call();
+ self::expect(true, c4d is{ForNonNullableByDefault} mai::Class4<dynamic>);
+ self::expect(false, c4d is{ForNonNullableByDefault} mai::Class4<core::int>);
+ self::throws(() → dynamic => f4c{dynamic}.call<core::int, core::String>());
+ <T extends core::Object? = dynamic>() → mai::Class4<T%> f4d = #C6;
+ mai::Class4<dynamic> c4e = f4d<dynamic>(){() → mai::Class4<dynamic>};
+ self::expect(true, c4e is{ForNonNullableByDefault} mai::Class4<dynamic>);
+ self::expect(false, c4e is{ForNonNullableByDefault} mai::Class4<core::int>);
+ mai::Class4<core::int> c4f = f4d<core::int>(){() → mai::Class4<core::int>};
+ self::expect(true, c4f is{ForNonNullableByDefault} mai::Class4<core::int>);
+ self::expect(false, c4f is{ForNonNullableByDefault} mai::Class4<core::String>);
+ () → Null {
+ let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:87:8: Error: Expected 1 type arguments.
+ f4d<int, String>(); // error
+ ^" in f4d{<inapplicable>}.<core::int, core::String>();
+ };
+ () → mai::Class4<core::int> f4e = f4d<core::int>;
+ mai::Class4<core::int> c4g = f4e(){() → mai::Class4<core::int>};
+ self::expect(true, c4g is{ForNonNullableByDefault} mai::Class4<core::int>);
+ self::expect(false, c4g is{ForNonNullableByDefault} mai::Class4<core::String>);
+ () → Null {
+ let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:95:8: Error: Expected 0 type arguments.
+ f4e<int>(); // error
+ ^" in f4e{<inapplicable>}.<core::int>();
+ };
+ dynamic f4f = #C6;
+ dynamic c4h = f4f{dynamic}.call();
+ self::expect(true, c4h is{ForNonNullableByDefault} mai::Class4<dynamic>);
+ self::expect(false, c4h is{ForNonNullableByDefault} mai::Class4<core::int>);
+ self::throws(() → dynamic => f4f{dynamic}.call<core::int, core::String>());
+ <T extends core::num>() → mai::Class5<T> f5a = #C7;
+ mai::Class5<core::num> c5a = f5a<core::num>(){() → mai::Class5<core::num>};
+ self::expect(true, c5a is{ForNonNullableByDefault} mai::Class5<core::num>);
+ self::expect(false, c5a is{ForNonNullableByDefault} mai::Class5<core::int>);
+ mai::Class5<core::int> c5b = f5a<core::int>(){() → mai::Class5<core::int>};
+ self::expect(true, c5b is{ForNonNullableByDefault} mai::Class5<core::int>);
+ self::expect(false, c5b is{ForNonNullableByDefault} mai::Class5<core::double>);
+ () → Null {
+ f5a<core::String>(){() → mai::Class5<core::String>};
+ let final Never #t7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:113:8: Error: Expected 1 type arguments.
+ f5a<int, String>(); // error
+ ^" in f5a{<inapplicable>}.<core::int, core::String>();
+ };
+ dynamic f5b = #C7;
+ dynamic c5c = f5b{dynamic}.call();
+ self::expect(true, c5c is{ForNonNullableByDefault} mai::Class5<core::num>);
+ self::expect(false, c5c is{ForNonNullableByDefault} mai::Class5<core::int>);
+ dynamic c5d = f5b{dynamic}.call<core::int>();
+ self::expect(true, c5d is{ForNonNullableByDefault} mai::Class5<core::int>);
+ self::expect(false, c5d is{ForNonNullableByDefault} mai::Class5<core::double>);
+ self::throws(() → dynamic => f5b{dynamic}.call<core::String>());
+ self::throws(() → dynamic => f5b{dynamic}.call<core::int, core::String>());
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C8}) → dynamic {
+ try {
+ f(){() → dynamic};
+ }
+ on core::Object catch(final core::Object e) {
+ core::print("Thrown: ${e}");
+ return;
+ }
+ if(!self::inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw "Expected exception";
+}
+
+library /*isNonNullableByDefault*/;
+import self as mai;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+ synthetic constructor •() → mai::Class1
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff() → mai::Class1
+ return new mai::Class1::•();
+}
+class Class2 extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[mai::Class2::redirect]/*isLegacy*/;
+ constructor named() → mai::Class2
+ : super core::Object::•()
+ ;
+ static method _#named#tearOff() → mai::Class2
+ return new mai::Class2::named();
+ static factory redirect() → mai::Class2
+ let Never #redirecting_factory = mai::Class2::named in invalid-expression;
+ static method _#redirect#tearOff() → mai::Class2
+ return new mai::Class2::named();
+}
+class Class3 extends core::Object {
+ final field core::int field;
+ constructor •(core::int field) → mai::Class3
+ : mai::Class3::field = field, super core::Object::•()
+ ;
+ static method _#new#tearOff(core::int field) → mai::Class3
+ return new mai::Class3::•(field);
+}
+class Class4<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[mai::Class4::redirect]/*isLegacy*/;
+ constructor _() → mai::Class4<mai::Class4::T%>
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff<T extends core::Object? = dynamic>() → mai::Class4<mai::Class4::_#_#tearOff::T%>
+ return new mai::Class4::_<mai::Class4::_#_#tearOff::T%>();
+ static factory •<T extends core::Object? = dynamic>() → mai::Class4<mai::Class4::•::T%>
+ return new mai::Class4::_<mai::Class4::•::T%>();
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → mai::Class4<mai::Class4::_#new#tearOff::T%>
+ return mai::Class4::•<mai::Class4::_#new#tearOff::T%>();
+ static factory redirect<T extends core::Object? = dynamic>() → mai::Class4<mai::Class4::redirect::T%>
+ let Never #redirecting_factory = mai::Class4::_ in let mai::Class4::redirect::T% #typeArg0 = null in invalid-expression;
+ static method _#redirect#tearOff<T extends core::Object? = dynamic>() → mai::Class4<mai::Class4::_#redirect#tearOff::T%>
+ return new mai::Class4::_<mai::Class4::_#redirect#tearOff::T%>();
+}
+class Class5<T extends core::num> extends core::Object {
+ constructor _() → mai::Class5<mai::Class5::T>
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff<T extends core::num>() → mai::Class5<mai::Class5::_#_#tearOff::T>
+ return new mai::Class5::_<mai::Class5::_#_#tearOff::T>();
+ static factory •<T extends core::num>() → mai::Class5<mai::Class5::•::T>
+ return new mai::Class5::_<mai::Class5::•::T>();
+ static method _#new#tearOff<T extends core::num>() → mai::Class5<mai::Class5::_#new#tearOff::T>
+ return mai::Class5::•<mai::Class5::_#new#tearOff::T>();
+}
+
+constants {
+ #C1 = static-tearoff mai::Class1::_#new#tearOff
+ #C2 = static-tearoff mai::Class2::_#named#tearOff
+ #C3 = static-tearoff mai::Class2::_#redirect#tearOff
+ #C4 = static-tearoff mai::Class3::_#new#tearOff
+ #C5 = static-tearoff mai::Class4::_#new#tearOff
+ #C6 = static-tearoff mai::Class4::_#redirect#tearOff
+ #C7 = static-tearoff mai::Class5::_#new#tearOff
+ #C8 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart.textual_outline.expect
new file mode 100644
index 0000000..4166ca7
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart.textual_outline.expect
@@ -0,0 +1,6 @@
+import 'main_lib.dart';
+
+final bool inSoundMode = <int?>[] is! List<int>;
+main() {}
+expect(expected, actual) {}
+throws(Function() f, {bool inSoundModeOnly: false}) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..26f0c41
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart.textual_outline_modelled.expect
@@ -0,0 +1,6 @@
+import 'main_lib.dart';
+
+expect(expected, actual) {}
+final bool inSoundMode = <int?>[] is! List<int>;
+main() {}
+throws(Function() f, {bool inSoundModeOnly: false}) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart.weak.expect
new file mode 100644
index 0000000..1806fdc
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart.weak.expect
@@ -0,0 +1,246 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:44:8: Error: Too few positional arguments: 1 required, 0 given.
+// f3a(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:45:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f3a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:62:8: Error: Expected 1 type arguments.
+// f4a<int, String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:70:8: Error: Expected 0 type arguments.
+// f4b<int>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:87:8: Error: Expected 1 type arguments.
+// f4d<int, String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:95:8: Error: Expected 0 type arguments.
+// f4e<int>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:112:8: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'T' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+// f5a<String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:113:8: Error: Expected 1 type arguments.
+// f5a<int, String>(); // error
+// ^
+//
+import self as self;
+import "main_lib.dart" as mai;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///main_lib.dart";
+
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+ () → mai::Class1 f1a = #C1;
+ mai::Class1 c1a = f1a(){() → mai::Class1};
+ self::expect(true, c1a is{ForNonNullableByDefault} mai::Class1);
+ dynamic f1b = #C1;
+ dynamic c1b = f1b{dynamic}.call();
+ self::expect(true, c1b is{ForNonNullableByDefault} mai::Class1);
+ self::expect(true, core::identical(f1a, f1b));
+ () → mai::Class2 f2a = #C2;
+ mai::Class2 c2a = f2a(){() → mai::Class2};
+ self::expect(true, c2a is{ForNonNullableByDefault} mai::Class2);
+ dynamic f2b = #C2;
+ dynamic c2b = f2b{dynamic}.call();
+ self::expect(true, c2b is{ForNonNullableByDefault} mai::Class2);
+ self::expect(true, core::identical(f2a, f2b));
+ () → mai::Class2 f2c = #C3;
+ mai::Class2 c2c = f2c(){() → mai::Class2};
+ self::expect(true, c2c is{ForNonNullableByDefault} mai::Class2);
+ dynamic f2d = #C3;
+ dynamic c2d = f2d{dynamic}.call();
+ self::expect(true, c2d is{ForNonNullableByDefault} mai::Class2);
+ self::expect(true, core::identical(f2c, f2d));
+ (core::int) → mai::Class3 f3a = #C4;
+ mai::Class3 c3a = f3a(42){(core::int) → mai::Class3};
+ self::expect(42, c3a.{mai::Class3::field}{core::int});
+ () → Null {
+ let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:44:8: Error: Too few positional arguments: 1 required, 0 given.
+ f3a(); // error
+ ^" in f3a{<inapplicable>}.();
+ let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:45:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f3a(42, 87); // error
+ ^" in f3a{<inapplicable>}.(42, 87);
+ };
+ dynamic f3b = #C4;
+ dynamic c3b = f3b{dynamic}.call(87);
+ self::expect(87, c3b{dynamic}.field);
+ self::throws(() → dynamic => f3b{dynamic}.call());
+ self::throws(() → dynamic => f3b{dynamic}.call(42, 87));
+ <T extends core::Object? = dynamic>() → mai::Class4<T%> f4a = #C5;
+ mai::Class4<dynamic> c4a = f4a<dynamic>(){() → mai::Class4<dynamic>};
+ self::expect(true, c4a is{ForNonNullableByDefault} mai::Class4<dynamic>);
+ self::expect(false, c4a is{ForNonNullableByDefault} mai::Class4<core::int>);
+ mai::Class4<core::int> c4b = f4a<core::int>(){() → mai::Class4<core::int>};
+ self::expect(true, c4b is{ForNonNullableByDefault} mai::Class4<core::int>);
+ self::expect(false, c4b is{ForNonNullableByDefault} mai::Class4<core::String>);
+ () → Null {
+ let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:62:8: Error: Expected 1 type arguments.
+ f4a<int, String>(); // error
+ ^" in f4a{<inapplicable>}.<core::int, core::String>();
+ };
+ () → mai::Class4<core::int> f4b = f4a<core::int>;
+ mai::Class4<core::int> c4c = f4b(){() → mai::Class4<core::int>};
+ self::expect(true, c4c is{ForNonNullableByDefault} mai::Class4<core::int>);
+ self::expect(false, c4c is{ForNonNullableByDefault} mai::Class4<core::String>);
+ () → Null {
+ let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:70:8: Error: Expected 0 type arguments.
+ f4b<int>(); // error
+ ^" in f4b{<inapplicable>}.<core::int>();
+ };
+ dynamic f4c = #C5;
+ dynamic c4d = f4c{dynamic}.call();
+ self::expect(true, c4d is{ForNonNullableByDefault} mai::Class4<dynamic>);
+ self::expect(false, c4d is{ForNonNullableByDefault} mai::Class4<core::int>);
+ self::throws(() → dynamic => f4c{dynamic}.call<core::int, core::String>());
+ <T extends core::Object? = dynamic>() → mai::Class4<T%> f4d = #C6;
+ mai::Class4<dynamic> c4e = f4d<dynamic>(){() → mai::Class4<dynamic>};
+ self::expect(true, c4e is{ForNonNullableByDefault} mai::Class4<dynamic>);
+ self::expect(false, c4e is{ForNonNullableByDefault} mai::Class4<core::int>);
+ mai::Class4<core::int> c4f = f4d<core::int>(){() → mai::Class4<core::int>};
+ self::expect(true, c4f is{ForNonNullableByDefault} mai::Class4<core::int>);
+ self::expect(false, c4f is{ForNonNullableByDefault} mai::Class4<core::String>);
+ () → Null {
+ let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:87:8: Error: Expected 1 type arguments.
+ f4d<int, String>(); // error
+ ^" in f4d{<inapplicable>}.<core::int, core::String>();
+ };
+ () → mai::Class4<core::int> f4e = f4d<core::int>;
+ mai::Class4<core::int> c4g = f4e(){() → mai::Class4<core::int>};
+ self::expect(true, c4g is{ForNonNullableByDefault} mai::Class4<core::int>);
+ self::expect(false, c4g is{ForNonNullableByDefault} mai::Class4<core::String>);
+ () → Null {
+ let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:95:8: Error: Expected 0 type arguments.
+ f4e<int>(); // error
+ ^" in f4e{<inapplicable>}.<core::int>();
+ };
+ dynamic f4f = #C6;
+ dynamic c4h = f4f{dynamic}.call();
+ self::expect(true, c4h is{ForNonNullableByDefault} mai::Class4<dynamic>);
+ self::expect(false, c4h is{ForNonNullableByDefault} mai::Class4<core::int>);
+ self::throws(() → dynamic => f4f{dynamic}.call<core::int, core::String>());
+ <T extends core::num>() → mai::Class5<T> f5a = #C7;
+ mai::Class5<core::num> c5a = f5a<core::num>(){() → mai::Class5<core::num>};
+ self::expect(true, c5a is{ForNonNullableByDefault} mai::Class5<core::num>);
+ self::expect(false, c5a is{ForNonNullableByDefault} mai::Class5<core::int>);
+ mai::Class5<core::int> c5b = f5a<core::int>(){() → mai::Class5<core::int>};
+ self::expect(true, c5b is{ForNonNullableByDefault} mai::Class5<core::int>);
+ self::expect(false, c5b is{ForNonNullableByDefault} mai::Class5<core::double>);
+ () → Null {
+ f5a<core::String>(){() → mai::Class5<core::String>};
+ let final Never #t7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:113:8: Error: Expected 1 type arguments.
+ f5a<int, String>(); // error
+ ^" in f5a{<inapplicable>}.<core::int, core::String>();
+ };
+ dynamic f5b = #C7;
+ dynamic c5c = f5b{dynamic}.call();
+ self::expect(true, c5c is{ForNonNullableByDefault} mai::Class5<core::num>);
+ self::expect(false, c5c is{ForNonNullableByDefault} mai::Class5<core::int>);
+ dynamic c5d = f5b{dynamic}.call<core::int>();
+ self::expect(true, c5d is{ForNonNullableByDefault} mai::Class5<core::int>);
+ self::expect(false, c5d is{ForNonNullableByDefault} mai::Class5<core::double>);
+ self::throws(() → dynamic => f5b{dynamic}.call<core::String>());
+ self::throws(() → dynamic => f5b{dynamic}.call<core::int, core::String>());
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C8}) → dynamic {
+ try {
+ f(){() → dynamic};
+ }
+ on core::Object catch(final core::Object e) {
+ core::print("Thrown: ${e}");
+ return;
+ }
+ if(!self::inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw "Expected exception";
+}
+
+library /*isNonNullableByDefault*/;
+import self as mai;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+ synthetic constructor •() → mai::Class1
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff() → mai::Class1
+ return new mai::Class1::•();
+}
+class Class2 extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[mai::Class2::redirect]/*isLegacy*/;
+ constructor named() → mai::Class2
+ : super core::Object::•()
+ ;
+ static method _#named#tearOff() → mai::Class2
+ return new mai::Class2::named();
+ static factory redirect() → mai::Class2
+ let dynamic #redirecting_factory = mai::Class2::named in invalid-expression;
+ static method _#redirect#tearOff() → mai::Class2
+ return new mai::Class2::named();
+}
+class Class3 extends core::Object {
+ final field core::int field;
+ constructor •(core::int field) → mai::Class3
+ : mai::Class3::field = field, super core::Object::•()
+ ;
+ static method _#new#tearOff(core::int field) → mai::Class3
+ return new mai::Class3::•(field);
+}
+class Class4<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[mai::Class4::redirect]/*isLegacy*/;
+ constructor _() → mai::Class4<mai::Class4::T%>
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff<T extends core::Object? = dynamic>() → mai::Class4<mai::Class4::_#_#tearOff::T%>
+ return new mai::Class4::_<mai::Class4::_#_#tearOff::T%>();
+ static factory •<T extends core::Object? = dynamic>() → mai::Class4<mai::Class4::•::T%>
+ return new mai::Class4::_<mai::Class4::•::T%>();
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → mai::Class4<mai::Class4::_#new#tearOff::T%>
+ return mai::Class4::•<mai::Class4::_#new#tearOff::T%>();
+ static factory redirect<T extends core::Object? = dynamic>() → mai::Class4<mai::Class4::redirect::T%>
+ let dynamic #redirecting_factory = mai::Class4::_ in let mai::Class4::redirect::T% #typeArg0 = null in invalid-expression;
+ static method _#redirect#tearOff<T extends core::Object? = dynamic>() → mai::Class4<mai::Class4::_#redirect#tearOff::T%>
+ return new mai::Class4::_<mai::Class4::_#redirect#tearOff::T%>();
+}
+class Class5<T extends core::num> extends core::Object {
+ constructor _() → mai::Class5<mai::Class5::T>
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff<T extends core::num>() → mai::Class5<mai::Class5::_#_#tearOff::T>
+ return new mai::Class5::_<mai::Class5::_#_#tearOff::T>();
+ static factory •<T extends core::num>() → mai::Class5<mai::Class5::•::T>
+ return new mai::Class5::_<mai::Class5::•::T>();
+ static method _#new#tearOff<T extends core::num>() → mai::Class5<mai::Class5::_#new#tearOff::T>
+ return mai::Class5::•<mai::Class5::_#new#tearOff::T>();
+}
+
+constants {
+ #C1 = static-tearoff mai::Class1::_#new#tearOff
+ #C2 = static-tearoff mai::Class2::_#named#tearOff
+ #C3 = static-tearoff mai::Class2::_#redirect#tearOff
+ #C4 = static-tearoff mai::Class3::_#new#tearOff
+ #C5 = static-tearoff mai::Class4::_#new#tearOff
+ #C6 = static-tearoff mai::Class4::_#redirect#tearOff
+ #C7 = static-tearoff mai::Class5::_#new#tearOff
+ #C8 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart.weak.outline.expect
new file mode 100644
index 0000000..a682b15
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart.weak.outline.expect
@@ -0,0 +1,67 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///main_lib.dart";
+
+static final field core::bool inSoundMode;
+static method main() → dynamic
+ ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+ ;
+static method throws(() → dynamic f, {core::bool inSoundModeOnly}) → dynamic
+ ;
+
+library /*isNonNullableByDefault*/;
+import self as self2;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+ synthetic constructor •() → self2::Class1
+ ;
+ static method _#new#tearOff() → self2::Class1
+ return new self2::Class1::•();
+}
+class Class2 extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self2::Class2::redirect]/*isLegacy*/;
+ constructor named() → self2::Class2
+ ;
+ static method _#named#tearOff() → self2::Class2
+ return new self2::Class2::named();
+ static factory redirect() → self2::Class2
+ let dynamic #redirecting_factory = self2::Class2::named in invalid-expression;
+ static method _#redirect#tearOff() → self2::Class2
+ return new self2::Class2::named();
+}
+class Class3 extends core::Object {
+ final field core::int field;
+ constructor •(core::int field) → self2::Class3
+ ;
+ static method _#new#tearOff(core::int field) → self2::Class3
+ return new self2::Class3::•(field);
+}
+class Class4<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self2::Class4::redirect]/*isLegacy*/;
+ constructor _() → self2::Class4<self2::Class4::T%>
+ ;
+ static method _#_#tearOff<T extends core::Object? = dynamic>() → self2::Class4<self2::Class4::_#_#tearOff::T%>
+ return new self2::Class4::_<self2::Class4::_#_#tearOff::T%>();
+ static factory •<T extends core::Object? = dynamic>() → self2::Class4<self2::Class4::•::T%>
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self2::Class4<self2::Class4::_#new#tearOff::T%>
+ return self2::Class4::•<self2::Class4::_#new#tearOff::T%>();
+ static factory redirect<T extends core::Object? = dynamic>() → self2::Class4<self2::Class4::redirect::T%>
+ let dynamic #redirecting_factory = self2::Class4::_ in let self2::Class4::redirect::T% #typeArg0 = null in invalid-expression;
+ static method _#redirect#tearOff<T extends core::Object? = dynamic>() → self2::Class4<self2::Class4::_#redirect#tearOff::T%>
+ return new self2::Class4::_<self2::Class4::_#redirect#tearOff::T%>();
+}
+class Class5<T extends core::num> extends core::Object {
+ constructor _() → self2::Class5<self2::Class5::T>
+ ;
+ static method _#_#tearOff<T extends core::num>() → self2::Class5<self2::Class5::_#_#tearOff::T>
+ return new self2::Class5::_<self2::Class5::_#_#tearOff::T>();
+ static factory •<T extends core::num>() → self2::Class5<self2::Class5::•::T>
+ ;
+ static method _#new#tearOff<T extends core::num>() → self2::Class5<self2::Class5::_#new#tearOff::T>
+ return self2::Class5::•<self2::Class5::_#new#tearOff::T>();
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart.weak.transformed.expect
new file mode 100644
index 0000000..9edd33a
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart.weak.transformed.expect
@@ -0,0 +1,246 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:44:8: Error: Too few positional arguments: 1 required, 0 given.
+// f3a(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:45:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f3a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:62:8: Error: Expected 1 type arguments.
+// f4a<int, String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:70:8: Error: Expected 0 type arguments.
+// f4b<int>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:87:8: Error: Expected 1 type arguments.
+// f4d<int, String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:95:8: Error: Expected 0 type arguments.
+// f4e<int>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:112:8: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'T' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+// f5a<String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:113:8: Error: Expected 1 type arguments.
+// f5a<int, String>(); // error
+// ^
+//
+import self as self;
+import "main_lib.dart" as mai;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///main_lib.dart";
+
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+ () → mai::Class1 f1a = #C1;
+ mai::Class1 c1a = f1a(){() → mai::Class1};
+ self::expect(true, c1a is{ForNonNullableByDefault} mai::Class1);
+ dynamic f1b = #C1;
+ dynamic c1b = f1b{dynamic}.call();
+ self::expect(true, c1b is{ForNonNullableByDefault} mai::Class1);
+ self::expect(true, core::identical(f1a, f1b));
+ () → mai::Class2 f2a = #C2;
+ mai::Class2 c2a = f2a(){() → mai::Class2};
+ self::expect(true, c2a is{ForNonNullableByDefault} mai::Class2);
+ dynamic f2b = #C2;
+ dynamic c2b = f2b{dynamic}.call();
+ self::expect(true, c2b is{ForNonNullableByDefault} mai::Class2);
+ self::expect(true, core::identical(f2a, f2b));
+ () → mai::Class2 f2c = #C3;
+ mai::Class2 c2c = f2c(){() → mai::Class2};
+ self::expect(true, c2c is{ForNonNullableByDefault} mai::Class2);
+ dynamic f2d = #C3;
+ dynamic c2d = f2d{dynamic}.call();
+ self::expect(true, c2d is{ForNonNullableByDefault} mai::Class2);
+ self::expect(true, core::identical(f2c, f2d));
+ (core::int) → mai::Class3 f3a = #C4;
+ mai::Class3 c3a = f3a(42){(core::int) → mai::Class3};
+ self::expect(42, c3a.{mai::Class3::field}{core::int});
+ () → Null {
+ let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:44:8: Error: Too few positional arguments: 1 required, 0 given.
+ f3a(); // error
+ ^" in f3a{<inapplicable>}.();
+ let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:45:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f3a(42, 87); // error
+ ^" in f3a{<inapplicable>}.(42, 87);
+ };
+ dynamic f3b = #C4;
+ dynamic c3b = f3b{dynamic}.call(87);
+ self::expect(87, c3b{dynamic}.field);
+ self::throws(() → dynamic => f3b{dynamic}.call());
+ self::throws(() → dynamic => f3b{dynamic}.call(42, 87));
+ <T extends core::Object? = dynamic>() → mai::Class4<T%> f4a = #C5;
+ mai::Class4<dynamic> c4a = f4a<dynamic>(){() → mai::Class4<dynamic>};
+ self::expect(true, c4a is{ForNonNullableByDefault} mai::Class4<dynamic>);
+ self::expect(false, c4a is{ForNonNullableByDefault} mai::Class4<core::int>);
+ mai::Class4<core::int> c4b = f4a<core::int>(){() → mai::Class4<core::int>};
+ self::expect(true, c4b is{ForNonNullableByDefault} mai::Class4<core::int>);
+ self::expect(false, c4b is{ForNonNullableByDefault} mai::Class4<core::String>);
+ () → Null {
+ let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:62:8: Error: Expected 1 type arguments.
+ f4a<int, String>(); // error
+ ^" in f4a{<inapplicable>}.<core::int, core::String>();
+ };
+ () → mai::Class4<core::int> f4b = f4a<core::int>;
+ mai::Class4<core::int> c4c = f4b(){() → mai::Class4<core::int>};
+ self::expect(true, c4c is{ForNonNullableByDefault} mai::Class4<core::int>);
+ self::expect(false, c4c is{ForNonNullableByDefault} mai::Class4<core::String>);
+ () → Null {
+ let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:70:8: Error: Expected 0 type arguments.
+ f4b<int>(); // error
+ ^" in f4b{<inapplicable>}.<core::int>();
+ };
+ dynamic f4c = #C5;
+ dynamic c4d = f4c{dynamic}.call();
+ self::expect(true, c4d is{ForNonNullableByDefault} mai::Class4<dynamic>);
+ self::expect(false, c4d is{ForNonNullableByDefault} mai::Class4<core::int>);
+ self::throws(() → dynamic => f4c{dynamic}.call<core::int, core::String>());
+ <T extends core::Object? = dynamic>() → mai::Class4<T%> f4d = #C6;
+ mai::Class4<dynamic> c4e = f4d<dynamic>(){() → mai::Class4<dynamic>};
+ self::expect(true, c4e is{ForNonNullableByDefault} mai::Class4<dynamic>);
+ self::expect(false, c4e is{ForNonNullableByDefault} mai::Class4<core::int>);
+ mai::Class4<core::int> c4f = f4d<core::int>(){() → mai::Class4<core::int>};
+ self::expect(true, c4f is{ForNonNullableByDefault} mai::Class4<core::int>);
+ self::expect(false, c4f is{ForNonNullableByDefault} mai::Class4<core::String>);
+ () → Null {
+ let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:87:8: Error: Expected 1 type arguments.
+ f4d<int, String>(); // error
+ ^" in f4d{<inapplicable>}.<core::int, core::String>();
+ };
+ () → mai::Class4<core::int> f4e = f4d<core::int>;
+ mai::Class4<core::int> c4g = f4e(){() → mai::Class4<core::int>};
+ self::expect(true, c4g is{ForNonNullableByDefault} mai::Class4<core::int>);
+ self::expect(false, c4g is{ForNonNullableByDefault} mai::Class4<core::String>);
+ () → Null {
+ let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:95:8: Error: Expected 0 type arguments.
+ f4e<int>(); // error
+ ^" in f4e{<inapplicable>}.<core::int>();
+ };
+ dynamic f4f = #C6;
+ dynamic c4h = f4f{dynamic}.call();
+ self::expect(true, c4h is{ForNonNullableByDefault} mai::Class4<dynamic>);
+ self::expect(false, c4h is{ForNonNullableByDefault} mai::Class4<core::int>);
+ self::throws(() → dynamic => f4f{dynamic}.call<core::int, core::String>());
+ <T extends core::num>() → mai::Class5<T> f5a = #C7;
+ mai::Class5<core::num> c5a = f5a<core::num>(){() → mai::Class5<core::num>};
+ self::expect(true, c5a is{ForNonNullableByDefault} mai::Class5<core::num>);
+ self::expect(false, c5a is{ForNonNullableByDefault} mai::Class5<core::int>);
+ mai::Class5<core::int> c5b = f5a<core::int>(){() → mai::Class5<core::int>};
+ self::expect(true, c5b is{ForNonNullableByDefault} mai::Class5<core::int>);
+ self::expect(false, c5b is{ForNonNullableByDefault} mai::Class5<core::double>);
+ () → Null {
+ f5a<core::String>(){() → mai::Class5<core::String>};
+ let final Never #t7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main.dart:113:8: Error: Expected 1 type arguments.
+ f5a<int, String>(); // error
+ ^" in f5a{<inapplicable>}.<core::int, core::String>();
+ };
+ dynamic f5b = #C7;
+ dynamic c5c = f5b{dynamic}.call();
+ self::expect(true, c5c is{ForNonNullableByDefault} mai::Class5<core::num>);
+ self::expect(false, c5c is{ForNonNullableByDefault} mai::Class5<core::int>);
+ dynamic c5d = f5b{dynamic}.call<core::int>();
+ self::expect(true, c5d is{ForNonNullableByDefault} mai::Class5<core::int>);
+ self::expect(false, c5d is{ForNonNullableByDefault} mai::Class5<core::double>);
+ self::throws(() → dynamic => f5b{dynamic}.call<core::String>());
+ self::throws(() → dynamic => f5b{dynamic}.call<core::int, core::String>());
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C8}) → dynamic {
+ try {
+ f(){() → dynamic};
+ }
+ on core::Object catch(final core::Object e) {
+ core::print("Thrown: ${e}");
+ return;
+ }
+ if(!self::inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw "Expected exception";
+}
+
+library /*isNonNullableByDefault*/;
+import self as mai;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+ synthetic constructor •() → mai::Class1
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff() → mai::Class1
+ return new mai::Class1::•();
+}
+class Class2 extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[mai::Class2::redirect]/*isLegacy*/;
+ constructor named() → mai::Class2
+ : super core::Object::•()
+ ;
+ static method _#named#tearOff() → mai::Class2
+ return new mai::Class2::named();
+ static factory redirect() → mai::Class2
+ let Never #redirecting_factory = mai::Class2::named in invalid-expression;
+ static method _#redirect#tearOff() → mai::Class2
+ return new mai::Class2::named();
+}
+class Class3 extends core::Object {
+ final field core::int field;
+ constructor •(core::int field) → mai::Class3
+ : mai::Class3::field = field, super core::Object::•()
+ ;
+ static method _#new#tearOff(core::int field) → mai::Class3
+ return new mai::Class3::•(field);
+}
+class Class4<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[mai::Class4::redirect]/*isLegacy*/;
+ constructor _() → mai::Class4<mai::Class4::T%>
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff<T extends core::Object? = dynamic>() → mai::Class4<mai::Class4::_#_#tearOff::T%>
+ return new mai::Class4::_<mai::Class4::_#_#tearOff::T%>();
+ static factory •<T extends core::Object? = dynamic>() → mai::Class4<mai::Class4::•::T%>
+ return new mai::Class4::_<mai::Class4::•::T%>();
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → mai::Class4<mai::Class4::_#new#tearOff::T%>
+ return mai::Class4::•<mai::Class4::_#new#tearOff::T%>();
+ static factory redirect<T extends core::Object? = dynamic>() → mai::Class4<mai::Class4::redirect::T%>
+ let Never #redirecting_factory = mai::Class4::_ in let mai::Class4::redirect::T% #typeArg0 = null in invalid-expression;
+ static method _#redirect#tearOff<T extends core::Object? = dynamic>() → mai::Class4<mai::Class4::_#redirect#tearOff::T%>
+ return new mai::Class4::_<mai::Class4::_#redirect#tearOff::T%>();
+}
+class Class5<T extends core::num> extends core::Object {
+ constructor _() → mai::Class5<mai::Class5::T>
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff<T extends core::num>() → mai::Class5<mai::Class5::_#_#tearOff::T>
+ return new mai::Class5::_<mai::Class5::_#_#tearOff::T>();
+ static factory •<T extends core::num>() → mai::Class5<mai::Class5::•::T>
+ return new mai::Class5::_<mai::Class5::•::T>();
+ static method _#new#tearOff<T extends core::num>() → mai::Class5<mai::Class5::_#new#tearOff::T>
+ return mai::Class5::•<mai::Class5::_#new#tearOff::T>();
+}
+
+constants {
+ #C1 = static-tearoff mai::Class1::_#new#tearOff
+ #C2 = static-tearoff mai::Class2::_#named#tearOff
+ #C3 = static-tearoff mai::Class2::_#redirect#tearOff
+ #C4 = static-tearoff mai::Class3::_#new#tearOff
+ #C5 = static-tearoff mai::Class4::_#new#tearOff
+ #C6 = static-tearoff mai::Class4::_#redirect#tearOff
+ #C7 = static-tearoff mai::Class5::_#new#tearOff
+ #C8 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main_lib.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main_lib.dart
new file mode 100644
index 0000000..eed7823
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/main_lib.dart
@@ -0,0 +1,27 @@
+// 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 Class1 {}
+
+class Class2 {
+ Class2.named();
+ factory Class2.redirect() = Class2.named;
+}
+
+class Class3 {
+ final int field;
+
+ Class3(this.field);
+}
+
+class Class4<T> {
+ Class4._();
+ factory Class4() => new Class4<T>._();
+ factory Class4.redirect() = Class4._;
+}
+
+class Class5<T extends num> {
+ Class5._();
+ factory Class5() => new Class5<T>._();
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/test.options b/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/test.options
new file mode 100644
index 0000000..bfe6dc8
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/from_dill/test.options
@@ -0,0 +1 @@
+main_lib.dart
\ No newline at end of file
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_constructor_tear_off.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_constructor_tear_off.dart.strong.expect
index d686ae7..1802229 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_constructor_tear_off.dart.strong.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_constructor_tear_off.dart.strong.expect
@@ -172,9 +172,9 @@
}
constants {
- #C1 = tearoff self::Class1::_#new#tearOff
- #C2 = tearoff self::Class2::_#new#tearOff
- #C3 = tearoff self::Class3::_#new#tearOff
- #C4 = tearoff self::Class4::_#new#tearOff
+ #C1 = static-tearoff self::Class1::_#new#tearOff
+ #C2 = static-tearoff self::Class2::_#new#tearOff
+ #C3 = static-tearoff self::Class3::_#new#tearOff
+ #C4 = static-tearoff self::Class4::_#new#tearOff
#C5 = false
}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_constructor_tear_off.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_constructor_tear_off.dart.strong.transformed.expect
index d58a81e..d13da4b 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_constructor_tear_off.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_constructor_tear_off.dart.strong.transformed.expect
@@ -172,9 +172,9 @@
}
constants {
- #C1 = tearoff self::Class1::_#new#tearOff
- #C2 = tearoff self::Class2::_#new#tearOff
- #C3 = tearoff self::Class3::_#new#tearOff
- #C4 = tearoff self::Class4::_#new#tearOff
+ #C1 = static-tearoff self::Class1::_#new#tearOff
+ #C2 = static-tearoff self::Class2::_#new#tearOff
+ #C3 = static-tearoff self::Class3::_#new#tearOff
+ #C4 = static-tearoff self::Class4::_#new#tearOff
#C5 = false
}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_constructor_tear_off.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_constructor_tear_off.dart.weak.expect
index d686ae7..1802229 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_constructor_tear_off.dart.weak.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_constructor_tear_off.dart.weak.expect
@@ -172,9 +172,9 @@
}
constants {
- #C1 = tearoff self::Class1::_#new#tearOff
- #C2 = tearoff self::Class2::_#new#tearOff
- #C3 = tearoff self::Class3::_#new#tearOff
- #C4 = tearoff self::Class4::_#new#tearOff
+ #C1 = static-tearoff self::Class1::_#new#tearOff
+ #C2 = static-tearoff self::Class2::_#new#tearOff
+ #C3 = static-tearoff self::Class3::_#new#tearOff
+ #C4 = static-tearoff self::Class4::_#new#tearOff
#C5 = false
}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_constructor_tear_off.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_constructor_tear_off.dart.weak.transformed.expect
index d58a81e..d13da4b 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_constructor_tear_off.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_constructor_tear_off.dart.weak.transformed.expect
@@ -172,9 +172,9 @@
}
constants {
- #C1 = tearoff self::Class1::_#new#tearOff
- #C2 = tearoff self::Class2::_#new#tearOff
- #C3 = tearoff self::Class3::_#new#tearOff
- #C4 = tearoff self::Class4::_#new#tearOff
+ #C1 = static-tearoff self::Class1::_#new#tearOff
+ #C2 = static-tearoff self::Class2::_#new#tearOff
+ #C3 = static-tearoff self::Class3::_#new#tearOff
+ #C4 = static-tearoff self::Class4::_#new#tearOff
#C5 = false
}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart
new file mode 100644
index 0000000..a8d167a
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart
@@ -0,0 +1,134 @@
+// 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.
+
+final bool inSoundMode = <int?>[] is! List<int>;
+
+main() {
+ print('inSoundMode: $inSoundMode');
+ testGeneric();
+ testBounded();
+}
+
+class Class1<T> {
+ Class1._();
+ factory Class1() => new Class1<T>._();
+}
+
+testGeneric() {
+ var f1a = Class1.new;
+ var c1a = f1a();
+ expect(true, c1a is Class1<dynamic>);
+ expect(false, c1a is Class1<int>);
+ var c1b = f1a<int>();
+ expect(true, c1b is Class1<int>);
+ expect(false, c1b is Class1<String>);
+ () {
+ f1a<int, String>(); // error
+ };
+
+ var f1b = f1a<int>;
+ var c1c = f1b();
+ expect(true, c1c is Class1<int>);
+ expect(false, c1c is Class1<String>);
+ () {
+ f1b<int>(); // error
+ };
+
+ dynamic f1c = Class1.new;
+ var c1d = f1c();
+ expect(true, c1a is Class1<dynamic>);
+ expect(false, c1a is Class1<int>);
+ throws(() => f1c<int, String>());
+}
+
+class Class2<T extends num> {
+ Class2._();
+ factory Class2() => new Class2<T>._();
+}
+
+class Class3<T extends S, S> {
+ Class3._();
+ factory Class3() => new Class3<T, S>._();
+}
+
+class Class4<T extends Class4<T>> {
+ Class4._();
+ factory Class4() => new Class4<T>._();
+}
+
+class Class4int extends Class4<Class4int> {
+ Class4int._() : super._();
+ factory Class4int() => new Class4int._();
+}
+
+testBounded() {
+ var f2a = Class2.new;
+ var c2a = f2a();
+ expect(true, c2a is Class2<num>);
+ expect(false, c2a is Class2<int>);
+ var c2b = f2a<int>();
+ expect(true, c2b is Class2<int>);
+ expect(false, c2b is Class2<double>);
+ () {
+ f2a<String>(); // error
+ f2a<int, String>(); // error
+ };
+
+ dynamic f2b = Class2.new;
+ var c2c = f2b();
+ expect(true, c2c is Class2<num>);
+ expect(false, c2c is Class2<int>);
+ var c2d = f2b<int>();
+ expect(true, c2d is Class2<int>);
+ expect(false, c2d is Class2<double>);
+ throws(() => f2b<String>());
+ throws(() => f2b<int, String>());
+
+ var f3a = Class3.new;
+ var c3a = f3a();
+ expect(true, c3a is Class3<dynamic, dynamic>);
+ expect(false, c3a is Class3<int, num>);
+ var c3b = f3a<int, num>();
+ expect(true, c3b is Class3<int, num>);
+ expect(false, c3b is Class3<double, num>);
+ () {
+ f3a<num, int>(); // error
+ };
+
+ dynamic f3b = Class3.new;
+ var c3c = f3b();
+ expect(true, c3c is Class3<dynamic, dynamic>);
+ expect(false, c3c is Class3<int, num>);
+ var c3d = f3b<int, num>();
+ expect(true, c3d is Class3<int, num>);
+ expect(false, c3d is Class3<double, num>);
+ throws(() => f3b<num, int>());
+
+ var f4a = Class4.new;
+ () {
+ var c4a = f4a(); // error
+ };
+
+ dynamic f4b = Class4.new;
+ throws(() => f4b());
+ var c4b = f4b<Class4int>();
+ expect(true, c4b is Class4<Class4int>);
+}
+
+expect(expected, actual) {
+ if (expected != actual) throw 'Expected $expected, actual $actual';
+}
+
+throws(Function() f, {bool inSoundModeOnly: false}) {
+ try {
+ f();
+ } catch (e) {
+ print('Thrown: $e');
+ return;
+ }
+ if (!inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw 'Expected exception';
+}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart.strong.expect
new file mode 100644
index 0000000..eae54df
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart.strong.expect
@@ -0,0 +1,200 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:27:8: Error: Expected 1 type arguments.
+// f1a<int, String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:35:8: Error: Expected 0 type arguments.
+// f1b<int>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:74:8: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'T' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+// f2a<String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:75:8: Error: Expected 1 type arguments.
+// f2a<int, String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:96:8: Error: Type argument 'num' doesn't conform to the bound 'S' of the type variable 'T' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+// f3a<num, int>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:110:18: Error: Inferred type argument 'Class4<Object?>' doesn't conform to the bound 'Class4<T>' of the type variable 'T' on 'call'.
+// - 'Class4' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart'.
+// - 'Object' is from 'dart:core'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// var c4a = f4a(); // error
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1<T extends core::Object? = dynamic> extends core::Object {
+ constructor _() → self::Class1<self::Class1::T%>
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff<T extends core::Object? = dynamic>() → self::Class1<self::Class1::_#_#tearOff::T%>
+ return new self::Class1::_<self::Class1::_#_#tearOff::T%>();
+ static factory •<T extends core::Object? = dynamic>() → self::Class1<self::Class1::•::T%>
+ return new self::Class1::_<self::Class1::•::T%>();
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class1<self::Class1::_#new#tearOff::T%>
+ return self::Class1::•<self::Class1::_#new#tearOff::T%>();
+}
+class Class2<T extends core::num> extends core::Object {
+ constructor _() → self::Class2<self::Class2::T>
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff<T extends core::num>() → self::Class2<self::Class2::_#_#tearOff::T>
+ return new self::Class2::_<self::Class2::_#_#tearOff::T>();
+ static factory •<T extends core::num>() → self::Class2<self::Class2::•::T>
+ return new self::Class2::_<self::Class2::•::T>();
+ static method _#new#tearOff<T extends core::num>() → self::Class2<self::Class2::_#new#tearOff::T>
+ return self::Class2::•<self::Class2::_#new#tearOff::T>();
+}
+class Class3<T extends self::Class3::S% = dynamic, S extends core::Object? = dynamic> extends core::Object {
+ constructor _() → self::Class3<self::Class3::T%, self::Class3::S%>
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff<T extends self::Class3::_#_#tearOff::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::_#_#tearOff::T%, self::Class3::_#_#tearOff::S%>
+ return new self::Class3::_<self::Class3::_#_#tearOff::T%, self::Class3::_#_#tearOff::S%>();
+ static factory •<T extends self::Class3::•::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::•::T%, self::Class3::•::S%>
+ return new self::Class3::_<self::Class3::•::T%, self::Class3::•::S%>();
+ static method _#new#tearOff<T extends self::Class3::_#new#tearOff::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::_#new#tearOff::T%, self::Class3::_#new#tearOff::S%>
+ return self::Class3::•<self::Class3::_#new#tearOff::T%, self::Class3::_#new#tearOff::S%>();
+}
+class Class4<T extends self::Class4<self::Class4::T> = self::Class4<dynamic>> extends core::Object {
+ constructor _() → self::Class4<self::Class4::T>
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff<T extends self::Class4<self::Class4::_#_#tearOff::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::_#_#tearOff::T>
+ return new self::Class4::_<self::Class4::_#_#tearOff::T>();
+ static factory •<T extends self::Class4<self::Class4::•::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::•::T>
+ return new self::Class4::_<self::Class4::•::T>();
+ static method _#new#tearOff<T extends self::Class4<self::Class4::_#new#tearOff::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::_#new#tearOff::T>
+ return self::Class4::•<self::Class4::_#new#tearOff::T>();
+}
+class Class4int extends self::Class4<self::Class4int> {
+ constructor _() → self::Class4int
+ : super self::Class4::_()
+ ;
+ static method _#_#tearOff() → self::Class4int
+ return new self::Class4int::_();
+ static factory •() → self::Class4int
+ return new self::Class4int::_();
+ static method _#new#tearOff() → self::Class4int
+ return self::Class4int::•();
+}
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+ core::print("inSoundMode: ${self::inSoundMode}");
+ self::testGeneric();
+ self::testBounded();
+}
+static method testGeneric() → dynamic {
+ <T extends core::Object? = dynamic>() → self::Class1<T%> f1a = #C1;
+ self::Class1<dynamic> c1a = f1a<dynamic>(){() → self::Class1<dynamic>};
+ self::expect(true, c1a is{ForNonNullableByDefault} self::Class1<dynamic>);
+ self::expect(false, c1a is{ForNonNullableByDefault} self::Class1<core::int>);
+ self::Class1<core::int> c1b = f1a<core::int>(){() → self::Class1<core::int>};
+ self::expect(true, c1b is{ForNonNullableByDefault} self::Class1<core::int>);
+ self::expect(false, c1b is{ForNonNullableByDefault} self::Class1<core::String>);
+ () → Null {
+ let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:27:8: Error: Expected 1 type arguments.
+ f1a<int, String>(); // error
+ ^" in f1a{<inapplicable>}.<core::int, core::String>();
+ };
+ () → self::Class1<core::int> f1b = f1a<core::int>;
+ self::Class1<core::int> c1c = f1b(){() → self::Class1<core::int>};
+ self::expect(true, c1c is{ForNonNullableByDefault} self::Class1<core::int>);
+ self::expect(false, c1c is{ForNonNullableByDefault} self::Class1<core::String>);
+ () → Null {
+ let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:35:8: Error: Expected 0 type arguments.
+ f1b<int>(); // error
+ ^" in f1b{<inapplicable>}.<core::int>();
+ };
+ dynamic f1c = #C1;
+ dynamic c1d = f1c{dynamic}.call();
+ self::expect(true, c1a is{ForNonNullableByDefault} self::Class1<dynamic>);
+ self::expect(false, c1a is{ForNonNullableByDefault} self::Class1<core::int>);
+ self::throws(() → dynamic => f1c{dynamic}.call<core::int, core::String>());
+}
+static method testBounded() → dynamic {
+ <T extends core::num>() → self::Class2<T> f2a = #C2;
+ self::Class2<core::num> c2a = f2a<core::num>(){() → self::Class2<core::num>};
+ self::expect(true, c2a is{ForNonNullableByDefault} self::Class2<core::num>);
+ self::expect(false, c2a is{ForNonNullableByDefault} self::Class2<core::int>);
+ self::Class2<core::int> c2b = f2a<core::int>(){() → self::Class2<core::int>};
+ self::expect(true, c2b is{ForNonNullableByDefault} self::Class2<core::int>);
+ self::expect(false, c2b is{ForNonNullableByDefault} self::Class2<core::double>);
+ () → Null {
+ f2a<core::String>(){() → self::Class2<core::String>};
+ let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:75:8: Error: Expected 1 type arguments.
+ f2a<int, String>(); // error
+ ^" in f2a{<inapplicable>}.<core::int, core::String>();
+ };
+ dynamic f2b = #C2;
+ dynamic c2c = f2b{dynamic}.call();
+ self::expect(true, c2c is{ForNonNullableByDefault} self::Class2<core::num>);
+ self::expect(false, c2c is{ForNonNullableByDefault} self::Class2<core::int>);
+ dynamic c2d = f2b{dynamic}.call<core::int>();
+ self::expect(true, c2d is{ForNonNullableByDefault} self::Class2<core::int>);
+ self::expect(false, c2d is{ForNonNullableByDefault} self::Class2<core::double>);
+ self::throws(() → dynamic => f2b{dynamic}.call<core::String>());
+ self::throws(() → dynamic => f2b{dynamic}.call<core::int, core::String>());
+ <T extends S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<T%, S%> f3a = #C3;
+ self::Class3<dynamic, dynamic> c3a = f3a<dynamic, dynamic>(){() → self::Class3<dynamic, dynamic>};
+ self::expect(true, c3a is{ForNonNullableByDefault} self::Class3<dynamic, dynamic>);
+ self::expect(false, c3a is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+ self::Class3<core::int, core::num> c3b = f3a<core::int, core::num>(){() → self::Class3<core::int, core::num>};
+ self::expect(true, c3b is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+ self::expect(false, c3b is{ForNonNullableByDefault} self::Class3<core::double, core::num>);
+ () → Null {
+ f3a<core::num, core::int>(){() → self::Class3<core::num, core::int>};
+ };
+ dynamic f3b = #C3;
+ dynamic c3c = f3b{dynamic}.call();
+ self::expect(true, c3c is{ForNonNullableByDefault} self::Class3<dynamic, dynamic>);
+ self::expect(false, c3c is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+ dynamic c3d = f3b{dynamic}.call<core::int, core::num>();
+ self::expect(true, c3d is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+ self::expect(false, c3d is{ForNonNullableByDefault} self::Class3<core::double, core::num>);
+ self::throws(() → dynamic => f3b{dynamic}.call<core::num, core::int>());
+ <T extends self::Class4<T> = self::Class4<dynamic>>() → self::Class4<T> f4a = #C4;
+ () → Null {
+ self::Class4<self::Class4<core::Object?>> c4a = f4a<self::Class4<core::Object?>>(){() → self::Class4<self::Class4<core::Object?>>};
+ };
+ dynamic f4b = #C4;
+ self::throws(() → dynamic => f4b{dynamic}.call());
+ dynamic c4b = f4b{dynamic}.call<self::Class4int>();
+ self::expect(true, c4b is{ForNonNullableByDefault} self::Class4<self::Class4int>);
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C5}) → dynamic {
+ try {
+ f(){() → dynamic};
+ }
+ on core::Object catch(final core::Object e) {
+ core::print("Thrown: ${e}");
+ return;
+ }
+ if(!self::inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw "Expected exception";
+}
+
+constants {
+ #C1 = static-tearoff self::Class1::_#new#tearOff
+ #C2 = static-tearoff self::Class2::_#new#tearOff
+ #C3 = static-tearoff self::Class3::_#new#tearOff
+ #C4 = static-tearoff self::Class4::_#new#tearOff
+ #C5 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart.strong.transformed.expect
new file mode 100644
index 0000000..552fe7e
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart.strong.transformed.expect
@@ -0,0 +1,200 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:27:8: Error: Expected 1 type arguments.
+// f1a<int, String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:35:8: Error: Expected 0 type arguments.
+// f1b<int>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:74:8: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'T' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+// f2a<String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:75:8: Error: Expected 1 type arguments.
+// f2a<int, String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:96:8: Error: Type argument 'num' doesn't conform to the bound 'S' of the type variable 'T' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+// f3a<num, int>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:110:18: Error: Inferred type argument 'Class4<Object?>' doesn't conform to the bound 'Class4<T>' of the type variable 'T' on 'call'.
+// - 'Class4' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart'.
+// - 'Object' is from 'dart:core'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// var c4a = f4a(); // error
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1<T extends core::Object? = dynamic> extends core::Object {
+ constructor _() → self::Class1<self::Class1::T%>
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff<T extends core::Object? = dynamic>() → self::Class1<self::Class1::_#_#tearOff::T%>
+ return new self::Class1::_<self::Class1::_#_#tearOff::T%>();
+ static factory •<T extends core::Object? = dynamic>() → self::Class1<self::Class1::•::T%>
+ return new self::Class1::_<self::Class1::•::T%>();
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class1<self::Class1::_#new#tearOff::T%>
+ return self::Class1::•<self::Class1::_#new#tearOff::T%>();
+}
+class Class2<T extends core::num> extends core::Object {
+ constructor _() → self::Class2<self::Class2::T>
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff<T extends core::num>() → self::Class2<self::Class2::_#_#tearOff::T>
+ return new self::Class2::_<self::Class2::_#_#tearOff::T>();
+ static factory •<T extends core::num>() → self::Class2<self::Class2::•::T>
+ return new self::Class2::_<self::Class2::•::T>();
+ static method _#new#tearOff<T extends core::num>() → self::Class2<self::Class2::_#new#tearOff::T>
+ return self::Class2::•<self::Class2::_#new#tearOff::T>();
+}
+class Class3<T extends self::Class3::S% = dynamic, S extends core::Object? = dynamic> extends core::Object {
+ constructor _() → self::Class3<self::Class3::T%, self::Class3::S%>
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff<T extends self::Class3::_#_#tearOff::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::_#_#tearOff::T%, self::Class3::_#_#tearOff::S%>
+ return new self::Class3::_<self::Class3::_#_#tearOff::T%, self::Class3::_#_#tearOff::S%>();
+ static factory •<T extends self::Class3::•::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::•::T%, self::Class3::•::S%>
+ return new self::Class3::_<self::Class3::•::T%, self::Class3::•::S%>();
+ static method _#new#tearOff<T extends self::Class3::_#new#tearOff::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::_#new#tearOff::T%, self::Class3::_#new#tearOff::S%>
+ return self::Class3::•<self::Class3::_#new#tearOff::T%, self::Class3::_#new#tearOff::S%>();
+}
+class Class4<T extends self::Class4<self::Class4::T> = self::Class4<dynamic>> extends core::Object {
+ constructor _() → self::Class4<self::Class4::T>
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff<T extends self::Class4<self::Class4::_#_#tearOff::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::_#_#tearOff::T>
+ return new self::Class4::_<self::Class4::_#_#tearOff::T>();
+ static factory •<T extends self::Class4<self::Class4::•::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::•::T>
+ return new self::Class4::_<self::Class4::•::T>();
+ static method _#new#tearOff<T extends self::Class4<self::Class4::_#new#tearOff::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::_#new#tearOff::T>
+ return self::Class4::•<self::Class4::_#new#tearOff::T>();
+}
+class Class4int extends self::Class4<self::Class4int> {
+ constructor _() → self::Class4int
+ : super self::Class4::_()
+ ;
+ static method _#_#tearOff() → self::Class4int
+ return new self::Class4int::_();
+ static factory •() → self::Class4int
+ return new self::Class4int::_();
+ static method _#new#tearOff() → self::Class4int
+ return self::Class4int::•();
+}
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+ core::print("inSoundMode: ${self::inSoundMode}");
+ self::testGeneric();
+ self::testBounded();
+}
+static method testGeneric() → dynamic {
+ <T extends core::Object? = dynamic>() → self::Class1<T%> f1a = #C1;
+ self::Class1<dynamic> c1a = f1a<dynamic>(){() → self::Class1<dynamic>};
+ self::expect(true, c1a is{ForNonNullableByDefault} self::Class1<dynamic>);
+ self::expect(false, c1a is{ForNonNullableByDefault} self::Class1<core::int>);
+ self::Class1<core::int> c1b = f1a<core::int>(){() → self::Class1<core::int>};
+ self::expect(true, c1b is{ForNonNullableByDefault} self::Class1<core::int>);
+ self::expect(false, c1b is{ForNonNullableByDefault} self::Class1<core::String>);
+ () → Null {
+ let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:27:8: Error: Expected 1 type arguments.
+ f1a<int, String>(); // error
+ ^" in f1a{<inapplicable>}.<core::int, core::String>();
+ };
+ () → self::Class1<core::int> f1b = f1a<core::int>;
+ self::Class1<core::int> c1c = f1b(){() → self::Class1<core::int>};
+ self::expect(true, c1c is{ForNonNullableByDefault} self::Class1<core::int>);
+ self::expect(false, c1c is{ForNonNullableByDefault} self::Class1<core::String>);
+ () → Null {
+ let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:35:8: Error: Expected 0 type arguments.
+ f1b<int>(); // error
+ ^" in f1b{<inapplicable>}.<core::int>();
+ };
+ dynamic f1c = #C1;
+ dynamic c1d = f1c{dynamic}.call();
+ self::expect(true, c1a is{ForNonNullableByDefault} self::Class1<dynamic>);
+ self::expect(false, c1a is{ForNonNullableByDefault} self::Class1<core::int>);
+ self::throws(() → dynamic => f1c{dynamic}.call<core::int, core::String>());
+}
+static method testBounded() → dynamic {
+ <T extends core::num>() → self::Class2<T> f2a = #C2;
+ self::Class2<core::num> c2a = f2a<core::num>(){() → self::Class2<core::num>};
+ self::expect(true, c2a is{ForNonNullableByDefault} self::Class2<core::num>);
+ self::expect(false, c2a is{ForNonNullableByDefault} self::Class2<core::int>);
+ self::Class2<core::int> c2b = f2a<core::int>(){() → self::Class2<core::int>};
+ self::expect(true, c2b is{ForNonNullableByDefault} self::Class2<core::int>);
+ self::expect(false, c2b is{ForNonNullableByDefault} self::Class2<core::double>);
+ () → Null {
+ f2a<core::String>(){() → self::Class2<core::String>};
+ let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:75:8: Error: Expected 1 type arguments.
+ f2a<int, String>(); // error
+ ^" in f2a{<inapplicable>}.<core::int, core::String>();
+ };
+ dynamic f2b = #C2;
+ dynamic c2c = f2b{dynamic}.call();
+ self::expect(true, c2c is{ForNonNullableByDefault} self::Class2<core::num>);
+ self::expect(false, c2c is{ForNonNullableByDefault} self::Class2<core::int>);
+ dynamic c2d = f2b{dynamic}.call<core::int>();
+ self::expect(true, c2d is{ForNonNullableByDefault} self::Class2<core::int>);
+ self::expect(false, c2d is{ForNonNullableByDefault} self::Class2<core::double>);
+ self::throws(() → dynamic => f2b{dynamic}.call<core::String>());
+ self::throws(() → dynamic => f2b{dynamic}.call<core::int, core::String>());
+ <T extends S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<T%, S%> f3a = #C3;
+ self::Class3<dynamic, dynamic> c3a = f3a<dynamic, dynamic>(){() → self::Class3<dynamic, dynamic>};
+ self::expect(true, c3a is{ForNonNullableByDefault} self::Class3<dynamic, dynamic>);
+ self::expect(false, c3a is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+ self::Class3<core::int, core::num> c3b = f3a<core::int, core::num>(){() → self::Class3<core::int, core::num>};
+ self::expect(true, c3b is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+ self::expect(false, c3b is{ForNonNullableByDefault} self::Class3<core::double, core::num>);
+ () → Null {
+ f3a<core::num, core::int>(){() → self::Class3<core::num, core::int>};
+ };
+ dynamic f3b = #C3;
+ dynamic c3c = f3b{dynamic}.call();
+ self::expect(true, c3c is{ForNonNullableByDefault} self::Class3<dynamic, dynamic>);
+ self::expect(false, c3c is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+ dynamic c3d = f3b{dynamic}.call<core::int, core::num>();
+ self::expect(true, c3d is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+ self::expect(false, c3d is{ForNonNullableByDefault} self::Class3<core::double, core::num>);
+ self::throws(() → dynamic => f3b{dynamic}.call<core::num, core::int>());
+ <T extends self::Class4<T> = self::Class4<dynamic>>() → self::Class4<T> f4a = #C4;
+ () → Null {
+ self::Class4<self::Class4<core::Object?>> c4a = f4a<self::Class4<core::Object?>>(){() → self::Class4<self::Class4<core::Object?>>};
+ };
+ dynamic f4b = #C4;
+ self::throws(() → dynamic => f4b{dynamic}.call());
+ dynamic c4b = f4b{dynamic}.call<self::Class4int>();
+ self::expect(true, c4b is{ForNonNullableByDefault} self::Class4<self::Class4int>);
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C5}) → dynamic {
+ try {
+ f(){() → dynamic};
+ }
+ on core::Object catch(final core::Object e) {
+ core::print("Thrown: ${e}");
+ return;
+ }
+ if(!self::inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw "Expected exception";
+}
+
+constants {
+ #C1 = static-tearoff self::Class1::_#new#tearOff
+ #C2 = static-tearoff self::Class2::_#new#tearOff
+ #C3 = static-tearoff self::Class3::_#new#tearOff
+ #C4 = static-tearoff self::Class4::_#new#tearOff
+ #C5 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart.textual_outline.expect
new file mode 100644
index 0000000..b692fbf
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart.textual_outline.expect
@@ -0,0 +1,33 @@
+final bool inSoundMode = <int?>[] is! List<int>;
+main() {}
+
+class Class1<T> {
+ Class1._();
+ factory Class1() => new Class1<T>._();
+}
+
+testGeneric() {}
+
+class Class2<T extends num> {
+ Class2._();
+ factory Class2() => new Class2<T>._();
+}
+
+class Class3<T extends S, S> {
+ Class3._();
+ factory Class3() => new Class3<T, S>._();
+}
+
+class Class4<T extends Class4<T>> {
+ Class4._();
+ factory Class4() => new Class4<T>._();
+}
+
+class Class4int extends Class4<Class4int> {
+ Class4int._() : super._();
+ factory Class4int() => new Class4int._();
+}
+
+testBounded() {}
+expect(expected, actual) {}
+throws(Function() f, {bool inSoundModeOnly: false}) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..c82d489
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart.textual_outline_modelled.expect
@@ -0,0 +1,31 @@
+class Class1<T> {
+ Class1._();
+ factory Class1() => new Class1<T>._();
+}
+
+class Class2<T extends num> {
+ Class2._();
+ factory Class2() => new Class2<T>._();
+}
+
+class Class3<T extends S, S> {
+ Class3._();
+ factory Class3() => new Class3<T, S>._();
+}
+
+class Class4<T extends Class4<T>> {
+ Class4._();
+ factory Class4() => new Class4<T>._();
+}
+
+class Class4int extends Class4<Class4int> {
+ Class4int._() : super._();
+ factory Class4int() => new Class4int._();
+}
+
+expect(expected, actual) {}
+final bool inSoundMode = <int?>[] is! List<int>;
+main() {}
+testBounded() {}
+testGeneric() {}
+throws(Function() f, {bool inSoundModeOnly: false}) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart.weak.expect
new file mode 100644
index 0000000..eae54df
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart.weak.expect
@@ -0,0 +1,200 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:27:8: Error: Expected 1 type arguments.
+// f1a<int, String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:35:8: Error: Expected 0 type arguments.
+// f1b<int>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:74:8: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'T' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+// f2a<String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:75:8: Error: Expected 1 type arguments.
+// f2a<int, String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:96:8: Error: Type argument 'num' doesn't conform to the bound 'S' of the type variable 'T' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+// f3a<num, int>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:110:18: Error: Inferred type argument 'Class4<Object?>' doesn't conform to the bound 'Class4<T>' of the type variable 'T' on 'call'.
+// - 'Class4' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart'.
+// - 'Object' is from 'dart:core'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// var c4a = f4a(); // error
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1<T extends core::Object? = dynamic> extends core::Object {
+ constructor _() → self::Class1<self::Class1::T%>
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff<T extends core::Object? = dynamic>() → self::Class1<self::Class1::_#_#tearOff::T%>
+ return new self::Class1::_<self::Class1::_#_#tearOff::T%>();
+ static factory •<T extends core::Object? = dynamic>() → self::Class1<self::Class1::•::T%>
+ return new self::Class1::_<self::Class1::•::T%>();
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class1<self::Class1::_#new#tearOff::T%>
+ return self::Class1::•<self::Class1::_#new#tearOff::T%>();
+}
+class Class2<T extends core::num> extends core::Object {
+ constructor _() → self::Class2<self::Class2::T>
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff<T extends core::num>() → self::Class2<self::Class2::_#_#tearOff::T>
+ return new self::Class2::_<self::Class2::_#_#tearOff::T>();
+ static factory •<T extends core::num>() → self::Class2<self::Class2::•::T>
+ return new self::Class2::_<self::Class2::•::T>();
+ static method _#new#tearOff<T extends core::num>() → self::Class2<self::Class2::_#new#tearOff::T>
+ return self::Class2::•<self::Class2::_#new#tearOff::T>();
+}
+class Class3<T extends self::Class3::S% = dynamic, S extends core::Object? = dynamic> extends core::Object {
+ constructor _() → self::Class3<self::Class3::T%, self::Class3::S%>
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff<T extends self::Class3::_#_#tearOff::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::_#_#tearOff::T%, self::Class3::_#_#tearOff::S%>
+ return new self::Class3::_<self::Class3::_#_#tearOff::T%, self::Class3::_#_#tearOff::S%>();
+ static factory •<T extends self::Class3::•::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::•::T%, self::Class3::•::S%>
+ return new self::Class3::_<self::Class3::•::T%, self::Class3::•::S%>();
+ static method _#new#tearOff<T extends self::Class3::_#new#tearOff::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::_#new#tearOff::T%, self::Class3::_#new#tearOff::S%>
+ return self::Class3::•<self::Class3::_#new#tearOff::T%, self::Class3::_#new#tearOff::S%>();
+}
+class Class4<T extends self::Class4<self::Class4::T> = self::Class4<dynamic>> extends core::Object {
+ constructor _() → self::Class4<self::Class4::T>
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff<T extends self::Class4<self::Class4::_#_#tearOff::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::_#_#tearOff::T>
+ return new self::Class4::_<self::Class4::_#_#tearOff::T>();
+ static factory •<T extends self::Class4<self::Class4::•::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::•::T>
+ return new self::Class4::_<self::Class4::•::T>();
+ static method _#new#tearOff<T extends self::Class4<self::Class4::_#new#tearOff::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::_#new#tearOff::T>
+ return self::Class4::•<self::Class4::_#new#tearOff::T>();
+}
+class Class4int extends self::Class4<self::Class4int> {
+ constructor _() → self::Class4int
+ : super self::Class4::_()
+ ;
+ static method _#_#tearOff() → self::Class4int
+ return new self::Class4int::_();
+ static factory •() → self::Class4int
+ return new self::Class4int::_();
+ static method _#new#tearOff() → self::Class4int
+ return self::Class4int::•();
+}
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+ core::print("inSoundMode: ${self::inSoundMode}");
+ self::testGeneric();
+ self::testBounded();
+}
+static method testGeneric() → dynamic {
+ <T extends core::Object? = dynamic>() → self::Class1<T%> f1a = #C1;
+ self::Class1<dynamic> c1a = f1a<dynamic>(){() → self::Class1<dynamic>};
+ self::expect(true, c1a is{ForNonNullableByDefault} self::Class1<dynamic>);
+ self::expect(false, c1a is{ForNonNullableByDefault} self::Class1<core::int>);
+ self::Class1<core::int> c1b = f1a<core::int>(){() → self::Class1<core::int>};
+ self::expect(true, c1b is{ForNonNullableByDefault} self::Class1<core::int>);
+ self::expect(false, c1b is{ForNonNullableByDefault} self::Class1<core::String>);
+ () → Null {
+ let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:27:8: Error: Expected 1 type arguments.
+ f1a<int, String>(); // error
+ ^" in f1a{<inapplicable>}.<core::int, core::String>();
+ };
+ () → self::Class1<core::int> f1b = f1a<core::int>;
+ self::Class1<core::int> c1c = f1b(){() → self::Class1<core::int>};
+ self::expect(true, c1c is{ForNonNullableByDefault} self::Class1<core::int>);
+ self::expect(false, c1c is{ForNonNullableByDefault} self::Class1<core::String>);
+ () → Null {
+ let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:35:8: Error: Expected 0 type arguments.
+ f1b<int>(); // error
+ ^" in f1b{<inapplicable>}.<core::int>();
+ };
+ dynamic f1c = #C1;
+ dynamic c1d = f1c{dynamic}.call();
+ self::expect(true, c1a is{ForNonNullableByDefault} self::Class1<dynamic>);
+ self::expect(false, c1a is{ForNonNullableByDefault} self::Class1<core::int>);
+ self::throws(() → dynamic => f1c{dynamic}.call<core::int, core::String>());
+}
+static method testBounded() → dynamic {
+ <T extends core::num>() → self::Class2<T> f2a = #C2;
+ self::Class2<core::num> c2a = f2a<core::num>(){() → self::Class2<core::num>};
+ self::expect(true, c2a is{ForNonNullableByDefault} self::Class2<core::num>);
+ self::expect(false, c2a is{ForNonNullableByDefault} self::Class2<core::int>);
+ self::Class2<core::int> c2b = f2a<core::int>(){() → self::Class2<core::int>};
+ self::expect(true, c2b is{ForNonNullableByDefault} self::Class2<core::int>);
+ self::expect(false, c2b is{ForNonNullableByDefault} self::Class2<core::double>);
+ () → Null {
+ f2a<core::String>(){() → self::Class2<core::String>};
+ let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:75:8: Error: Expected 1 type arguments.
+ f2a<int, String>(); // error
+ ^" in f2a{<inapplicable>}.<core::int, core::String>();
+ };
+ dynamic f2b = #C2;
+ dynamic c2c = f2b{dynamic}.call();
+ self::expect(true, c2c is{ForNonNullableByDefault} self::Class2<core::num>);
+ self::expect(false, c2c is{ForNonNullableByDefault} self::Class2<core::int>);
+ dynamic c2d = f2b{dynamic}.call<core::int>();
+ self::expect(true, c2d is{ForNonNullableByDefault} self::Class2<core::int>);
+ self::expect(false, c2d is{ForNonNullableByDefault} self::Class2<core::double>);
+ self::throws(() → dynamic => f2b{dynamic}.call<core::String>());
+ self::throws(() → dynamic => f2b{dynamic}.call<core::int, core::String>());
+ <T extends S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<T%, S%> f3a = #C3;
+ self::Class3<dynamic, dynamic> c3a = f3a<dynamic, dynamic>(){() → self::Class3<dynamic, dynamic>};
+ self::expect(true, c3a is{ForNonNullableByDefault} self::Class3<dynamic, dynamic>);
+ self::expect(false, c3a is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+ self::Class3<core::int, core::num> c3b = f3a<core::int, core::num>(){() → self::Class3<core::int, core::num>};
+ self::expect(true, c3b is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+ self::expect(false, c3b is{ForNonNullableByDefault} self::Class3<core::double, core::num>);
+ () → Null {
+ f3a<core::num, core::int>(){() → self::Class3<core::num, core::int>};
+ };
+ dynamic f3b = #C3;
+ dynamic c3c = f3b{dynamic}.call();
+ self::expect(true, c3c is{ForNonNullableByDefault} self::Class3<dynamic, dynamic>);
+ self::expect(false, c3c is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+ dynamic c3d = f3b{dynamic}.call<core::int, core::num>();
+ self::expect(true, c3d is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+ self::expect(false, c3d is{ForNonNullableByDefault} self::Class3<core::double, core::num>);
+ self::throws(() → dynamic => f3b{dynamic}.call<core::num, core::int>());
+ <T extends self::Class4<T> = self::Class4<dynamic>>() → self::Class4<T> f4a = #C4;
+ () → Null {
+ self::Class4<self::Class4<core::Object?>> c4a = f4a<self::Class4<core::Object?>>(){() → self::Class4<self::Class4<core::Object?>>};
+ };
+ dynamic f4b = #C4;
+ self::throws(() → dynamic => f4b{dynamic}.call());
+ dynamic c4b = f4b{dynamic}.call<self::Class4int>();
+ self::expect(true, c4b is{ForNonNullableByDefault} self::Class4<self::Class4int>);
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C5}) → dynamic {
+ try {
+ f(){() → dynamic};
+ }
+ on core::Object catch(final core::Object e) {
+ core::print("Thrown: ${e}");
+ return;
+ }
+ if(!self::inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw "Expected exception";
+}
+
+constants {
+ #C1 = static-tearoff self::Class1::_#new#tearOff
+ #C2 = static-tearoff self::Class2::_#new#tearOff
+ #C3 = static-tearoff self::Class3::_#new#tearOff
+ #C4 = static-tearoff self::Class4::_#new#tearOff
+ #C5 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart.weak.outline.expect
new file mode 100644
index 0000000..6216fd6
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart.weak.outline.expect
@@ -0,0 +1,65 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Class1<T extends core::Object? = dynamic> extends core::Object {
+ constructor _() → self::Class1<self::Class1::T%>
+ ;
+ static method _#_#tearOff<T extends core::Object? = dynamic>() → self::Class1<self::Class1::_#_#tearOff::T%>
+ return new self::Class1::_<self::Class1::_#_#tearOff::T%>();
+ static factory •<T extends core::Object? = dynamic>() → self::Class1<self::Class1::•::T%>
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class1<self::Class1::_#new#tearOff::T%>
+ return self::Class1::•<self::Class1::_#new#tearOff::T%>();
+}
+class Class2<T extends core::num> extends core::Object {
+ constructor _() → self::Class2<self::Class2::T>
+ ;
+ static method _#_#tearOff<T extends core::num>() → self::Class2<self::Class2::_#_#tearOff::T>
+ return new self::Class2::_<self::Class2::_#_#tearOff::T>();
+ static factory •<T extends core::num>() → self::Class2<self::Class2::•::T>
+ ;
+ static method _#new#tearOff<T extends core::num>() → self::Class2<self::Class2::_#new#tearOff::T>
+ return self::Class2::•<self::Class2::_#new#tearOff::T>();
+}
+class Class3<T extends self::Class3::S% = dynamic, S extends core::Object? = dynamic> extends core::Object {
+ constructor _() → self::Class3<self::Class3::T%, self::Class3::S%>
+ ;
+ static method _#_#tearOff<T extends self::Class3::_#_#tearOff::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::_#_#tearOff::T%, self::Class3::_#_#tearOff::S%>
+ return new self::Class3::_<self::Class3::_#_#tearOff::T%, self::Class3::_#_#tearOff::S%>();
+ static factory •<T extends self::Class3::•::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::•::T%, self::Class3::•::S%>
+ ;
+ static method _#new#tearOff<T extends self::Class3::_#new#tearOff::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::_#new#tearOff::T%, self::Class3::_#new#tearOff::S%>
+ return self::Class3::•<self::Class3::_#new#tearOff::T%, self::Class3::_#new#tearOff::S%>();
+}
+class Class4<T extends self::Class4<self::Class4::T> = self::Class4<dynamic>> extends core::Object {
+ constructor _() → self::Class4<self::Class4::T>
+ ;
+ static method _#_#tearOff<T extends self::Class4<self::Class4::_#_#tearOff::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::_#_#tearOff::T>
+ return new self::Class4::_<self::Class4::_#_#tearOff::T>();
+ static factory •<T extends self::Class4<self::Class4::•::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::•::T>
+ ;
+ static method _#new#tearOff<T extends self::Class4<self::Class4::_#new#tearOff::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::_#new#tearOff::T>
+ return self::Class4::•<self::Class4::_#new#tearOff::T>();
+}
+class Class4int extends self::Class4<self::Class4int> {
+ constructor _() → self::Class4int
+ ;
+ static method _#_#tearOff() → self::Class4int
+ return new self::Class4int::_();
+ static factory •() → self::Class4int
+ ;
+ static method _#new#tearOff() → self::Class4int
+ return self::Class4int::•();
+}
+static final field core::bool inSoundMode;
+static method main() → dynamic
+ ;
+static method testGeneric() → dynamic
+ ;
+static method testBounded() → dynamic
+ ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+ ;
+static method throws(() → dynamic f, {core::bool inSoundModeOnly}) → dynamic
+ ;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart.weak.transformed.expect
new file mode 100644
index 0000000..552fe7e
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart.weak.transformed.expect
@@ -0,0 +1,200 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:27:8: Error: Expected 1 type arguments.
+// f1a<int, String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:35:8: Error: Expected 0 type arguments.
+// f1b<int>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:74:8: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'T' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+// f2a<String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:75:8: Error: Expected 1 type arguments.
+// f2a<int, String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:96:8: Error: Type argument 'num' doesn't conform to the bound 'S' of the type variable 'T' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+// f3a<num, int>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:110:18: Error: Inferred type argument 'Class4<Object?>' doesn't conform to the bound 'Class4<T>' of the type variable 'T' on 'call'.
+// - 'Class4' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart'.
+// - 'Object' is from 'dart:core'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// var c4a = f4a(); // error
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1<T extends core::Object? = dynamic> extends core::Object {
+ constructor _() → self::Class1<self::Class1::T%>
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff<T extends core::Object? = dynamic>() → self::Class1<self::Class1::_#_#tearOff::T%>
+ return new self::Class1::_<self::Class1::_#_#tearOff::T%>();
+ static factory •<T extends core::Object? = dynamic>() → self::Class1<self::Class1::•::T%>
+ return new self::Class1::_<self::Class1::•::T%>();
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class1<self::Class1::_#new#tearOff::T%>
+ return self::Class1::•<self::Class1::_#new#tearOff::T%>();
+}
+class Class2<T extends core::num> extends core::Object {
+ constructor _() → self::Class2<self::Class2::T>
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff<T extends core::num>() → self::Class2<self::Class2::_#_#tearOff::T>
+ return new self::Class2::_<self::Class2::_#_#tearOff::T>();
+ static factory •<T extends core::num>() → self::Class2<self::Class2::•::T>
+ return new self::Class2::_<self::Class2::•::T>();
+ static method _#new#tearOff<T extends core::num>() → self::Class2<self::Class2::_#new#tearOff::T>
+ return self::Class2::•<self::Class2::_#new#tearOff::T>();
+}
+class Class3<T extends self::Class3::S% = dynamic, S extends core::Object? = dynamic> extends core::Object {
+ constructor _() → self::Class3<self::Class3::T%, self::Class3::S%>
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff<T extends self::Class3::_#_#tearOff::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::_#_#tearOff::T%, self::Class3::_#_#tearOff::S%>
+ return new self::Class3::_<self::Class3::_#_#tearOff::T%, self::Class3::_#_#tearOff::S%>();
+ static factory •<T extends self::Class3::•::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::•::T%, self::Class3::•::S%>
+ return new self::Class3::_<self::Class3::•::T%, self::Class3::•::S%>();
+ static method _#new#tearOff<T extends self::Class3::_#new#tearOff::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::_#new#tearOff::T%, self::Class3::_#new#tearOff::S%>
+ return self::Class3::•<self::Class3::_#new#tearOff::T%, self::Class3::_#new#tearOff::S%>();
+}
+class Class4<T extends self::Class4<self::Class4::T> = self::Class4<dynamic>> extends core::Object {
+ constructor _() → self::Class4<self::Class4::T>
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff<T extends self::Class4<self::Class4::_#_#tearOff::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::_#_#tearOff::T>
+ return new self::Class4::_<self::Class4::_#_#tearOff::T>();
+ static factory •<T extends self::Class4<self::Class4::•::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::•::T>
+ return new self::Class4::_<self::Class4::•::T>();
+ static method _#new#tearOff<T extends self::Class4<self::Class4::_#new#tearOff::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::_#new#tearOff::T>
+ return self::Class4::•<self::Class4::_#new#tearOff::T>();
+}
+class Class4int extends self::Class4<self::Class4int> {
+ constructor _() → self::Class4int
+ : super self::Class4::_()
+ ;
+ static method _#_#tearOff() → self::Class4int
+ return new self::Class4int::_();
+ static factory •() → self::Class4int
+ return new self::Class4int::_();
+ static method _#new#tearOff() → self::Class4int
+ return self::Class4int::•();
+}
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+ core::print("inSoundMode: ${self::inSoundMode}");
+ self::testGeneric();
+ self::testBounded();
+}
+static method testGeneric() → dynamic {
+ <T extends core::Object? = dynamic>() → self::Class1<T%> f1a = #C1;
+ self::Class1<dynamic> c1a = f1a<dynamic>(){() → self::Class1<dynamic>};
+ self::expect(true, c1a is{ForNonNullableByDefault} self::Class1<dynamic>);
+ self::expect(false, c1a is{ForNonNullableByDefault} self::Class1<core::int>);
+ self::Class1<core::int> c1b = f1a<core::int>(){() → self::Class1<core::int>};
+ self::expect(true, c1b is{ForNonNullableByDefault} self::Class1<core::int>);
+ self::expect(false, c1b is{ForNonNullableByDefault} self::Class1<core::String>);
+ () → Null {
+ let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:27:8: Error: Expected 1 type arguments.
+ f1a<int, String>(); // error
+ ^" in f1a{<inapplicable>}.<core::int, core::String>();
+ };
+ () → self::Class1<core::int> f1b = f1a<core::int>;
+ self::Class1<core::int> c1c = f1b(){() → self::Class1<core::int>};
+ self::expect(true, c1c is{ForNonNullableByDefault} self::Class1<core::int>);
+ self::expect(false, c1c is{ForNonNullableByDefault} self::Class1<core::String>);
+ () → Null {
+ let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:35:8: Error: Expected 0 type arguments.
+ f1b<int>(); // error
+ ^" in f1b{<inapplicable>}.<core::int>();
+ };
+ dynamic f1c = #C1;
+ dynamic c1d = f1c{dynamic}.call();
+ self::expect(true, c1a is{ForNonNullableByDefault} self::Class1<dynamic>);
+ self::expect(false, c1a is{ForNonNullableByDefault} self::Class1<core::int>);
+ self::throws(() → dynamic => f1c{dynamic}.call<core::int, core::String>());
+}
+static method testBounded() → dynamic {
+ <T extends core::num>() → self::Class2<T> f2a = #C2;
+ self::Class2<core::num> c2a = f2a<core::num>(){() → self::Class2<core::num>};
+ self::expect(true, c2a is{ForNonNullableByDefault} self::Class2<core::num>);
+ self::expect(false, c2a is{ForNonNullableByDefault} self::Class2<core::int>);
+ self::Class2<core::int> c2b = f2a<core::int>(){() → self::Class2<core::int>};
+ self::expect(true, c2b is{ForNonNullableByDefault} self::Class2<core::int>);
+ self::expect(false, c2b is{ForNonNullableByDefault} self::Class2<core::double>);
+ () → Null {
+ f2a<core::String>(){() → self::Class2<core::String>};
+ let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/generic_factory_tear_off.dart:75:8: Error: Expected 1 type arguments.
+ f2a<int, String>(); // error
+ ^" in f2a{<inapplicable>}.<core::int, core::String>();
+ };
+ dynamic f2b = #C2;
+ dynamic c2c = f2b{dynamic}.call();
+ self::expect(true, c2c is{ForNonNullableByDefault} self::Class2<core::num>);
+ self::expect(false, c2c is{ForNonNullableByDefault} self::Class2<core::int>);
+ dynamic c2d = f2b{dynamic}.call<core::int>();
+ self::expect(true, c2d is{ForNonNullableByDefault} self::Class2<core::int>);
+ self::expect(false, c2d is{ForNonNullableByDefault} self::Class2<core::double>);
+ self::throws(() → dynamic => f2b{dynamic}.call<core::String>());
+ self::throws(() → dynamic => f2b{dynamic}.call<core::int, core::String>());
+ <T extends S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<T%, S%> f3a = #C3;
+ self::Class3<dynamic, dynamic> c3a = f3a<dynamic, dynamic>(){() → self::Class3<dynamic, dynamic>};
+ self::expect(true, c3a is{ForNonNullableByDefault} self::Class3<dynamic, dynamic>);
+ self::expect(false, c3a is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+ self::Class3<core::int, core::num> c3b = f3a<core::int, core::num>(){() → self::Class3<core::int, core::num>};
+ self::expect(true, c3b is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+ self::expect(false, c3b is{ForNonNullableByDefault} self::Class3<core::double, core::num>);
+ () → Null {
+ f3a<core::num, core::int>(){() → self::Class3<core::num, core::int>};
+ };
+ dynamic f3b = #C3;
+ dynamic c3c = f3b{dynamic}.call();
+ self::expect(true, c3c is{ForNonNullableByDefault} self::Class3<dynamic, dynamic>);
+ self::expect(false, c3c is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+ dynamic c3d = f3b{dynamic}.call<core::int, core::num>();
+ self::expect(true, c3d is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+ self::expect(false, c3d is{ForNonNullableByDefault} self::Class3<core::double, core::num>);
+ self::throws(() → dynamic => f3b{dynamic}.call<core::num, core::int>());
+ <T extends self::Class4<T> = self::Class4<dynamic>>() → self::Class4<T> f4a = #C4;
+ () → Null {
+ self::Class4<self::Class4<core::Object?>> c4a = f4a<self::Class4<core::Object?>>(){() → self::Class4<self::Class4<core::Object?>>};
+ };
+ dynamic f4b = #C4;
+ self::throws(() → dynamic => f4b{dynamic}.call());
+ dynamic c4b = f4b{dynamic}.call<self::Class4int>();
+ self::expect(true, c4b is{ForNonNullableByDefault} self::Class4<self::Class4int>);
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C5}) → dynamic {
+ try {
+ f(){() → dynamic};
+ }
+ on core::Object catch(final core::Object e) {
+ core::print("Thrown: ${e}");
+ return;
+ }
+ if(!self::inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw "Expected exception";
+}
+
+constants {
+ #C1 = static-tearoff self::Class1::_#new#tearOff
+ #C2 = static-tearoff self::Class2::_#new#tearOff
+ #C3 = static-tearoff self::Class3::_#new#tearOff
+ #C4 = static-tearoff self::Class4::_#new#tearOff
+ #C5 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart
new file mode 100644
index 0000000..302f380
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart
@@ -0,0 +1,134 @@
+// 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.
+
+final bool inSoundMode = <int?>[] is! List<int>;
+
+main() {
+ print('inSoundMode: $inSoundMode');
+ testGeneric();
+ testBounded();
+}
+
+class Class1<T> {
+ Class1._();
+ factory Class1() = Class1<T>._;
+}
+
+testGeneric() {
+ var f1a = Class1.new;
+ var c1a = f1a();
+ expect(true, c1a is Class1<dynamic>);
+ expect(false, c1a is Class1<int>);
+ var c1b = f1a<int>();
+ expect(true, c1b is Class1<int>);
+ expect(false, c1b is Class1<String>);
+ () {
+ f1a<int, String>(); // error
+ };
+
+ var f1b = f1a<int>;
+ var c1c = f1b();
+ expect(true, c1c is Class1<int>);
+ expect(false, c1c is Class1<String>);
+ () {
+ f1b<int>(); // error
+ };
+
+ dynamic f1c = Class1.new;
+ var c1d = f1c();
+ expect(true, c1a is Class1<dynamic>);
+ expect(false, c1a is Class1<int>);
+ throws(() => f1c<int, String>());
+}
+
+class Class2<T extends num> {
+ Class2._();
+ factory Class2() = Class2<T>._;
+}
+
+class Class3<T extends S, S> {
+ Class3._();
+ factory Class3() = Class3<T, S>._;
+}
+
+class Class4<T extends Class4<T>> {
+ Class4._();
+ factory Class4() = Class4<T>._;
+}
+
+class Class4int extends Class4<Class4int> {
+ Class4int._() : super._();
+ factory Class4int() = Class4int._;
+}
+
+testBounded() {
+ var f2a = Class2.new;
+ var c2a = f2a();
+ expect(true, c2a is Class2<num>);
+ expect(false, c2a is Class2<int>);
+ var c2b = f2a<int>();
+ expect(true, c2b is Class2<int>);
+ expect(false, c2b is Class2<double>);
+ () {
+ f2a<String>(); // error
+ f2a<int, String>(); // error
+ };
+
+ dynamic f2b = Class2.new;
+ var c2c = f2b();
+ expect(true, c2c is Class2<num>);
+ expect(false, c2c is Class2<int>);
+ var c2d = f2b<int>();
+ expect(true, c2d is Class2<int>);
+ expect(false, c2d is Class2<double>);
+ throws(() => f2b<String>());
+ throws(() => f2b<int, String>());
+
+ var f3a = Class3.new;
+ var c3a = f3a();
+ expect(true, c3a is Class3<dynamic, dynamic>);
+ expect(false, c3a is Class3<int, num>);
+ var c3b = f3a<int, num>();
+ expect(true, c3b is Class3<int, num>);
+ expect(false, c3b is Class3<double, num>);
+ () {
+ f3a<num, int>(); // error
+ };
+
+ dynamic f3b = Class3.new;
+ var c3c = f3b();
+ expect(true, c3c is Class3<dynamic, dynamic>);
+ expect(false, c3c is Class3<int, num>);
+ var c3d = f3b<int, num>();
+ expect(true, c3d is Class3<int, num>);
+ expect(false, c3d is Class3<double, num>);
+ throws(() => f3b<num, int>());
+
+ var f4a = Class4.new;
+ () {
+ var c4a = f4a(); // error
+ };
+
+ dynamic f4b = Class4.new;
+ throws(() => f4b());
+ var c4b = f4b<Class4int>();
+ expect(true, c4b is Class4<Class4int>);
+}
+
+expect(expected, actual) {
+ if (expected != actual) throw 'Expected $expected, actual $actual';
+}
+
+throws(Function() f, {bool inSoundModeOnly: false}) {
+ try {
+ f();
+ } catch (e) {
+ print('Thrown: $e');
+ return;
+ }
+ if (!inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw 'Expected exception';
+}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart.strong.expect
new file mode 100644
index 0000000..14303b7
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart.strong.expect
@@ -0,0 +1,205 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:27:8: Error: Expected 1 type arguments.
+// f1a<int, String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:35:8: Error: Expected 0 type arguments.
+// f1b<int>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:74:8: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'T' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+// f2a<String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:75:8: Error: Expected 1 type arguments.
+// f2a<int, String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:96:8: Error: Type argument 'num' doesn't conform to the bound 'S' of the type variable 'T' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+// f3a<num, int>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:110:18: Error: Inferred type argument 'Class4<Object?>' doesn't conform to the bound 'Class4<T>' of the type variable 'T' on 'call'.
+// - 'Class4' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart'.
+// - 'Object' is from 'dart:core'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// var c4a = f4a(); // error
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class1::•]/*isLegacy*/;
+ constructor _() → self::Class1<self::Class1::T%>
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff<T extends core::Object? = dynamic>() → self::Class1<self::Class1::_#_#tearOff::T%>
+ return new self::Class1::_<self::Class1::_#_#tearOff::T%>();
+ static factory •<T extends core::Object? = dynamic>() → self::Class1<self::Class1::•::T%>
+ let dynamic #redirecting_factory = self::Class1::_ in let self::Class1::•::T% #typeArg0 = null in invalid-expression;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class1<self::Class1::_#new#tearOff::T%>
+ return new self::Class1::_<self::Class1::_#new#tearOff::T%>();
+}
+class Class2<T extends core::num> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class2::•]/*isLegacy*/;
+ constructor _() → self::Class2<self::Class2::T>
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff<T extends core::num>() → self::Class2<self::Class2::_#_#tearOff::T>
+ return new self::Class2::_<self::Class2::_#_#tearOff::T>();
+ static factory •<T extends core::num>() → self::Class2<self::Class2::•::T>
+ let dynamic #redirecting_factory = self::Class2::_ in let self::Class2::•::T #typeArg0 = null in invalid-expression;
+ static method _#new#tearOff<T extends core::num>() → self::Class2<self::Class2::_#new#tearOff::T>
+ return new self::Class2::_<self::Class2::_#new#tearOff::T>();
+}
+class Class3<T extends self::Class3::S% = dynamic, S extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class3::•]/*isLegacy*/;
+ constructor _() → self::Class3<self::Class3::T%, self::Class3::S%>
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff<T extends self::Class3::_#_#tearOff::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::_#_#tearOff::T%, self::Class3::_#_#tearOff::S%>
+ return new self::Class3::_<self::Class3::_#_#tearOff::T%, self::Class3::_#_#tearOff::S%>();
+ static factory •<T extends self::Class3::•::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::•::T%, self::Class3::•::S%>
+ let dynamic #redirecting_factory = self::Class3::_ in let self::Class3::•::T% #typeArg0 = null in let self::Class3::•::S% #typeArg1 = null in invalid-expression;
+ static method _#new#tearOff<T extends self::Class3::_#new#tearOff::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::_#new#tearOff::T%, self::Class3::_#new#tearOff::S%>
+ return new self::Class3::_<self::Class3::_#new#tearOff::T%, self::Class3::_#new#tearOff::S%>();
+}
+class Class4<T extends self::Class4<self::Class4::T> = self::Class4<dynamic>> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class4::•]/*isLegacy*/;
+ constructor _() → self::Class4<self::Class4::T>
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff<T extends self::Class4<self::Class4::_#_#tearOff::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::_#_#tearOff::T>
+ return new self::Class4::_<self::Class4::_#_#tearOff::T>();
+ static factory •<T extends self::Class4<self::Class4::•::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::•::T>
+ let dynamic #redirecting_factory = self::Class4::_ in let self::Class4::•::T #typeArg0 = null in invalid-expression;
+ static method _#new#tearOff<T extends self::Class4<self::Class4::_#new#tearOff::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::_#new#tearOff::T>
+ return new self::Class4::_<self::Class4::_#new#tearOff::T>();
+}
+class Class4int extends self::Class4<self::Class4int> {
+ static final field dynamic _redirecting# = <dynamic>[self::Class4int::•]/*isLegacy*/;
+ constructor _() → self::Class4int
+ : super self::Class4::_()
+ ;
+ static method _#_#tearOff() → self::Class4int
+ return new self::Class4int::_();
+ static factory •() → self::Class4int
+ let dynamic #redirecting_factory = self::Class4int::_ in invalid-expression;
+ static method _#new#tearOff() → self::Class4int
+ return new self::Class4int::_();
+}
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+ core::print("inSoundMode: ${self::inSoundMode}");
+ self::testGeneric();
+ self::testBounded();
+}
+static method testGeneric() → dynamic {
+ <T extends core::Object? = dynamic>() → self::Class1<T%> f1a = #C1;
+ self::Class1<dynamic> c1a = f1a<dynamic>(){() → self::Class1<dynamic>};
+ self::expect(true, c1a is{ForNonNullableByDefault} self::Class1<dynamic>);
+ self::expect(false, c1a is{ForNonNullableByDefault} self::Class1<core::int>);
+ self::Class1<core::int> c1b = f1a<core::int>(){() → self::Class1<core::int>};
+ self::expect(true, c1b is{ForNonNullableByDefault} self::Class1<core::int>);
+ self::expect(false, c1b is{ForNonNullableByDefault} self::Class1<core::String>);
+ () → Null {
+ let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:27:8: Error: Expected 1 type arguments.
+ f1a<int, String>(); // error
+ ^" in f1a{<inapplicable>}.<core::int, core::String>();
+ };
+ () → self::Class1<core::int> f1b = f1a<core::int>;
+ self::Class1<core::int> c1c = f1b(){() → self::Class1<core::int>};
+ self::expect(true, c1c is{ForNonNullableByDefault} self::Class1<core::int>);
+ self::expect(false, c1c is{ForNonNullableByDefault} self::Class1<core::String>);
+ () → Null {
+ let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:35:8: Error: Expected 0 type arguments.
+ f1b<int>(); // error
+ ^" in f1b{<inapplicable>}.<core::int>();
+ };
+ dynamic f1c = #C1;
+ dynamic c1d = f1c{dynamic}.call();
+ self::expect(true, c1a is{ForNonNullableByDefault} self::Class1<dynamic>);
+ self::expect(false, c1a is{ForNonNullableByDefault} self::Class1<core::int>);
+ self::throws(() → dynamic => f1c{dynamic}.call<core::int, core::String>());
+}
+static method testBounded() → dynamic {
+ <T extends core::num>() → self::Class2<T> f2a = #C2;
+ self::Class2<core::num> c2a = f2a<core::num>(){() → self::Class2<core::num>};
+ self::expect(true, c2a is{ForNonNullableByDefault} self::Class2<core::num>);
+ self::expect(false, c2a is{ForNonNullableByDefault} self::Class2<core::int>);
+ self::Class2<core::int> c2b = f2a<core::int>(){() → self::Class2<core::int>};
+ self::expect(true, c2b is{ForNonNullableByDefault} self::Class2<core::int>);
+ self::expect(false, c2b is{ForNonNullableByDefault} self::Class2<core::double>);
+ () → Null {
+ f2a<core::String>(){() → self::Class2<core::String>};
+ let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:75:8: Error: Expected 1 type arguments.
+ f2a<int, String>(); // error
+ ^" in f2a{<inapplicable>}.<core::int, core::String>();
+ };
+ dynamic f2b = #C2;
+ dynamic c2c = f2b{dynamic}.call();
+ self::expect(true, c2c is{ForNonNullableByDefault} self::Class2<core::num>);
+ self::expect(false, c2c is{ForNonNullableByDefault} self::Class2<core::int>);
+ dynamic c2d = f2b{dynamic}.call<core::int>();
+ self::expect(true, c2d is{ForNonNullableByDefault} self::Class2<core::int>);
+ self::expect(false, c2d is{ForNonNullableByDefault} self::Class2<core::double>);
+ self::throws(() → dynamic => f2b{dynamic}.call<core::String>());
+ self::throws(() → dynamic => f2b{dynamic}.call<core::int, core::String>());
+ <T extends S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<T%, S%> f3a = #C3;
+ self::Class3<dynamic, dynamic> c3a = f3a<dynamic, dynamic>(){() → self::Class3<dynamic, dynamic>};
+ self::expect(true, c3a is{ForNonNullableByDefault} self::Class3<dynamic, dynamic>);
+ self::expect(false, c3a is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+ self::Class3<core::int, core::num> c3b = f3a<core::int, core::num>(){() → self::Class3<core::int, core::num>};
+ self::expect(true, c3b is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+ self::expect(false, c3b is{ForNonNullableByDefault} self::Class3<core::double, core::num>);
+ () → Null {
+ f3a<core::num, core::int>(){() → self::Class3<core::num, core::int>};
+ };
+ dynamic f3b = #C3;
+ dynamic c3c = f3b{dynamic}.call();
+ self::expect(true, c3c is{ForNonNullableByDefault} self::Class3<dynamic, dynamic>);
+ self::expect(false, c3c is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+ dynamic c3d = f3b{dynamic}.call<core::int, core::num>();
+ self::expect(true, c3d is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+ self::expect(false, c3d is{ForNonNullableByDefault} self::Class3<core::double, core::num>);
+ self::throws(() → dynamic => f3b{dynamic}.call<core::num, core::int>());
+ <T extends self::Class4<T> = self::Class4<dynamic>>() → self::Class4<T> f4a = #C4;
+ () → Null {
+ self::Class4<self::Class4<core::Object?>> c4a = f4a<self::Class4<core::Object?>>(){() → self::Class4<self::Class4<core::Object?>>};
+ };
+ dynamic f4b = #C4;
+ self::throws(() → dynamic => f4b{dynamic}.call());
+ dynamic c4b = f4b{dynamic}.call<self::Class4int>();
+ self::expect(true, c4b is{ForNonNullableByDefault} self::Class4<self::Class4int>);
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C5}) → dynamic {
+ try {
+ f(){() → dynamic};
+ }
+ on core::Object catch(final core::Object e) {
+ core::print("Thrown: ${e}");
+ return;
+ }
+ if(!self::inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw "Expected exception";
+}
+
+constants {
+ #C1 = static-tearoff self::Class1::_#new#tearOff
+ #C2 = static-tearoff self::Class2::_#new#tearOff
+ #C3 = static-tearoff self::Class3::_#new#tearOff
+ #C4 = static-tearoff self::Class4::_#new#tearOff
+ #C5 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart.strong.transformed.expect
new file mode 100644
index 0000000..2ede93c
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart.strong.transformed.expect
@@ -0,0 +1,205 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:27:8: Error: Expected 1 type arguments.
+// f1a<int, String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:35:8: Error: Expected 0 type arguments.
+// f1b<int>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:74:8: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'T' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+// f2a<String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:75:8: Error: Expected 1 type arguments.
+// f2a<int, String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:96:8: Error: Type argument 'num' doesn't conform to the bound 'S' of the type variable 'T' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+// f3a<num, int>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:110:18: Error: Inferred type argument 'Class4<Object?>' doesn't conform to the bound 'Class4<T>' of the type variable 'T' on 'call'.
+// - 'Class4' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart'.
+// - 'Object' is from 'dart:core'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// var c4a = f4a(); // error
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class1::•]/*isLegacy*/;
+ constructor _() → self::Class1<self::Class1::T%>
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff<T extends core::Object? = dynamic>() → self::Class1<self::Class1::_#_#tearOff::T%>
+ return new self::Class1::_<self::Class1::_#_#tearOff::T%>();
+ static factory •<T extends core::Object? = dynamic>() → self::Class1<self::Class1::•::T%>
+ let Never #redirecting_factory = self::Class1::_ in let self::Class1::•::T% #typeArg0 = null in invalid-expression;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class1<self::Class1::_#new#tearOff::T%>
+ return new self::Class1::_<self::Class1::_#new#tearOff::T%>();
+}
+class Class2<T extends core::num> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class2::•]/*isLegacy*/;
+ constructor _() → self::Class2<self::Class2::T>
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff<T extends core::num>() → self::Class2<self::Class2::_#_#tearOff::T>
+ return new self::Class2::_<self::Class2::_#_#tearOff::T>();
+ static factory •<T extends core::num>() → self::Class2<self::Class2::•::T>
+ let Never #redirecting_factory = self::Class2::_ in let self::Class2::•::T #typeArg0 = null in invalid-expression;
+ static method _#new#tearOff<T extends core::num>() → self::Class2<self::Class2::_#new#tearOff::T>
+ return new self::Class2::_<self::Class2::_#new#tearOff::T>();
+}
+class Class3<T extends self::Class3::S% = dynamic, S extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class3::•]/*isLegacy*/;
+ constructor _() → self::Class3<self::Class3::T%, self::Class3::S%>
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff<T extends self::Class3::_#_#tearOff::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::_#_#tearOff::T%, self::Class3::_#_#tearOff::S%>
+ return new self::Class3::_<self::Class3::_#_#tearOff::T%, self::Class3::_#_#tearOff::S%>();
+ static factory •<T extends self::Class3::•::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::•::T%, self::Class3::•::S%>
+ let Never #redirecting_factory = self::Class3::_ in let self::Class3::•::T% #typeArg0 = null in let self::Class3::•::S% #typeArg1 = null in invalid-expression;
+ static method _#new#tearOff<T extends self::Class3::_#new#tearOff::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::_#new#tearOff::T%, self::Class3::_#new#tearOff::S%>
+ return new self::Class3::_<self::Class3::_#new#tearOff::T%, self::Class3::_#new#tearOff::S%>();
+}
+class Class4<T extends self::Class4<self::Class4::T> = self::Class4<dynamic>> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class4::•]/*isLegacy*/;
+ constructor _() → self::Class4<self::Class4::T>
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff<T extends self::Class4<self::Class4::_#_#tearOff::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::_#_#tearOff::T>
+ return new self::Class4::_<self::Class4::_#_#tearOff::T>();
+ static factory •<T extends self::Class4<self::Class4::•::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::•::T>
+ let Never #redirecting_factory = self::Class4::_ in let self::Class4::•::T #typeArg0 = null in invalid-expression;
+ static method _#new#tearOff<T extends self::Class4<self::Class4::_#new#tearOff::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::_#new#tearOff::T>
+ return new self::Class4::_<self::Class4::_#new#tearOff::T>();
+}
+class Class4int extends self::Class4<self::Class4int> {
+ static final field dynamic _redirecting# = <dynamic>[self::Class4int::•]/*isLegacy*/;
+ constructor _() → self::Class4int
+ : super self::Class4::_()
+ ;
+ static method _#_#tearOff() → self::Class4int
+ return new self::Class4int::_();
+ static factory •() → self::Class4int
+ let Never #redirecting_factory = self::Class4int::_ in invalid-expression;
+ static method _#new#tearOff() → self::Class4int
+ return new self::Class4int::_();
+}
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+ core::print("inSoundMode: ${self::inSoundMode}");
+ self::testGeneric();
+ self::testBounded();
+}
+static method testGeneric() → dynamic {
+ <T extends core::Object? = dynamic>() → self::Class1<T%> f1a = #C1;
+ self::Class1<dynamic> c1a = f1a<dynamic>(){() → self::Class1<dynamic>};
+ self::expect(true, c1a is{ForNonNullableByDefault} self::Class1<dynamic>);
+ self::expect(false, c1a is{ForNonNullableByDefault} self::Class1<core::int>);
+ self::Class1<core::int> c1b = f1a<core::int>(){() → self::Class1<core::int>};
+ self::expect(true, c1b is{ForNonNullableByDefault} self::Class1<core::int>);
+ self::expect(false, c1b is{ForNonNullableByDefault} self::Class1<core::String>);
+ () → Null {
+ let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:27:8: Error: Expected 1 type arguments.
+ f1a<int, String>(); // error
+ ^" in f1a{<inapplicable>}.<core::int, core::String>();
+ };
+ () → self::Class1<core::int> f1b = f1a<core::int>;
+ self::Class1<core::int> c1c = f1b(){() → self::Class1<core::int>};
+ self::expect(true, c1c is{ForNonNullableByDefault} self::Class1<core::int>);
+ self::expect(false, c1c is{ForNonNullableByDefault} self::Class1<core::String>);
+ () → Null {
+ let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:35:8: Error: Expected 0 type arguments.
+ f1b<int>(); // error
+ ^" in f1b{<inapplicable>}.<core::int>();
+ };
+ dynamic f1c = #C1;
+ dynamic c1d = f1c{dynamic}.call();
+ self::expect(true, c1a is{ForNonNullableByDefault} self::Class1<dynamic>);
+ self::expect(false, c1a is{ForNonNullableByDefault} self::Class1<core::int>);
+ self::throws(() → dynamic => f1c{dynamic}.call<core::int, core::String>());
+}
+static method testBounded() → dynamic {
+ <T extends core::num>() → self::Class2<T> f2a = #C2;
+ self::Class2<core::num> c2a = f2a<core::num>(){() → self::Class2<core::num>};
+ self::expect(true, c2a is{ForNonNullableByDefault} self::Class2<core::num>);
+ self::expect(false, c2a is{ForNonNullableByDefault} self::Class2<core::int>);
+ self::Class2<core::int> c2b = f2a<core::int>(){() → self::Class2<core::int>};
+ self::expect(true, c2b is{ForNonNullableByDefault} self::Class2<core::int>);
+ self::expect(false, c2b is{ForNonNullableByDefault} self::Class2<core::double>);
+ () → Null {
+ f2a<core::String>(){() → self::Class2<core::String>};
+ let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:75:8: Error: Expected 1 type arguments.
+ f2a<int, String>(); // error
+ ^" in f2a{<inapplicable>}.<core::int, core::String>();
+ };
+ dynamic f2b = #C2;
+ dynamic c2c = f2b{dynamic}.call();
+ self::expect(true, c2c is{ForNonNullableByDefault} self::Class2<core::num>);
+ self::expect(false, c2c is{ForNonNullableByDefault} self::Class2<core::int>);
+ dynamic c2d = f2b{dynamic}.call<core::int>();
+ self::expect(true, c2d is{ForNonNullableByDefault} self::Class2<core::int>);
+ self::expect(false, c2d is{ForNonNullableByDefault} self::Class2<core::double>);
+ self::throws(() → dynamic => f2b{dynamic}.call<core::String>());
+ self::throws(() → dynamic => f2b{dynamic}.call<core::int, core::String>());
+ <T extends S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<T%, S%> f3a = #C3;
+ self::Class3<dynamic, dynamic> c3a = f3a<dynamic, dynamic>(){() → self::Class3<dynamic, dynamic>};
+ self::expect(true, c3a is{ForNonNullableByDefault} self::Class3<dynamic, dynamic>);
+ self::expect(false, c3a is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+ self::Class3<core::int, core::num> c3b = f3a<core::int, core::num>(){() → self::Class3<core::int, core::num>};
+ self::expect(true, c3b is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+ self::expect(false, c3b is{ForNonNullableByDefault} self::Class3<core::double, core::num>);
+ () → Null {
+ f3a<core::num, core::int>(){() → self::Class3<core::num, core::int>};
+ };
+ dynamic f3b = #C3;
+ dynamic c3c = f3b{dynamic}.call();
+ self::expect(true, c3c is{ForNonNullableByDefault} self::Class3<dynamic, dynamic>);
+ self::expect(false, c3c is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+ dynamic c3d = f3b{dynamic}.call<core::int, core::num>();
+ self::expect(true, c3d is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+ self::expect(false, c3d is{ForNonNullableByDefault} self::Class3<core::double, core::num>);
+ self::throws(() → dynamic => f3b{dynamic}.call<core::num, core::int>());
+ <T extends self::Class4<T> = self::Class4<dynamic>>() → self::Class4<T> f4a = #C4;
+ () → Null {
+ self::Class4<self::Class4<core::Object?>> c4a = f4a<self::Class4<core::Object?>>(){() → self::Class4<self::Class4<core::Object?>>};
+ };
+ dynamic f4b = #C4;
+ self::throws(() → dynamic => f4b{dynamic}.call());
+ dynamic c4b = f4b{dynamic}.call<self::Class4int>();
+ self::expect(true, c4b is{ForNonNullableByDefault} self::Class4<self::Class4int>);
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C5}) → dynamic {
+ try {
+ f(){() → dynamic};
+ }
+ on core::Object catch(final core::Object e) {
+ core::print("Thrown: ${e}");
+ return;
+ }
+ if(!self::inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw "Expected exception";
+}
+
+constants {
+ #C1 = static-tearoff self::Class1::_#new#tearOff
+ #C2 = static-tearoff self::Class2::_#new#tearOff
+ #C3 = static-tearoff self::Class3::_#new#tearOff
+ #C4 = static-tearoff self::Class4::_#new#tearOff
+ #C5 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart.textual_outline.expect
new file mode 100644
index 0000000..ad86735
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart.textual_outline.expect
@@ -0,0 +1,33 @@
+final bool inSoundMode = <int?>[] is! List<int>;
+main() {}
+
+class Class1<T> {
+ Class1._();
+ factory Class1() = Class1<T>._;
+}
+
+testGeneric() {}
+
+class Class2<T extends num> {
+ Class2._();
+ factory Class2() = Class2<T>._;
+}
+
+class Class3<T extends S, S> {
+ Class3._();
+ factory Class3() = Class3<T, S>._;
+}
+
+class Class4<T extends Class4<T>> {
+ Class4._();
+ factory Class4() = Class4<T>._;
+}
+
+class Class4int extends Class4<Class4int> {
+ Class4int._() : super._();
+ factory Class4int() = Class4int._;
+}
+
+testBounded() {}
+expect(expected, actual) {}
+throws(Function() f, {bool inSoundModeOnly: false}) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..24223f7
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart.textual_outline_modelled.expect
@@ -0,0 +1,31 @@
+class Class1<T> {
+ Class1._();
+ factory Class1() = Class1<T>._;
+}
+
+class Class2<T extends num> {
+ Class2._();
+ factory Class2() = Class2<T>._;
+}
+
+class Class3<T extends S, S> {
+ Class3._();
+ factory Class3() = Class3<T, S>._;
+}
+
+class Class4<T extends Class4<T>> {
+ Class4._();
+ factory Class4() = Class4<T>._;
+}
+
+class Class4int extends Class4<Class4int> {
+ Class4int._() : super._();
+ factory Class4int() = Class4int._;
+}
+
+expect(expected, actual) {}
+final bool inSoundMode = <int?>[] is! List<int>;
+main() {}
+testBounded() {}
+testGeneric() {}
+throws(Function() f, {bool inSoundModeOnly: false}) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart.weak.expect
new file mode 100644
index 0000000..14303b7
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart.weak.expect
@@ -0,0 +1,205 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:27:8: Error: Expected 1 type arguments.
+// f1a<int, String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:35:8: Error: Expected 0 type arguments.
+// f1b<int>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:74:8: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'T' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+// f2a<String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:75:8: Error: Expected 1 type arguments.
+// f2a<int, String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:96:8: Error: Type argument 'num' doesn't conform to the bound 'S' of the type variable 'T' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+// f3a<num, int>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:110:18: Error: Inferred type argument 'Class4<Object?>' doesn't conform to the bound 'Class4<T>' of the type variable 'T' on 'call'.
+// - 'Class4' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart'.
+// - 'Object' is from 'dart:core'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// var c4a = f4a(); // error
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class1::•]/*isLegacy*/;
+ constructor _() → self::Class1<self::Class1::T%>
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff<T extends core::Object? = dynamic>() → self::Class1<self::Class1::_#_#tearOff::T%>
+ return new self::Class1::_<self::Class1::_#_#tearOff::T%>();
+ static factory •<T extends core::Object? = dynamic>() → self::Class1<self::Class1::•::T%>
+ let dynamic #redirecting_factory = self::Class1::_ in let self::Class1::•::T% #typeArg0 = null in invalid-expression;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class1<self::Class1::_#new#tearOff::T%>
+ return new self::Class1::_<self::Class1::_#new#tearOff::T%>();
+}
+class Class2<T extends core::num> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class2::•]/*isLegacy*/;
+ constructor _() → self::Class2<self::Class2::T>
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff<T extends core::num>() → self::Class2<self::Class2::_#_#tearOff::T>
+ return new self::Class2::_<self::Class2::_#_#tearOff::T>();
+ static factory •<T extends core::num>() → self::Class2<self::Class2::•::T>
+ let dynamic #redirecting_factory = self::Class2::_ in let self::Class2::•::T #typeArg0 = null in invalid-expression;
+ static method _#new#tearOff<T extends core::num>() → self::Class2<self::Class2::_#new#tearOff::T>
+ return new self::Class2::_<self::Class2::_#new#tearOff::T>();
+}
+class Class3<T extends self::Class3::S% = dynamic, S extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class3::•]/*isLegacy*/;
+ constructor _() → self::Class3<self::Class3::T%, self::Class3::S%>
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff<T extends self::Class3::_#_#tearOff::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::_#_#tearOff::T%, self::Class3::_#_#tearOff::S%>
+ return new self::Class3::_<self::Class3::_#_#tearOff::T%, self::Class3::_#_#tearOff::S%>();
+ static factory •<T extends self::Class3::•::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::•::T%, self::Class3::•::S%>
+ let dynamic #redirecting_factory = self::Class3::_ in let self::Class3::•::T% #typeArg0 = null in let self::Class3::•::S% #typeArg1 = null in invalid-expression;
+ static method _#new#tearOff<T extends self::Class3::_#new#tearOff::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::_#new#tearOff::T%, self::Class3::_#new#tearOff::S%>
+ return new self::Class3::_<self::Class3::_#new#tearOff::T%, self::Class3::_#new#tearOff::S%>();
+}
+class Class4<T extends self::Class4<self::Class4::T> = self::Class4<dynamic>> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class4::•]/*isLegacy*/;
+ constructor _() → self::Class4<self::Class4::T>
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff<T extends self::Class4<self::Class4::_#_#tearOff::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::_#_#tearOff::T>
+ return new self::Class4::_<self::Class4::_#_#tearOff::T>();
+ static factory •<T extends self::Class4<self::Class4::•::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::•::T>
+ let dynamic #redirecting_factory = self::Class4::_ in let self::Class4::•::T #typeArg0 = null in invalid-expression;
+ static method _#new#tearOff<T extends self::Class4<self::Class4::_#new#tearOff::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::_#new#tearOff::T>
+ return new self::Class4::_<self::Class4::_#new#tearOff::T>();
+}
+class Class4int extends self::Class4<self::Class4int> {
+ static final field dynamic _redirecting# = <dynamic>[self::Class4int::•]/*isLegacy*/;
+ constructor _() → self::Class4int
+ : super self::Class4::_()
+ ;
+ static method _#_#tearOff() → self::Class4int
+ return new self::Class4int::_();
+ static factory •() → self::Class4int
+ let dynamic #redirecting_factory = self::Class4int::_ in invalid-expression;
+ static method _#new#tearOff() → self::Class4int
+ return new self::Class4int::_();
+}
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+ core::print("inSoundMode: ${self::inSoundMode}");
+ self::testGeneric();
+ self::testBounded();
+}
+static method testGeneric() → dynamic {
+ <T extends core::Object? = dynamic>() → self::Class1<T%> f1a = #C1;
+ self::Class1<dynamic> c1a = f1a<dynamic>(){() → self::Class1<dynamic>};
+ self::expect(true, c1a is{ForNonNullableByDefault} self::Class1<dynamic>);
+ self::expect(false, c1a is{ForNonNullableByDefault} self::Class1<core::int>);
+ self::Class1<core::int> c1b = f1a<core::int>(){() → self::Class1<core::int>};
+ self::expect(true, c1b is{ForNonNullableByDefault} self::Class1<core::int>);
+ self::expect(false, c1b is{ForNonNullableByDefault} self::Class1<core::String>);
+ () → Null {
+ let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:27:8: Error: Expected 1 type arguments.
+ f1a<int, String>(); // error
+ ^" in f1a{<inapplicable>}.<core::int, core::String>();
+ };
+ () → self::Class1<core::int> f1b = f1a<core::int>;
+ self::Class1<core::int> c1c = f1b(){() → self::Class1<core::int>};
+ self::expect(true, c1c is{ForNonNullableByDefault} self::Class1<core::int>);
+ self::expect(false, c1c is{ForNonNullableByDefault} self::Class1<core::String>);
+ () → Null {
+ let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:35:8: Error: Expected 0 type arguments.
+ f1b<int>(); // error
+ ^" in f1b{<inapplicable>}.<core::int>();
+ };
+ dynamic f1c = #C1;
+ dynamic c1d = f1c{dynamic}.call();
+ self::expect(true, c1a is{ForNonNullableByDefault} self::Class1<dynamic>);
+ self::expect(false, c1a is{ForNonNullableByDefault} self::Class1<core::int>);
+ self::throws(() → dynamic => f1c{dynamic}.call<core::int, core::String>());
+}
+static method testBounded() → dynamic {
+ <T extends core::num>() → self::Class2<T> f2a = #C2;
+ self::Class2<core::num> c2a = f2a<core::num>(){() → self::Class2<core::num>};
+ self::expect(true, c2a is{ForNonNullableByDefault} self::Class2<core::num>);
+ self::expect(false, c2a is{ForNonNullableByDefault} self::Class2<core::int>);
+ self::Class2<core::int> c2b = f2a<core::int>(){() → self::Class2<core::int>};
+ self::expect(true, c2b is{ForNonNullableByDefault} self::Class2<core::int>);
+ self::expect(false, c2b is{ForNonNullableByDefault} self::Class2<core::double>);
+ () → Null {
+ f2a<core::String>(){() → self::Class2<core::String>};
+ let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:75:8: Error: Expected 1 type arguments.
+ f2a<int, String>(); // error
+ ^" in f2a{<inapplicable>}.<core::int, core::String>();
+ };
+ dynamic f2b = #C2;
+ dynamic c2c = f2b{dynamic}.call();
+ self::expect(true, c2c is{ForNonNullableByDefault} self::Class2<core::num>);
+ self::expect(false, c2c is{ForNonNullableByDefault} self::Class2<core::int>);
+ dynamic c2d = f2b{dynamic}.call<core::int>();
+ self::expect(true, c2d is{ForNonNullableByDefault} self::Class2<core::int>);
+ self::expect(false, c2d is{ForNonNullableByDefault} self::Class2<core::double>);
+ self::throws(() → dynamic => f2b{dynamic}.call<core::String>());
+ self::throws(() → dynamic => f2b{dynamic}.call<core::int, core::String>());
+ <T extends S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<T%, S%> f3a = #C3;
+ self::Class3<dynamic, dynamic> c3a = f3a<dynamic, dynamic>(){() → self::Class3<dynamic, dynamic>};
+ self::expect(true, c3a is{ForNonNullableByDefault} self::Class3<dynamic, dynamic>);
+ self::expect(false, c3a is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+ self::Class3<core::int, core::num> c3b = f3a<core::int, core::num>(){() → self::Class3<core::int, core::num>};
+ self::expect(true, c3b is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+ self::expect(false, c3b is{ForNonNullableByDefault} self::Class3<core::double, core::num>);
+ () → Null {
+ f3a<core::num, core::int>(){() → self::Class3<core::num, core::int>};
+ };
+ dynamic f3b = #C3;
+ dynamic c3c = f3b{dynamic}.call();
+ self::expect(true, c3c is{ForNonNullableByDefault} self::Class3<dynamic, dynamic>);
+ self::expect(false, c3c is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+ dynamic c3d = f3b{dynamic}.call<core::int, core::num>();
+ self::expect(true, c3d is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+ self::expect(false, c3d is{ForNonNullableByDefault} self::Class3<core::double, core::num>);
+ self::throws(() → dynamic => f3b{dynamic}.call<core::num, core::int>());
+ <T extends self::Class4<T> = self::Class4<dynamic>>() → self::Class4<T> f4a = #C4;
+ () → Null {
+ self::Class4<self::Class4<core::Object?>> c4a = f4a<self::Class4<core::Object?>>(){() → self::Class4<self::Class4<core::Object?>>};
+ };
+ dynamic f4b = #C4;
+ self::throws(() → dynamic => f4b{dynamic}.call());
+ dynamic c4b = f4b{dynamic}.call<self::Class4int>();
+ self::expect(true, c4b is{ForNonNullableByDefault} self::Class4<self::Class4int>);
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C5}) → dynamic {
+ try {
+ f(){() → dynamic};
+ }
+ on core::Object catch(final core::Object e) {
+ core::print("Thrown: ${e}");
+ return;
+ }
+ if(!self::inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw "Expected exception";
+}
+
+constants {
+ #C1 = static-tearoff self::Class1::_#new#tearOff
+ #C2 = static-tearoff self::Class2::_#new#tearOff
+ #C3 = static-tearoff self::Class3::_#new#tearOff
+ #C4 = static-tearoff self::Class4::_#new#tearOff
+ #C5 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart.weak.outline.expect
new file mode 100644
index 0000000..26553e6
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart.weak.outline.expect
@@ -0,0 +1,70 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Class1<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class1::•]/*isLegacy*/;
+ constructor _() → self::Class1<self::Class1::T%>
+ ;
+ static method _#_#tearOff<T extends core::Object? = dynamic>() → self::Class1<self::Class1::_#_#tearOff::T%>
+ return new self::Class1::_<self::Class1::_#_#tearOff::T%>();
+ static factory •<T extends core::Object? = dynamic>() → self::Class1<self::Class1::•::T%>
+ let dynamic #redirecting_factory = self::Class1::_ in let self::Class1::•::T% #typeArg0 = null in invalid-expression;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class1<self::Class1::_#new#tearOff::T%>
+ return new self::Class1::_<self::Class1::_#new#tearOff::T%>();
+}
+class Class2<T extends core::num> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class2::•]/*isLegacy*/;
+ constructor _() → self::Class2<self::Class2::T>
+ ;
+ static method _#_#tearOff<T extends core::num>() → self::Class2<self::Class2::_#_#tearOff::T>
+ return new self::Class2::_<self::Class2::_#_#tearOff::T>();
+ static factory •<T extends core::num>() → self::Class2<self::Class2::•::T>
+ let dynamic #redirecting_factory = self::Class2::_ in let self::Class2::•::T #typeArg0 = null in invalid-expression;
+ static method _#new#tearOff<T extends core::num>() → self::Class2<self::Class2::_#new#tearOff::T>
+ return new self::Class2::_<self::Class2::_#new#tearOff::T>();
+}
+class Class3<T extends self::Class3::S% = dynamic, S extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class3::•]/*isLegacy*/;
+ constructor _() → self::Class3<self::Class3::T%, self::Class3::S%>
+ ;
+ static method _#_#tearOff<T extends self::Class3::_#_#tearOff::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::_#_#tearOff::T%, self::Class3::_#_#tearOff::S%>
+ return new self::Class3::_<self::Class3::_#_#tearOff::T%, self::Class3::_#_#tearOff::S%>();
+ static factory •<T extends self::Class3::•::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::•::T%, self::Class3::•::S%>
+ let dynamic #redirecting_factory = self::Class3::_ in let self::Class3::•::T% #typeArg0 = null in let self::Class3::•::S% #typeArg1 = null in invalid-expression;
+ static method _#new#tearOff<T extends self::Class3::_#new#tearOff::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::_#new#tearOff::T%, self::Class3::_#new#tearOff::S%>
+ return new self::Class3::_<self::Class3::_#new#tearOff::T%, self::Class3::_#new#tearOff::S%>();
+}
+class Class4<T extends self::Class4<self::Class4::T> = self::Class4<dynamic>> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class4::•]/*isLegacy*/;
+ constructor _() → self::Class4<self::Class4::T>
+ ;
+ static method _#_#tearOff<T extends self::Class4<self::Class4::_#_#tearOff::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::_#_#tearOff::T>
+ return new self::Class4::_<self::Class4::_#_#tearOff::T>();
+ static factory •<T extends self::Class4<self::Class4::•::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::•::T>
+ let dynamic #redirecting_factory = self::Class4::_ in let self::Class4::•::T #typeArg0 = null in invalid-expression;
+ static method _#new#tearOff<T extends self::Class4<self::Class4::_#new#tearOff::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::_#new#tearOff::T>
+ return new self::Class4::_<self::Class4::_#new#tearOff::T>();
+}
+class Class4int extends self::Class4<self::Class4int> {
+ static final field dynamic _redirecting# = <dynamic>[self::Class4int::•]/*isLegacy*/;
+ constructor _() → self::Class4int
+ ;
+ static method _#_#tearOff() → self::Class4int
+ return new self::Class4int::_();
+ static factory •() → self::Class4int
+ let dynamic #redirecting_factory = self::Class4int::_ in invalid-expression;
+ static method _#new#tearOff() → self::Class4int
+ return new self::Class4int::_();
+}
+static final field core::bool inSoundMode;
+static method main() → dynamic
+ ;
+static method testGeneric() → dynamic
+ ;
+static method testBounded() → dynamic
+ ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+ ;
+static method throws(() → dynamic f, {core::bool inSoundModeOnly}) → dynamic
+ ;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart.weak.transformed.expect
new file mode 100644
index 0000000..2ede93c
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart.weak.transformed.expect
@@ -0,0 +1,205 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:27:8: Error: Expected 1 type arguments.
+// f1a<int, String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:35:8: Error: Expected 0 type arguments.
+// f1b<int>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:74:8: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'T' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+// f2a<String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:75:8: Error: Expected 1 type arguments.
+// f2a<int, String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:96:8: Error: Type argument 'num' doesn't conform to the bound 'S' of the type variable 'T' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+// f3a<num, int>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:110:18: Error: Inferred type argument 'Class4<Object?>' doesn't conform to the bound 'Class4<T>' of the type variable 'T' on 'call'.
+// - 'Class4' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart'.
+// - 'Object' is from 'dart:core'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+// var c4a = f4a(); // error
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class1::•]/*isLegacy*/;
+ constructor _() → self::Class1<self::Class1::T%>
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff<T extends core::Object? = dynamic>() → self::Class1<self::Class1::_#_#tearOff::T%>
+ return new self::Class1::_<self::Class1::_#_#tearOff::T%>();
+ static factory •<T extends core::Object? = dynamic>() → self::Class1<self::Class1::•::T%>
+ let Never #redirecting_factory = self::Class1::_ in let self::Class1::•::T% #typeArg0 = null in invalid-expression;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class1<self::Class1::_#new#tearOff::T%>
+ return new self::Class1::_<self::Class1::_#new#tearOff::T%>();
+}
+class Class2<T extends core::num> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class2::•]/*isLegacy*/;
+ constructor _() → self::Class2<self::Class2::T>
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff<T extends core::num>() → self::Class2<self::Class2::_#_#tearOff::T>
+ return new self::Class2::_<self::Class2::_#_#tearOff::T>();
+ static factory •<T extends core::num>() → self::Class2<self::Class2::•::T>
+ let Never #redirecting_factory = self::Class2::_ in let self::Class2::•::T #typeArg0 = null in invalid-expression;
+ static method _#new#tearOff<T extends core::num>() → self::Class2<self::Class2::_#new#tearOff::T>
+ return new self::Class2::_<self::Class2::_#new#tearOff::T>();
+}
+class Class3<T extends self::Class3::S% = dynamic, S extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class3::•]/*isLegacy*/;
+ constructor _() → self::Class3<self::Class3::T%, self::Class3::S%>
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff<T extends self::Class3::_#_#tearOff::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::_#_#tearOff::T%, self::Class3::_#_#tearOff::S%>
+ return new self::Class3::_<self::Class3::_#_#tearOff::T%, self::Class3::_#_#tearOff::S%>();
+ static factory •<T extends self::Class3::•::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::•::T%, self::Class3::•::S%>
+ let Never #redirecting_factory = self::Class3::_ in let self::Class3::•::T% #typeArg0 = null in let self::Class3::•::S% #typeArg1 = null in invalid-expression;
+ static method _#new#tearOff<T extends self::Class3::_#new#tearOff::S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<self::Class3::_#new#tearOff::T%, self::Class3::_#new#tearOff::S%>
+ return new self::Class3::_<self::Class3::_#new#tearOff::T%, self::Class3::_#new#tearOff::S%>();
+}
+class Class4<T extends self::Class4<self::Class4::T> = self::Class4<dynamic>> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class4::•]/*isLegacy*/;
+ constructor _() → self::Class4<self::Class4::T>
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff<T extends self::Class4<self::Class4::_#_#tearOff::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::_#_#tearOff::T>
+ return new self::Class4::_<self::Class4::_#_#tearOff::T>();
+ static factory •<T extends self::Class4<self::Class4::•::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::•::T>
+ let Never #redirecting_factory = self::Class4::_ in let self::Class4::•::T #typeArg0 = null in invalid-expression;
+ static method _#new#tearOff<T extends self::Class4<self::Class4::_#new#tearOff::T> = self::Class4<dynamic>>() → self::Class4<self::Class4::_#new#tearOff::T>
+ return new self::Class4::_<self::Class4::_#new#tearOff::T>();
+}
+class Class4int extends self::Class4<self::Class4int> {
+ static final field dynamic _redirecting# = <dynamic>[self::Class4int::•]/*isLegacy*/;
+ constructor _() → self::Class4int
+ : super self::Class4::_()
+ ;
+ static method _#_#tearOff() → self::Class4int
+ return new self::Class4int::_();
+ static factory •() → self::Class4int
+ let Never #redirecting_factory = self::Class4int::_ in invalid-expression;
+ static method _#new#tearOff() → self::Class4int
+ return new self::Class4int::_();
+}
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+ core::print("inSoundMode: ${self::inSoundMode}");
+ self::testGeneric();
+ self::testBounded();
+}
+static method testGeneric() → dynamic {
+ <T extends core::Object? = dynamic>() → self::Class1<T%> f1a = #C1;
+ self::Class1<dynamic> c1a = f1a<dynamic>(){() → self::Class1<dynamic>};
+ self::expect(true, c1a is{ForNonNullableByDefault} self::Class1<dynamic>);
+ self::expect(false, c1a is{ForNonNullableByDefault} self::Class1<core::int>);
+ self::Class1<core::int> c1b = f1a<core::int>(){() → self::Class1<core::int>};
+ self::expect(true, c1b is{ForNonNullableByDefault} self::Class1<core::int>);
+ self::expect(false, c1b is{ForNonNullableByDefault} self::Class1<core::String>);
+ () → Null {
+ let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:27:8: Error: Expected 1 type arguments.
+ f1a<int, String>(); // error
+ ^" in f1a{<inapplicable>}.<core::int, core::String>();
+ };
+ () → self::Class1<core::int> f1b = f1a<core::int>;
+ self::Class1<core::int> c1c = f1b(){() → self::Class1<core::int>};
+ self::expect(true, c1c is{ForNonNullableByDefault} self::Class1<core::int>);
+ self::expect(false, c1c is{ForNonNullableByDefault} self::Class1<core::String>);
+ () → Null {
+ let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:35:8: Error: Expected 0 type arguments.
+ f1b<int>(); // error
+ ^" in f1b{<inapplicable>}.<core::int>();
+ };
+ dynamic f1c = #C1;
+ dynamic c1d = f1c{dynamic}.call();
+ self::expect(true, c1a is{ForNonNullableByDefault} self::Class1<dynamic>);
+ self::expect(false, c1a is{ForNonNullableByDefault} self::Class1<core::int>);
+ self::throws(() → dynamic => f1c{dynamic}.call<core::int, core::String>());
+}
+static method testBounded() → dynamic {
+ <T extends core::num>() → self::Class2<T> f2a = #C2;
+ self::Class2<core::num> c2a = f2a<core::num>(){() → self::Class2<core::num>};
+ self::expect(true, c2a is{ForNonNullableByDefault} self::Class2<core::num>);
+ self::expect(false, c2a is{ForNonNullableByDefault} self::Class2<core::int>);
+ self::Class2<core::int> c2b = f2a<core::int>(){() → self::Class2<core::int>};
+ self::expect(true, c2b is{ForNonNullableByDefault} self::Class2<core::int>);
+ self::expect(false, c2b is{ForNonNullableByDefault} self::Class2<core::double>);
+ () → Null {
+ f2a<core::String>(){() → self::Class2<core::String>};
+ let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/generic_redirecting_factory_tear_off.dart:75:8: Error: Expected 1 type arguments.
+ f2a<int, String>(); // error
+ ^" in f2a{<inapplicable>}.<core::int, core::String>();
+ };
+ dynamic f2b = #C2;
+ dynamic c2c = f2b{dynamic}.call();
+ self::expect(true, c2c is{ForNonNullableByDefault} self::Class2<core::num>);
+ self::expect(false, c2c is{ForNonNullableByDefault} self::Class2<core::int>);
+ dynamic c2d = f2b{dynamic}.call<core::int>();
+ self::expect(true, c2d is{ForNonNullableByDefault} self::Class2<core::int>);
+ self::expect(false, c2d is{ForNonNullableByDefault} self::Class2<core::double>);
+ self::throws(() → dynamic => f2b{dynamic}.call<core::String>());
+ self::throws(() → dynamic => f2b{dynamic}.call<core::int, core::String>());
+ <T extends S% = dynamic, S extends core::Object? = dynamic>() → self::Class3<T%, S%> f3a = #C3;
+ self::Class3<dynamic, dynamic> c3a = f3a<dynamic, dynamic>(){() → self::Class3<dynamic, dynamic>};
+ self::expect(true, c3a is{ForNonNullableByDefault} self::Class3<dynamic, dynamic>);
+ self::expect(false, c3a is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+ self::Class3<core::int, core::num> c3b = f3a<core::int, core::num>(){() → self::Class3<core::int, core::num>};
+ self::expect(true, c3b is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+ self::expect(false, c3b is{ForNonNullableByDefault} self::Class3<core::double, core::num>);
+ () → Null {
+ f3a<core::num, core::int>(){() → self::Class3<core::num, core::int>};
+ };
+ dynamic f3b = #C3;
+ dynamic c3c = f3b{dynamic}.call();
+ self::expect(true, c3c is{ForNonNullableByDefault} self::Class3<dynamic, dynamic>);
+ self::expect(false, c3c is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+ dynamic c3d = f3b{dynamic}.call<core::int, core::num>();
+ self::expect(true, c3d is{ForNonNullableByDefault} self::Class3<core::int, core::num>);
+ self::expect(false, c3d is{ForNonNullableByDefault} self::Class3<core::double, core::num>);
+ self::throws(() → dynamic => f3b{dynamic}.call<core::num, core::int>());
+ <T extends self::Class4<T> = self::Class4<dynamic>>() → self::Class4<T> f4a = #C4;
+ () → Null {
+ self::Class4<self::Class4<core::Object?>> c4a = f4a<self::Class4<core::Object?>>(){() → self::Class4<self::Class4<core::Object?>>};
+ };
+ dynamic f4b = #C4;
+ self::throws(() → dynamic => f4b{dynamic}.call());
+ dynamic c4b = f4b{dynamic}.call<self::Class4int>();
+ self::expect(true, c4b is{ForNonNullableByDefault} self::Class4<self::Class4int>);
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C5}) → dynamic {
+ try {
+ f(){() → dynamic};
+ }
+ on core::Object catch(final core::Object e) {
+ core::print("Thrown: ${e}");
+ return;
+ }
+ if(!self::inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw "Expected exception";
+}
+
+constants {
+ #C1 = static-tearoff self::Class1::_#new#tearOff
+ #C2 = static-tearoff self::Class2::_#new#tearOff
+ #C3 = static-tearoff self::Class3::_#new#tearOff
+ #C4 = static-tearoff self::Class4::_#new#tearOff
+ #C5 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart
index fc8cba1..1750b68 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart
@@ -25,6 +25,9 @@
Class2(this.field);
}
+var Class1_new = Class1.new;
+var Class2_new = Class2.new;
+
testInferred() {
var f1a = Class1.new;
expect(true, f1a is Class1 Function(int));
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.strong.expect
index edd7977..fa85f71 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.strong.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.strong.expect
@@ -2,11 +2,11 @@
//
// Problems in library:
//
-// pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:35:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:38:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
// f1a(''); // error
// ^
//
-// pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:49:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:52:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
// f2a(''); // error
// ^
//
@@ -36,6 +36,8 @@
return new self::Class2::•(field);
}
static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static field (core::int) → self::Class1 Class1_new = #C1;
+static field (core::int) → self::Class2 Class2_new = #C2;
static method main() → dynamic {
core::print("inSoundMode: ${self::inSoundMode}");
self::testInferred();
@@ -47,7 +49,7 @@
self::Class1 c1a = f1a(0){(core::int) → self::Class1};
self::expect(true, c1a is{ForNonNullableByDefault} self::Class1);
() → Null {
- f1a(let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:35:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+ f1a(let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:38:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
f1a(''); // error
^" in "" as{TypeError,ForNonNullableByDefault} core::int){(core::int) → self::Class1};
};
@@ -61,7 +63,7 @@
self::Class2 c2a = f2a(0){(core::int) → self::Class2};
self::expect(true, c2a is{ForNonNullableByDefault} self::Class2);
() → Null {
- f2a(let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:49:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+ f2a(let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:52:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
f2a(''); // error
^" in "" as{TypeError,ForNonNullableByDefault} core::int){(core::int) → self::Class2};
};
@@ -89,7 +91,7 @@
}
constants {
- #C1 = tearoff self::Class1::_#new#tearOff
- #C2 = tearoff self::Class2::_#new#tearOff
+ #C1 = static-tearoff self::Class1::_#new#tearOff
+ #C2 = static-tearoff self::Class2::_#new#tearOff
#C3 = false
}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.strong.transformed.expect
index 9297490..2664cf0 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.strong.transformed.expect
@@ -2,11 +2,11 @@
//
// Problems in library:
//
-// pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:35:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:38:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
// f1a(''); // error
// ^
//
-// pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:49:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:52:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
// f2a(''); // error
// ^
//
@@ -36,6 +36,8 @@
return new self::Class2::•(field);
}
static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static field (core::int) → self::Class1 Class1_new = #C1;
+static field (core::int) → self::Class2 Class2_new = #C2;
static method main() → dynamic {
core::print("inSoundMode: ${self::inSoundMode}");
self::testInferred();
@@ -47,7 +49,7 @@
self::Class1 c1a = f1a(0){(core::int) → self::Class1};
self::expect(true, c1a is{ForNonNullableByDefault} self::Class1);
() → Null {
- f1a(let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:35:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+ f1a(let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:38:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
f1a(''); // error
^" in "" as{TypeError,ForNonNullableByDefault} core::int){(core::int) → self::Class1};
};
@@ -61,7 +63,7 @@
self::Class2 c2a = f2a(0){(core::int) → self::Class2};
self::expect(true, c2a is{ForNonNullableByDefault} self::Class2);
() → Null {
- f2a(let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:49:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+ f2a(let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:52:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
f2a(''); // error
^" in "" as{TypeError,ForNonNullableByDefault} core::int){(core::int) → self::Class2};
};
@@ -89,7 +91,7 @@
}
constants {
- #C1 = tearoff self::Class1::_#new#tearOff
- #C2 = tearoff self::Class2::_#new#tearOff
+ #C1 = static-tearoff self::Class1::_#new#tearOff
+ #C2 = static-tearoff self::Class2::_#new#tearOff
#C3 = false
}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.textual_outline.expect
index 9e086db..94115d1 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.textual_outline.expect
@@ -1,20 +1,18 @@
final bool inSoundMode = <int?>[] is! List<int>;
main() {}
-
class Class1 {
int field;
Class1(this.field);
}
-
abstract class Interface2 {
int get field;
}
-
class Class2 implements Interface2 {
final field;
Class2(this.field);
}
-
+var Class1_new = Class1.new;
+var Class2_new = Class2.new;
testInferred() {}
expect(expected, actual) {}
throws(Function() f, {bool inSoundModeOnly: false}) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.weak.expect
index edd7977..fa85f71 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.weak.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.weak.expect
@@ -2,11 +2,11 @@
//
// Problems in library:
//
-// pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:35:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:38:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
// f1a(''); // error
// ^
//
-// pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:49:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:52:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
// f2a(''); // error
// ^
//
@@ -36,6 +36,8 @@
return new self::Class2::•(field);
}
static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static field (core::int) → self::Class1 Class1_new = #C1;
+static field (core::int) → self::Class2 Class2_new = #C2;
static method main() → dynamic {
core::print("inSoundMode: ${self::inSoundMode}");
self::testInferred();
@@ -47,7 +49,7 @@
self::Class1 c1a = f1a(0){(core::int) → self::Class1};
self::expect(true, c1a is{ForNonNullableByDefault} self::Class1);
() → Null {
- f1a(let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:35:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+ f1a(let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:38:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
f1a(''); // error
^" in "" as{TypeError,ForNonNullableByDefault} core::int){(core::int) → self::Class1};
};
@@ -61,7 +63,7 @@
self::Class2 c2a = f2a(0){(core::int) → self::Class2};
self::expect(true, c2a is{ForNonNullableByDefault} self::Class2);
() → Null {
- f2a(let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:49:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+ f2a(let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:52:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
f2a(''); // error
^" in "" as{TypeError,ForNonNullableByDefault} core::int){(core::int) → self::Class2};
};
@@ -89,7 +91,7 @@
}
constants {
- #C1 = tearoff self::Class1::_#new#tearOff
- #C2 = tearoff self::Class2::_#new#tearOff
+ #C1 = static-tearoff self::Class1::_#new#tearOff
+ #C2 = static-tearoff self::Class2::_#new#tearOff
#C3 = false
}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.weak.outline.expect
index 802525c..cc60ae4 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.weak.outline.expect
@@ -22,6 +22,8 @@
return new self::Class2::•(field);
}
static final field core::bool inSoundMode;
+static field (core::int) → self::Class1 Class1_new;
+static field (core::int) → self::Class2 Class2_new;
static method main() → dynamic
;
static method testInferred() → dynamic
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.weak.transformed.expect
index 9297490..2664cf0 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart.weak.transformed.expect
@@ -2,11 +2,11 @@
//
// Problems in library:
//
-// pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:35:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:38:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
// f1a(''); // error
// ^
//
-// pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:49:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:52:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
// f2a(''); // error
// ^
//
@@ -36,6 +36,8 @@
return new self::Class2::•(field);
}
static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static field (core::int) → self::Class1 Class1_new = #C1;
+static field (core::int) → self::Class2 Class2_new = #C2;
static method main() → dynamic {
core::print("inSoundMode: ${self::inSoundMode}");
self::testInferred();
@@ -47,7 +49,7 @@
self::Class1 c1a = f1a(0){(core::int) → self::Class1};
self::expect(true, c1a is{ForNonNullableByDefault} self::Class1);
() → Null {
- f1a(let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:35:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+ f1a(let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:38:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
f1a(''); // error
^" in "" as{TypeError,ForNonNullableByDefault} core::int){(core::int) → self::Class1};
};
@@ -61,7 +63,7 @@
self::Class2 c2a = f2a(0){(core::int) → self::Class2};
self::expect(true, c2a is{ForNonNullableByDefault} self::Class2);
() → Null {
- f2a(let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:49:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
+ f2a(let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_constructor_tear_off.dart:52:9: Error: The argument type 'String' can't be assigned to the parameter type 'int'.
f2a(''); // error
^" in "" as{TypeError,ForNonNullableByDefault} core::int){(core::int) → self::Class2};
};
@@ -89,7 +91,7 @@
}
constants {
- #C1 = tearoff self::Class1::_#new#tearOff
- #C2 = tearoff self::Class2::_#new#tearOff
+ #C1 = static-tearoff self::Class1::_#new#tearOff
+ #C2 = static-tearoff self::Class2::_#new#tearOff
#C3 = false
}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart
new file mode 100644
index 0000000..36599bd
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart
@@ -0,0 +1,103 @@
+// 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.
+
+final bool inSoundMode = <int?>[] is! List<int>;
+
+class A<T> {
+ A();
+ factory A.fact() => new A<T>();
+ factory A.redirect() = A<T>;
+}
+
+typedef F<X extends num> = A<X>;
+typedef G<Y> = A<int>;
+typedef H<X, Y> = A<X>;
+
+const f1a = A<int>.new;
+const f1b = F<int>.new;
+const A<int> Function() f1c = F.new;
+const f1d = A<int>.fact;
+const f1e = F<int>.fact;
+const A<int> Function() f1f = F.fact;
+const f1g = A<int>.redirect;
+const f1h = F<int>.redirect;
+const A<int> Function() f1i = F.redirect;
+
+const g1a = A<int>.new;
+const g1b = G<String>.new;
+const A<int> Function() g1c = G.new;
+
+const h1a = A<int>.new;
+const h1b = H<int, String>.new;
+const A<int> Function() h1c = H.new;
+
+main() {
+ test<int>();
+
+ identical(f1a, f1b);
+ identical(f1a, f1c);
+
+ identical(f1d, f1e);
+ identical(f1d, f1f);
+
+ identical(f1g, f1h);
+ identical(f1g, f1i);
+
+ identical(g1a, g1b);
+ identical(g1a, g1c);
+
+ identical(h1a, h1b);
+ identical(h1a, h1c);
+}
+
+test<T extends num>() {
+ var f2a = A<T>.new;
+ var f2b = F<T>.new;
+ A<T> Function() f2c = F.new;
+ var f2d = A<T>.fact;
+ var f2e = F<T>.fact;
+ A<T> Function() f2f = F.fact;
+ var f2g = A<T>.redirect;
+ var f2h = F<T>.redirect;
+ A<T> Function() f2i = F.redirect;
+
+ var g2a = A<int>.new;
+ var g2b = G<T>.new;
+ A<int> Function() g2c = G.new;
+
+ var h2a = A<T>.new;
+ var h2b = H<T, String>.new;
+ A<T> Function() h2c = H.new;
+
+ // TODO(johnniwinther): Enable these if structural equality is supported at
+ // runtime.
+ /*expect(f1a, f2a);
+ expect(f2a, f2b);
+ expect(f2a, f2c);
+
+ expect(f1d, f2d);
+ expect(f2d, f2e);
+ expect(f2d, f2f);
+
+ expect(f1g, f2g);
+ expect(f2g, f2h);
+ expect(f2g, f2i);*/
+
+ expect(g1a, g2a);
+ expect(g2a, g2b);
+ if (inSoundMode) {
+ // In weak mode type arguments of constants are weakened.
+ expect(g2a, g2c);
+ }
+
+ // TODO(johnniwinther): Enable these if structural equality is supported at
+ // runtime.
+ /*expect(h1a, h2a);
+ expect(h2a, h2b);
+ expect(h2a, h2c);*/
+}
+
+expect(expected, actual) {
+ if (expected != actual) throw 'Expected $expected, actual $actual';
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.strong.expect
new file mode 100644
index 0000000..9277874
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.strong.expect
@@ -0,0 +1,105 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F<X extends core::num> = self::A<X>;
+typedef G<unrelated Y extends core::Object? = dynamic> = self::A<core::int>;
+typedef H<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic> = self::A<X%>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::A::redirect]/*isLegacy*/;
+ constructor •() → self::A<self::A::T%>
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#new#tearOff::T%>
+ return new self::A::•<self::A::_#new#tearOff::T%>();
+ static factory fact<T extends core::Object? = dynamic>() → self::A<self::A::fact::T%>
+ return new self::A::•<self::A::fact::T%>();
+ static method _#fact#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#fact#tearOff::T%>
+ return self::A::fact<self::A::_#fact#tearOff::T%>();
+ static factory redirect<T extends core::Object? = dynamic>() → self::A<self::A::redirect::T%>
+ let dynamic #redirecting_factory = self::A::• in let self::A::redirect::T% #typeArg0 = null in invalid-expression;
+ static method _#redirect#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#redirect#tearOff::T%>
+ return new self::A::•<self::A::_#redirect#tearOff::T%>();
+}
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static const field () → self::A<core::int> f1a = #C2;
+static const field () → self::A<core::int> f1b = #C2;
+static const field () → self::A<core::int> f1c = #C2;
+static const field () → self::A<core::int> f1d = #C4;
+static const field () → self::A<core::int> f1e = #C4;
+static const field () → self::A<core::int> f1f = #C4;
+static const field () → self::A<core::int> f1g = #C6;
+static const field () → self::A<core::int> f1h = #C6;
+static const field () → self::A<core::int> f1i = #C6;
+static const field () → self::A<core::int> g1a = #C2;
+static const field () → self::A<core::int> g1b = #C2;
+static const field () → self::A<core::int> g1c = #C2;
+static const field () → self::A<core::int> h1a = #C2;
+static const field () → self::A<core::int> h1b = #C2;
+static const field () → self::A<core::int> h1c = #C2;
+static method main() → dynamic {
+ self::test<core::int>();
+ core::identical(#C2, #C2);
+ core::identical(#C2, #C2);
+ core::identical(#C4, #C4);
+ core::identical(#C4, #C4);
+ core::identical(#C6, #C6);
+ core::identical(#C6, #C6);
+ core::identical(#C2, #C2);
+ core::identical(#C2, #C2);
+ core::identical(#C2, #C2);
+ core::identical(#C2, #C2);
+}
+static method test<T extends core::num>() → dynamic {
+ () → self::A<self::test::T> f2a = #C1<self::test::T>;
+ () → self::A<self::test::T> f2b = #C1<self::test::T>;
+ () → self::A<self::test::T> f2c = #C1<self::test::T>;
+ () → self::A<self::test::T> f2d = #C3<self::test::T>;
+ () → self::A<self::test::T> f2e = #C3<self::test::T>;
+ () → self::A<self::test::T> f2f = #C3<self::test::T>;
+ () → self::A<self::test::T> f2g = #C5<self::test::T>;
+ () → self::A<self::test::T> f2h = #C5<self::test::T>;
+ () → self::A<self::test::T> f2i = #C5<self::test::T>;
+ () → self::A<core::int> g2a = #C2;
+ () → self::A<core::int> g2b = #C2;
+ () → self::A<core::int> g2c = #C2;
+ () → self::A<self::test::T> h2a = #C1<self::test::T>;
+ () → self::A<self::test::T> h2b = #C1<self::test::T>;
+ () → self::A<self::test::T> h2c = #C1<self::test::T>;
+ self::expect(#C2, g2a);
+ self::expect(g2a, g2b);
+ if(self::inSoundMode) {
+ self::expect(g2a, g2c);
+ }
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method _#F#new#tearOff<X extends core::num>() → self::A<self::_#F#new#tearOff::X>
+ return new self::A::•<self::_#F#new#tearOff::X>();
+static method _#F#fact#tearOff<X extends core::num>() → self::A<self::_#F#fact#tearOff::X>
+ return self::A::fact<self::_#F#fact#tearOff::X>();
+static method _#F#redirect#tearOff<X extends core::num>() → self::A<self::_#F#redirect#tearOff::X>
+ return self::A::_#redirect#tearOff<self::_#F#redirect#tearOff::X>();
+static method _#G#new#tearOff<unrelated Y extends core::Object? = dynamic>() → self::A<core::int>
+ return new self::A::•<core::int>();
+static method _#G#fact#tearOff<unrelated Y extends core::Object? = dynamic>() → self::A<core::int>
+ return self::A::fact<core::int>();
+static method _#G#redirect#tearOff<unrelated Y extends core::Object? = dynamic>() → self::A<core::int>
+ return self::A::_#redirect#tearOff<core::int>();
+static method _#H#new#tearOff<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic>() → self::A<self::_#H#new#tearOff::X%>
+ return new self::A::•<self::_#H#new#tearOff::X%>();
+static method _#H#fact#tearOff<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic>() → self::A<self::_#H#fact#tearOff::X%>
+ return self::A::fact<self::_#H#fact#tearOff::X%>();
+static method _#H#redirect#tearOff<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic>() → self::A<self::_#H#redirect#tearOff::X%>
+ return self::A::_#redirect#tearOff<self::_#H#redirect#tearOff::X%>();
+
+constants {
+ #C1 = static-tearoff self::A::_#new#tearOff
+ #C2 = instantiation self::A::_#new#tearOff <core::int>
+ #C3 = static-tearoff self::A::_#fact#tearOff
+ #C4 = instantiation self::A::_#fact#tearOff <core::int>
+ #C5 = static-tearoff self::A::_#redirect#tearOff
+ #C6 = instantiation self::A::_#redirect#tearOff <core::int>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.strong.transformed.expect
new file mode 100644
index 0000000..bfa45c0
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.strong.transformed.expect
@@ -0,0 +1,118 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F<X extends core::num> = self::A<X>;
+typedef G<unrelated Y extends core::Object? = dynamic> = self::A<core::int>;
+typedef H<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic> = self::A<X%>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::A::redirect]/*isLegacy*/;
+ constructor •() → self::A<self::A::T%>
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#new#tearOff::T%>
+ return new self::A::•<self::A::_#new#tearOff::T%>();
+ static factory fact<T extends core::Object? = dynamic>() → self::A<self::A::fact::T%>
+ return new self::A::•<self::A::fact::T%>();
+ static method _#fact#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#fact#tearOff::T%>
+ return self::A::fact<self::A::_#fact#tearOff::T%>();
+ static factory redirect<T extends core::Object? = dynamic>() → self::A<self::A::redirect::T%>
+ let Never #redirecting_factory = self::A::• in let self::A::redirect::T% #typeArg0 = null in invalid-expression;
+ static method _#redirect#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#redirect#tearOff::T%>
+ return new self::A::•<self::A::_#redirect#tearOff::T%>();
+}
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static const field () → self::A<core::int> f1a = #C2;
+static const field () → self::A<core::int> f1b = #C2;
+static const field () → self::A<core::int> f1c = #C2;
+static const field () → self::A<core::int> f1d = #C4;
+static const field () → self::A<core::int> f1e = #C4;
+static const field () → self::A<core::int> f1f = #C4;
+static const field () → self::A<core::int> f1g = #C6;
+static const field () → self::A<core::int> f1h = #C6;
+static const field () → self::A<core::int> f1i = #C6;
+static const field () → self::A<core::int> g1a = #C2;
+static const field () → self::A<core::int> g1b = #C2;
+static const field () → self::A<core::int> g1c = #C2;
+static const field () → self::A<core::int> h1a = #C2;
+static const field () → self::A<core::int> h1b = #C2;
+static const field () → self::A<core::int> h1c = #C2;
+static method main() → dynamic {
+ self::test<core::int>();
+ core::identical(#C2, #C2);
+ core::identical(#C2, #C2);
+ core::identical(#C4, #C4);
+ core::identical(#C4, #C4);
+ core::identical(#C6, #C6);
+ core::identical(#C6, #C6);
+ core::identical(#C2, #C2);
+ core::identical(#C2, #C2);
+ core::identical(#C2, #C2);
+ core::identical(#C2, #C2);
+}
+static method test<T extends core::num>() → dynamic {
+ () → self::A<self::test::T> f2a = #C1<self::test::T>;
+ () → self::A<self::test::T> f2b = #C1<self::test::T>;
+ () → self::A<self::test::T> f2c = #C1<self::test::T>;
+ () → self::A<self::test::T> f2d = #C3<self::test::T>;
+ () → self::A<self::test::T> f2e = #C3<self::test::T>;
+ () → self::A<self::test::T> f2f = #C3<self::test::T>;
+ () → self::A<self::test::T> f2g = #C5<self::test::T>;
+ () → self::A<self::test::T> f2h = #C5<self::test::T>;
+ () → self::A<self::test::T> f2i = #C5<self::test::T>;
+ () → self::A<core::int> g2a = #C2;
+ () → self::A<core::int> g2b = #C2;
+ () → self::A<core::int> g2c = #C2;
+ () → self::A<self::test::T> h2a = #C1<self::test::T>;
+ () → self::A<self::test::T> h2b = #C1<self::test::T>;
+ () → self::A<self::test::T> h2c = #C1<self::test::T>;
+ self::expect(#C2, g2a);
+ self::expect(g2a, g2b);
+ if(self::inSoundMode) {
+ self::expect(g2a, g2c);
+ }
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method _#F#new#tearOff<X extends core::num>() → self::A<self::_#F#new#tearOff::X>
+ return new self::A::•<self::_#F#new#tearOff::X>();
+static method _#F#fact#tearOff<X extends core::num>() → self::A<self::_#F#fact#tearOff::X>
+ return self::A::fact<self::_#F#fact#tearOff::X>();
+static method _#F#redirect#tearOff<X extends core::num>() → self::A<self::_#F#redirect#tearOff::X>
+ return self::A::_#redirect#tearOff<self::_#F#redirect#tearOff::X>();
+static method _#G#new#tearOff<unrelated Y extends core::Object? = dynamic>() → self::A<core::int>
+ return new self::A::•<core::int>();
+static method _#G#fact#tearOff<unrelated Y extends core::Object? = dynamic>() → self::A<core::int>
+ return self::A::fact<core::int>();
+static method _#G#redirect#tearOff<unrelated Y extends core::Object? = dynamic>() → self::A<core::int>
+ return self::A::_#redirect#tearOff<core::int>();
+static method _#H#new#tearOff<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic>() → self::A<self::_#H#new#tearOff::X%>
+ return new self::A::•<self::_#H#new#tearOff::X%>();
+static method _#H#fact#tearOff<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic>() → self::A<self::_#H#fact#tearOff::X%>
+ return self::A::fact<self::_#H#fact#tearOff::X%>();
+static method _#H#redirect#tearOff<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic>() → self::A<self::_#H#redirect#tearOff::X%>
+ return self::A::_#redirect#tearOff<self::_#H#redirect#tearOff::X%>();
+
+constants {
+ #C1 = static-tearoff self::A::_#new#tearOff
+ #C2 = instantiation self::A::_#new#tearOff <core::int>
+ #C3 = static-tearoff self::A::_#fact#tearOff
+ #C4 = instantiation self::A::_#fact#tearOff <core::int>
+ #C5 = static-tearoff self::A::_#redirect#tearOff
+ #C6 = instantiation self::A::_#redirect#tearOff <core::int>
+}
+
+Extra constant evaluation status:
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:38:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:39:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:41:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:42:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:44:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:45:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:47:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:48:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:50:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:51:3 -> BoolConstant(true)
+Extra constant evaluation: evaluated: 61, effectively constant: 10
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.textual_outline.expect
new file mode 100644
index 0000000..8731bf4
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.textual_outline.expect
@@ -0,0 +1,27 @@
+final bool inSoundMode = <int?>[] is! List<int>;
+class A<T> {
+ A();
+ factory A.fact() => new A<T>();
+ factory A.redirect() = A<T>;
+}
+typedef F<X extends num> = A<X>;
+typedef G<Y> = A<int>;
+typedef H<X, Y> = A<X>;
+const f1a = A<int>.new;
+const f1b = F<int>.new;
+const A<int> Function() f1c = F.new;
+const f1d = A<int>.fact;
+const f1e = F<int>.fact;
+const A<int> Function() f1f = F.fact;
+const f1g = A<int>.redirect;
+const f1h = F<int>.redirect;
+const A<int> Function() f1i = F.redirect;
+const g1a = A<int>.new;
+const g1b = G<String>.new;
+const A<int> Function() g1c = G.new;
+const h1a = A<int>.new;
+const h1b = H<int, String>.new;
+const A<int> Function() h1c = H.new;
+main() {}
+test<T extends num>() {}
+expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.weak.expect
new file mode 100644
index 0000000..8e0844f
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.weak.expect
@@ -0,0 +1,108 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F<X extends core::num> = self::A<X>;
+typedef G<unrelated Y extends core::Object? = dynamic> = self::A<core::int>;
+typedef H<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic> = self::A<X%>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::A::redirect]/*isLegacy*/;
+ constructor •() → self::A<self::A::T%>
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#new#tearOff::T%>
+ return new self::A::•<self::A::_#new#tearOff::T%>();
+ static factory fact<T extends core::Object? = dynamic>() → self::A<self::A::fact::T%>
+ return new self::A::•<self::A::fact::T%>();
+ static method _#fact#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#fact#tearOff::T%>
+ return self::A::fact<self::A::_#fact#tearOff::T%>();
+ static factory redirect<T extends core::Object? = dynamic>() → self::A<self::A::redirect::T%>
+ let dynamic #redirecting_factory = self::A::• in let self::A::redirect::T% #typeArg0 = null in invalid-expression;
+ static method _#redirect#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#redirect#tearOff::T%>
+ return new self::A::•<self::A::_#redirect#tearOff::T%>();
+}
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static const field () → self::A<core::int> f1a = #C2;
+static const field () → self::A<core::int> f1b = #C2;
+static const field () → self::A<core::int> f1c = #C3;
+static const field () → self::A<core::int> f1d = #C5;
+static const field () → self::A<core::int> f1e = #C5;
+static const field () → self::A<core::int> f1f = #C6;
+static const field () → self::A<core::int> f1g = #C8;
+static const field () → self::A<core::int> f1h = #C8;
+static const field () → self::A<core::int> f1i = #C9;
+static const field () → self::A<core::int> g1a = #C2;
+static const field () → self::A<core::int> g1b = #C2;
+static const field () → self::A<core::int> g1c = #C3;
+static const field () → self::A<core::int> h1a = #C2;
+static const field () → self::A<core::int> h1b = #C2;
+static const field () → self::A<core::int> h1c = #C3;
+static method main() → dynamic {
+ self::test<core::int>();
+ core::identical(#C2, #C2);
+ core::identical(#C2, #C3);
+ core::identical(#C5, #C5);
+ core::identical(#C5, #C6);
+ core::identical(#C8, #C8);
+ core::identical(#C8, #C9);
+ core::identical(#C2, #C2);
+ core::identical(#C2, #C3);
+ core::identical(#C2, #C2);
+ core::identical(#C2, #C3);
+}
+static method test<T extends core::num>() → dynamic {
+ () → self::A<self::test::T> f2a = #C1<self::test::T>;
+ () → self::A<self::test::T> f2b = #C1<self::test::T>;
+ () → self::A<self::test::T> f2c = #C1<self::test::T>;
+ () → self::A<self::test::T> f2d = #C4<self::test::T>;
+ () → self::A<self::test::T> f2e = #C4<self::test::T>;
+ () → self::A<self::test::T> f2f = #C4<self::test::T>;
+ () → self::A<self::test::T> f2g = #C7<self::test::T>;
+ () → self::A<self::test::T> f2h = #C7<self::test::T>;
+ () → self::A<self::test::T> f2i = #C7<self::test::T>;
+ () → self::A<core::int> g2a = #C2;
+ () → self::A<core::int> g2b = #C2;
+ () → self::A<core::int> g2c = #C3;
+ () → self::A<self::test::T> h2a = #C1<self::test::T>;
+ () → self::A<self::test::T> h2b = #C1<self::test::T>;
+ () → self::A<self::test::T> h2c = #C1<self::test::T>;
+ self::expect(#C2, g2a);
+ self::expect(g2a, g2b);
+ if(self::inSoundMode) {
+ self::expect(g2a, g2c);
+ }
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method _#F#new#tearOff<X extends core::num>() → self::A<self::_#F#new#tearOff::X>
+ return new self::A::•<self::_#F#new#tearOff::X>();
+static method _#F#fact#tearOff<X extends core::num>() → self::A<self::_#F#fact#tearOff::X>
+ return self::A::fact<self::_#F#fact#tearOff::X>();
+static method _#F#redirect#tearOff<X extends core::num>() → self::A<self::_#F#redirect#tearOff::X>
+ return self::A::_#redirect#tearOff<self::_#F#redirect#tearOff::X>();
+static method _#G#new#tearOff<unrelated Y extends core::Object? = dynamic>() → self::A<core::int>
+ return new self::A::•<core::int>();
+static method _#G#fact#tearOff<unrelated Y extends core::Object? = dynamic>() → self::A<core::int>
+ return self::A::fact<core::int>();
+static method _#G#redirect#tearOff<unrelated Y extends core::Object? = dynamic>() → self::A<core::int>
+ return self::A::_#redirect#tearOff<core::int>();
+static method _#H#new#tearOff<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic>() → self::A<self::_#H#new#tearOff::X%>
+ return new self::A::•<self::_#H#new#tearOff::X%>();
+static method _#H#fact#tearOff<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic>() → self::A<self::_#H#fact#tearOff::X%>
+ return self::A::fact<self::_#H#fact#tearOff::X%>();
+static method _#H#redirect#tearOff<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic>() → self::A<self::_#H#redirect#tearOff::X%>
+ return self::A::_#redirect#tearOff<self::_#H#redirect#tearOff::X%>();
+
+constants {
+ #C1 = static-tearoff self::A::_#new#tearOff
+ #C2 = instantiation self::A::_#new#tearOff <core::int*>
+ #C3 = instantiation self::A::_#new#tearOff <core::int>
+ #C4 = static-tearoff self::A::_#fact#tearOff
+ #C5 = instantiation self::A::_#fact#tearOff <core::int*>
+ #C6 = instantiation self::A::_#fact#tearOff <core::int>
+ #C7 = static-tearoff self::A::_#redirect#tearOff
+ #C8 = instantiation self::A::_#redirect#tearOff <core::int*>
+ #C9 = instantiation self::A::_#redirect#tearOff <core::int>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.weak.outline.expect
new file mode 100644
index 0000000..e433d37
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.weak.outline.expect
@@ -0,0 +1,81 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F<X extends core::num> = self::A<X>;
+typedef G<unrelated Y extends core::Object? = dynamic> = self::A<core::int>;
+typedef H<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic> = self::A<X%>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::A::redirect]/*isLegacy*/;
+ constructor •() → self::A<self::A::T%>
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#new#tearOff::T%>
+ return new self::A::•<self::A::_#new#tearOff::T%>();
+ static factory fact<T extends core::Object? = dynamic>() → self::A<self::A::fact::T%>
+ ;
+ static method _#fact#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#fact#tearOff::T%>
+ return self::A::fact<self::A::_#fact#tearOff::T%>();
+ static factory redirect<T extends core::Object? = dynamic>() → self::A<self::A::redirect::T%>
+ let dynamic #redirecting_factory = self::A::• in let self::A::redirect::T% #typeArg0 = null in invalid-expression;
+ static method _#redirect#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#redirect#tearOff::T%>
+ return new self::A::•<self::A::_#redirect#tearOff::T%>();
+}
+static final field core::bool inSoundMode;
+static const field () → self::A<core::int> f1a = self::A::_#new#tearOff<core::int>;
+static const field () → self::A<core::int> f1b = self::A::_#new#tearOff<core::int>;
+static const field () → self::A<core::int> f1c = self::_#F#new#tearOff<core::int>;
+static const field () → self::A<core::int> f1d = self::A::_#fact#tearOff<core::int>;
+static const field () → self::A<core::int> f1e = self::A::_#fact#tearOff<core::int>;
+static const field () → self::A<core::int> f1f = self::_#F#fact#tearOff<core::int>;
+static const field () → self::A<core::int> f1g = self::A::_#redirect#tearOff<core::int>;
+static const field () → self::A<core::int> f1h = self::A::_#redirect#tearOff<core::int>;
+static const field () → self::A<core::int> f1i = self::_#F#redirect#tearOff<core::int>;
+static const field () → self::A<core::int> g1a = self::A::_#new#tearOff<core::int>;
+static const field () → self::A<core::int> g1b = self::A::_#new#tearOff<core::int>;
+static const field () → self::A<core::int> g1c = self::_#G#new#tearOff<dynamic>;
+static const field () → self::A<core::int> h1a = self::A::_#new#tearOff<core::int>;
+static const field () → self::A<core::int> h1b = self::A::_#new#tearOff<core::int>;
+static const field () → self::A<core::int> h1c = self::_#H#new#tearOff<core::int, dynamic>;
+static method main() → dynamic
+ ;
+static method test<T extends core::num>() → dynamic
+ ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+ ;
+static method _#F#new#tearOff<X extends core::num>() → self::A<self::_#F#new#tearOff::X>
+ return new self::A::•<self::_#F#new#tearOff::X>();
+static method _#F#fact#tearOff<X extends core::num>() → self::A<self::_#F#fact#tearOff::X>
+ return self::A::fact<self::_#F#fact#tearOff::X>();
+static method _#F#redirect#tearOff<X extends core::num>() → self::A<self::_#F#redirect#tearOff::X>
+ return self::A::_#redirect#tearOff<self::_#F#redirect#tearOff::X>();
+static method _#G#new#tearOff<unrelated Y extends core::Object? = dynamic>() → self::A<core::int>
+ return new self::A::•<core::int>();
+static method _#G#fact#tearOff<unrelated Y extends core::Object? = dynamic>() → self::A<core::int>
+ return self::A::fact<core::int>();
+static method _#G#redirect#tearOff<unrelated Y extends core::Object? = dynamic>() → self::A<core::int>
+ return self::A::_#redirect#tearOff<core::int>();
+static method _#H#new#tearOff<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic>() → self::A<self::_#H#new#tearOff::X%>
+ return new self::A::•<self::_#H#new#tearOff::X%>();
+static method _#H#fact#tearOff<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic>() → self::A<self::_#H#fact#tearOff::X%>
+ return self::A::fact<self::_#H#fact#tearOff::X%>();
+static method _#H#redirect#tearOff<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic>() → self::A<self::_#H#redirect#tearOff::X%>
+ return self::A::_#redirect#tearOff<self::_#H#redirect#tearOff::X%>();
+
+
+Extra constant evaluation status:
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:17:13 -> InstantiationConstant(A._#new#tearOff<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:18:13 -> InstantiationConstant(A._#new#tearOff<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:19:31 -> InstantiationConstant(A._#new#tearOff<int>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:20:13 -> InstantiationConstant(A._#fact#tearOff<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:21:13 -> InstantiationConstant(A._#fact#tearOff<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:22:31 -> InstantiationConstant(A._#fact#tearOff<int>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:23:13 -> InstantiationConstant(A._#redirect#tearOff<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:24:13 -> InstantiationConstant(A._#redirect#tearOff<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:25:31 -> InstantiationConstant(A._#redirect#tearOff<int>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:27:13 -> InstantiationConstant(A._#new#tearOff<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:28:13 -> InstantiationConstant(A._#new#tearOff<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:29:31 -> InstantiationConstant(A._#new#tearOff<int>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:31:13 -> InstantiationConstant(A._#new#tearOff<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:32:13 -> InstantiationConstant(A._#new#tearOff<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:33:31 -> InstantiationConstant(A._#new#tearOff<int>)
+Extra constant evaluation: evaluated: 32, effectively constant: 15
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.weak.transformed.expect
new file mode 100644
index 0000000..0b3ac45
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_non_proper_rename.dart.weak.transformed.expect
@@ -0,0 +1,121 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F<X extends core::num> = self::A<X>;
+typedef G<unrelated Y extends core::Object? = dynamic> = self::A<core::int>;
+typedef H<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic> = self::A<X%>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::A::redirect]/*isLegacy*/;
+ constructor •() → self::A<self::A::T%>
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#new#tearOff::T%>
+ return new self::A::•<self::A::_#new#tearOff::T%>();
+ static factory fact<T extends core::Object? = dynamic>() → self::A<self::A::fact::T%>
+ return new self::A::•<self::A::fact::T%>();
+ static method _#fact#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#fact#tearOff::T%>
+ return self::A::fact<self::A::_#fact#tearOff::T%>();
+ static factory redirect<T extends core::Object? = dynamic>() → self::A<self::A::redirect::T%>
+ let Never #redirecting_factory = self::A::• in let self::A::redirect::T% #typeArg0 = null in invalid-expression;
+ static method _#redirect#tearOff<T extends core::Object? = dynamic>() → self::A<self::A::_#redirect#tearOff::T%>
+ return new self::A::•<self::A::_#redirect#tearOff::T%>();
+}
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static const field () → self::A<core::int> f1a = #C2;
+static const field () → self::A<core::int> f1b = #C2;
+static const field () → self::A<core::int> f1c = #C3;
+static const field () → self::A<core::int> f1d = #C5;
+static const field () → self::A<core::int> f1e = #C5;
+static const field () → self::A<core::int> f1f = #C6;
+static const field () → self::A<core::int> f1g = #C8;
+static const field () → self::A<core::int> f1h = #C8;
+static const field () → self::A<core::int> f1i = #C9;
+static const field () → self::A<core::int> g1a = #C2;
+static const field () → self::A<core::int> g1b = #C2;
+static const field () → self::A<core::int> g1c = #C3;
+static const field () → self::A<core::int> h1a = #C2;
+static const field () → self::A<core::int> h1b = #C2;
+static const field () → self::A<core::int> h1c = #C3;
+static method main() → dynamic {
+ self::test<core::int>();
+ core::identical(#C2, #C2);
+ core::identical(#C2, #C3);
+ core::identical(#C5, #C5);
+ core::identical(#C5, #C6);
+ core::identical(#C8, #C8);
+ core::identical(#C8, #C9);
+ core::identical(#C2, #C2);
+ core::identical(#C2, #C3);
+ core::identical(#C2, #C2);
+ core::identical(#C2, #C3);
+}
+static method test<T extends core::num>() → dynamic {
+ () → self::A<self::test::T> f2a = #C1<self::test::T>;
+ () → self::A<self::test::T> f2b = #C1<self::test::T>;
+ () → self::A<self::test::T> f2c = #C1<self::test::T>;
+ () → self::A<self::test::T> f2d = #C4<self::test::T>;
+ () → self::A<self::test::T> f2e = #C4<self::test::T>;
+ () → self::A<self::test::T> f2f = #C4<self::test::T>;
+ () → self::A<self::test::T> f2g = #C7<self::test::T>;
+ () → self::A<self::test::T> f2h = #C7<self::test::T>;
+ () → self::A<self::test::T> f2i = #C7<self::test::T>;
+ () → self::A<core::int> g2a = #C2;
+ () → self::A<core::int> g2b = #C2;
+ () → self::A<core::int> g2c = #C3;
+ () → self::A<self::test::T> h2a = #C1<self::test::T>;
+ () → self::A<self::test::T> h2b = #C1<self::test::T>;
+ () → self::A<self::test::T> h2c = #C1<self::test::T>;
+ self::expect(#C2, g2a);
+ self::expect(g2a, g2b);
+ if(self::inSoundMode) {
+ self::expect(g2a, g2c);
+ }
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method _#F#new#tearOff<X extends core::num>() → self::A<self::_#F#new#tearOff::X>
+ return new self::A::•<self::_#F#new#tearOff::X>();
+static method _#F#fact#tearOff<X extends core::num>() → self::A<self::_#F#fact#tearOff::X>
+ return self::A::fact<self::_#F#fact#tearOff::X>();
+static method _#F#redirect#tearOff<X extends core::num>() → self::A<self::_#F#redirect#tearOff::X>
+ return self::A::_#redirect#tearOff<self::_#F#redirect#tearOff::X>();
+static method _#G#new#tearOff<unrelated Y extends core::Object? = dynamic>() → self::A<core::int>
+ return new self::A::•<core::int>();
+static method _#G#fact#tearOff<unrelated Y extends core::Object? = dynamic>() → self::A<core::int>
+ return self::A::fact<core::int>();
+static method _#G#redirect#tearOff<unrelated Y extends core::Object? = dynamic>() → self::A<core::int>
+ return self::A::_#redirect#tearOff<core::int>();
+static method _#H#new#tearOff<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic>() → self::A<self::_#H#new#tearOff::X%>
+ return new self::A::•<self::_#H#new#tearOff::X%>();
+static method _#H#fact#tearOff<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic>() → self::A<self::_#H#fact#tearOff::X%>
+ return self::A::fact<self::_#H#fact#tearOff::X%>();
+static method _#H#redirect#tearOff<X extends core::Object? = dynamic, unrelated Y extends core::Object? = dynamic>() → self::A<self::_#H#redirect#tearOff::X%>
+ return self::A::_#redirect#tearOff<self::_#H#redirect#tearOff::X%>();
+
+constants {
+ #C1 = static-tearoff self::A::_#new#tearOff
+ #C2 = instantiation self::A::_#new#tearOff <core::int*>
+ #C3 = instantiation self::A::_#new#tearOff <core::int>
+ #C4 = static-tearoff self::A::_#fact#tearOff
+ #C5 = instantiation self::A::_#fact#tearOff <core::int*>
+ #C6 = instantiation self::A::_#fact#tearOff <core::int>
+ #C7 = static-tearoff self::A::_#redirect#tearOff
+ #C8 = instantiation self::A::_#redirect#tearOff <core::int*>
+ #C9 = instantiation self::A::_#redirect#tearOff <core::int>
+}
+
+Extra constant evaluation status:
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:38:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:39:3 -> BoolConstant(false)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:41:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:42:3 -> BoolConstant(false)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:44:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:45:3 -> BoolConstant(false)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:47:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:48:3 -> BoolConstant(false)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:50:3 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///inferred_non_proper_rename.dart:51:3 -> BoolConstant(false)
+Extra constant evaluation: evaluated: 61, effectively constant: 10
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart
new file mode 100644
index 0000000..e923b7a
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart
@@ -0,0 +1,33 @@
+// 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.
+
+var A_new = A.new;
+var B_new = B.new;
+var F_new = F.new;
+var G_new = G.new;
+
+class A {
+ int field1 = 0;
+
+ A(this.field1);
+ A.named(this.field1);
+}
+
+class B<T> implements A {
+ var field1;
+ T field2;
+
+ B(this.field1, this.field2);
+ B.named(this.field1, this.field2);
+}
+
+typedef F<T> = A;
+typedef G<T extends num> = B;
+
+var A_named = A.named;
+var B_named = B<int>.named;
+var F_named = F.named;
+var G_named = G<int>.named;
+
+main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.strong.expect
new file mode 100644
index 0000000..d952a09
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.strong.expect
@@ -0,0 +1,62 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F<unrelated T extends core::Object? = dynamic> = self::A;
+typedef G<unrelated T extends core::num> = self::B<dynamic>;
+class A extends core::Object {
+ field core::int field1 = 0;
+ constructor •(core::int field1) → self::A
+ : self::A::field1 = field1, super core::Object::•()
+ ;
+ constructor named(core::int field1) → self::A
+ : self::A::field1 = field1, super core::Object::•()
+ ;
+ static method _#new#tearOff(core::int field1) → self::A
+ return new self::A::•(field1);
+ static method _#named#tearOff(core::int field1) → self::A
+ return new self::A::named(field1);
+}
+class B<T extends core::Object? = dynamic> extends core::Object implements self::A {
+ field core::int field1;
+ generic-covariant-impl field self::B::T% field2;
+ constructor •(core::int field1, self::B::T% field2) → self::B<self::B::T%>
+ : self::B::field1 = field1, self::B::field2 = field2, super core::Object::•()
+ ;
+ constructor named(core::int field1, self::B::T% field2) → self::B<self::B::T%>
+ : self::B::field1 = field1, self::B::field2 = field2, super core::Object::•()
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>(core::int field1, self::B::_#new#tearOff::T% field2) → self::B<self::B::_#new#tearOff::T%>
+ return new self::B::•<self::B::_#new#tearOff::T%>(field1, field2);
+ static method _#named#tearOff<T extends core::Object? = dynamic>(core::int field1, self::B::_#named#tearOff::T% field2) → self::B<self::B::_#named#tearOff::T%>
+ return new self::B::named<self::B::_#named#tearOff::T%>(field1, field2);
+}
+static field (core::int) → self::A A_new = #C1;
+static field <T extends core::Object? = dynamic>(core::int, T%) → self::B<T%> B_new = #C2;
+static field <unrelated T extends core::Object? = dynamic>(core::int) → self::A F_new = #C3;
+static field <unrelated T extends core::num>(core::int, dynamic) → self::B<dynamic> G_new = #C4;
+static field (core::int) → self::A A_named = #C5;
+static field (core::int, core::int) → self::B<core::int> B_named = #C7;
+static field <unrelated T extends core::Object? = dynamic>(core::int) → self::A F_named = #C8;
+static field (core::int, dynamic) → self::B<dynamic> G_named = #C9;
+static method main() → dynamic {}
+static method _#F#new#tearOff<unrelated T extends core::Object? = dynamic>(core::int field1) → self::A
+ return new self::A::•(field1);
+static method _#F#named#tearOff<unrelated T extends core::Object? = dynamic>(core::int field1) → self::A
+ return new self::A::named(field1);
+static method _#G#new#tearOff<unrelated T extends core::num>(core::int field1, dynamic field2) → self::B<dynamic>
+ return new self::B::•<dynamic>(field1, field2);
+static method _#G#named#tearOff<unrelated T extends core::num>(core::int field1, dynamic field2) → self::B<dynamic>
+ return new self::B::named<dynamic>(field1, field2);
+
+constants {
+ #C1 = static-tearoff self::A::_#new#tearOff
+ #C2 = static-tearoff self::B::_#new#tearOff
+ #C3 = static-tearoff self::_#F#new#tearOff
+ #C4 = static-tearoff self::_#G#new#tearOff
+ #C5 = static-tearoff self::A::_#named#tearOff
+ #C6 = static-tearoff self::B::_#named#tearOff
+ #C7 = instantiation self::B::_#named#tearOff <core::int>
+ #C8 = static-tearoff self::_#F#named#tearOff
+ #C9 = instantiation self::B::_#named#tearOff <dynamic>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.strong.transformed.expect
new file mode 100644
index 0000000..d952a09
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.strong.transformed.expect
@@ -0,0 +1,62 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F<unrelated T extends core::Object? = dynamic> = self::A;
+typedef G<unrelated T extends core::num> = self::B<dynamic>;
+class A extends core::Object {
+ field core::int field1 = 0;
+ constructor •(core::int field1) → self::A
+ : self::A::field1 = field1, super core::Object::•()
+ ;
+ constructor named(core::int field1) → self::A
+ : self::A::field1 = field1, super core::Object::•()
+ ;
+ static method _#new#tearOff(core::int field1) → self::A
+ return new self::A::•(field1);
+ static method _#named#tearOff(core::int field1) → self::A
+ return new self::A::named(field1);
+}
+class B<T extends core::Object? = dynamic> extends core::Object implements self::A {
+ field core::int field1;
+ generic-covariant-impl field self::B::T% field2;
+ constructor •(core::int field1, self::B::T% field2) → self::B<self::B::T%>
+ : self::B::field1 = field1, self::B::field2 = field2, super core::Object::•()
+ ;
+ constructor named(core::int field1, self::B::T% field2) → self::B<self::B::T%>
+ : self::B::field1 = field1, self::B::field2 = field2, super core::Object::•()
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>(core::int field1, self::B::_#new#tearOff::T% field2) → self::B<self::B::_#new#tearOff::T%>
+ return new self::B::•<self::B::_#new#tearOff::T%>(field1, field2);
+ static method _#named#tearOff<T extends core::Object? = dynamic>(core::int field1, self::B::_#named#tearOff::T% field2) → self::B<self::B::_#named#tearOff::T%>
+ return new self::B::named<self::B::_#named#tearOff::T%>(field1, field2);
+}
+static field (core::int) → self::A A_new = #C1;
+static field <T extends core::Object? = dynamic>(core::int, T%) → self::B<T%> B_new = #C2;
+static field <unrelated T extends core::Object? = dynamic>(core::int) → self::A F_new = #C3;
+static field <unrelated T extends core::num>(core::int, dynamic) → self::B<dynamic> G_new = #C4;
+static field (core::int) → self::A A_named = #C5;
+static field (core::int, core::int) → self::B<core::int> B_named = #C7;
+static field <unrelated T extends core::Object? = dynamic>(core::int) → self::A F_named = #C8;
+static field (core::int, dynamic) → self::B<dynamic> G_named = #C9;
+static method main() → dynamic {}
+static method _#F#new#tearOff<unrelated T extends core::Object? = dynamic>(core::int field1) → self::A
+ return new self::A::•(field1);
+static method _#F#named#tearOff<unrelated T extends core::Object? = dynamic>(core::int field1) → self::A
+ return new self::A::named(field1);
+static method _#G#new#tearOff<unrelated T extends core::num>(core::int field1, dynamic field2) → self::B<dynamic>
+ return new self::B::•<dynamic>(field1, field2);
+static method _#G#named#tearOff<unrelated T extends core::num>(core::int field1, dynamic field2) → self::B<dynamic>
+ return new self::B::named<dynamic>(field1, field2);
+
+constants {
+ #C1 = static-tearoff self::A::_#new#tearOff
+ #C2 = static-tearoff self::B::_#new#tearOff
+ #C3 = static-tearoff self::_#F#new#tearOff
+ #C4 = static-tearoff self::_#G#new#tearOff
+ #C5 = static-tearoff self::A::_#named#tearOff
+ #C6 = static-tearoff self::B::_#named#tearOff
+ #C7 = instantiation self::B::_#named#tearOff <core::int>
+ #C8 = static-tearoff self::_#F#named#tearOff
+ #C9 = instantiation self::B::_#named#tearOff <dynamic>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.textual_outline.expect
new file mode 100644
index 0000000..12bef00
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.textual_outline.expect
@@ -0,0 +1,22 @@
+var A_new = A.new;
+var B_new = B.new;
+var F_new = F.new;
+var G_new = G.new;
+class A {
+ int field1 = 0;
+ A(this.field1);
+ A.named(this.field1);
+}
+class B<T> implements A {
+ var field1;
+ T field2;
+ B(this.field1, this.field2);
+ B.named(this.field1, this.field2);
+}
+typedef F<T> = A;
+typedef G<T extends num> = B;
+var A_named = A.named;
+var B_named = B<int>.named;
+var F_named = F.named;
+var G_named = G<int>.named;
+main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.weak.expect
new file mode 100644
index 0000000..9294ac3
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.weak.expect
@@ -0,0 +1,62 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F<unrelated T extends core::Object? = dynamic> = self::A;
+typedef G<unrelated T extends core::num> = self::B<dynamic>;
+class A extends core::Object {
+ field core::int field1 = 0;
+ constructor •(core::int field1) → self::A
+ : self::A::field1 = field1, super core::Object::•()
+ ;
+ constructor named(core::int field1) → self::A
+ : self::A::field1 = field1, super core::Object::•()
+ ;
+ static method _#new#tearOff(core::int field1) → self::A
+ return new self::A::•(field1);
+ static method _#named#tearOff(core::int field1) → self::A
+ return new self::A::named(field1);
+}
+class B<T extends core::Object? = dynamic> extends core::Object implements self::A {
+ field core::int field1;
+ generic-covariant-impl field self::B::T% field2;
+ constructor •(core::int field1, self::B::T% field2) → self::B<self::B::T%>
+ : self::B::field1 = field1, self::B::field2 = field2, super core::Object::•()
+ ;
+ constructor named(core::int field1, self::B::T% field2) → self::B<self::B::T%>
+ : self::B::field1 = field1, self::B::field2 = field2, super core::Object::•()
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>(core::int field1, self::B::_#new#tearOff::T% field2) → self::B<self::B::_#new#tearOff::T%>
+ return new self::B::•<self::B::_#new#tearOff::T%>(field1, field2);
+ static method _#named#tearOff<T extends core::Object? = dynamic>(core::int field1, self::B::_#named#tearOff::T% field2) → self::B<self::B::_#named#tearOff::T%>
+ return new self::B::named<self::B::_#named#tearOff::T%>(field1, field2);
+}
+static field (core::int) → self::A A_new = #C1;
+static field <T extends core::Object? = dynamic>(core::int, T%) → self::B<T%> B_new = #C2;
+static field <unrelated T extends core::Object? = dynamic>(core::int) → self::A F_new = #C3;
+static field <unrelated T extends core::num>(core::int, dynamic) → self::B<dynamic> G_new = #C4;
+static field (core::int) → self::A A_named = #C5;
+static field (core::int, core::int) → self::B<core::int> B_named = #C7;
+static field <unrelated T extends core::Object? = dynamic>(core::int) → self::A F_named = #C8;
+static field (core::int, dynamic) → self::B<dynamic> G_named = #C9;
+static method main() → dynamic {}
+static method _#F#new#tearOff<unrelated T extends core::Object? = dynamic>(core::int field1) → self::A
+ return new self::A::•(field1);
+static method _#F#named#tearOff<unrelated T extends core::Object? = dynamic>(core::int field1) → self::A
+ return new self::A::named(field1);
+static method _#G#new#tearOff<unrelated T extends core::num>(core::int field1, dynamic field2) → self::B<dynamic>
+ return new self::B::•<dynamic>(field1, field2);
+static method _#G#named#tearOff<unrelated T extends core::num>(core::int field1, dynamic field2) → self::B<dynamic>
+ return new self::B::named<dynamic>(field1, field2);
+
+constants {
+ #C1 = static-tearoff self::A::_#new#tearOff
+ #C2 = static-tearoff self::B::_#new#tearOff
+ #C3 = static-tearoff self::_#F#new#tearOff
+ #C4 = static-tearoff self::_#G#new#tearOff
+ #C5 = static-tearoff self::A::_#named#tearOff
+ #C6 = static-tearoff self::B::_#named#tearOff
+ #C7 = instantiation self::B::_#named#tearOff <core::int*>
+ #C8 = static-tearoff self::_#F#named#tearOff
+ #C9 = instantiation self::B::_#named#tearOff <dynamic>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.weak.outline.expect
new file mode 100644
index 0000000..c32ee60
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.weak.outline.expect
@@ -0,0 +1,47 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F<unrelated T extends core::Object? = dynamic> = self::A;
+typedef G<unrelated T extends core::num> = self::B<dynamic>;
+class A extends core::Object {
+ field core::int field1;
+ constructor •(core::int field1) → self::A
+ ;
+ constructor named(core::int field1) → self::A
+ ;
+ static method _#new#tearOff(core::int field1) → self::A
+ return new self::A::•(field1);
+ static method _#named#tearOff(core::int field1) → self::A
+ return new self::A::named(field1);
+}
+class B<T extends core::Object? = dynamic> extends core::Object implements self::A {
+ field core::int field1;
+ generic-covariant-impl field self::B::T% field2;
+ constructor •(core::int field1, self::B::T% field2) → self::B<self::B::T%>
+ ;
+ constructor named(core::int field1, self::B::T% field2) → self::B<self::B::T%>
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>(core::int field1, self::B::_#new#tearOff::T% field2) → self::B<self::B::_#new#tearOff::T%>
+ return new self::B::•<self::B::_#new#tearOff::T%>(field1, field2);
+ static method _#named#tearOff<T extends core::Object? = dynamic>(core::int field1, self::B::_#named#tearOff::T% field2) → self::B<self::B::_#named#tearOff::T%>
+ return new self::B::named<self::B::_#named#tearOff::T%>(field1, field2);
+}
+static field (core::int) → self::A A_new;
+static field <T extends core::Object? = dynamic>(core::int, T%) → self::B<T%> B_new;
+static field <unrelated T extends core::Object? = dynamic>(core::int) → self::A F_new;
+static field <unrelated T extends core::num>(core::int, dynamic) → self::B<dynamic> G_new;
+static field (core::int) → self::A A_named;
+static field (core::int, core::int) → self::B<core::int> B_named;
+static field <unrelated T extends core::Object? = dynamic>(core::int) → self::A F_named;
+static field (core::int, dynamic) → self::B<dynamic> G_named;
+static method main() → dynamic
+ ;
+static method _#F#new#tearOff<unrelated T extends core::Object? = dynamic>(core::int field1) → self::A
+ return new self::A::•(field1);
+static method _#F#named#tearOff<unrelated T extends core::Object? = dynamic>(core::int field1) → self::A
+ return new self::A::named(field1);
+static method _#G#new#tearOff<unrelated T extends core::num>(core::int field1, dynamic field2) → self::B<dynamic>
+ return new self::B::•<dynamic>(field1, field2);
+static method _#G#named#tearOff<unrelated T extends core::num>(core::int field1, dynamic field2) → self::B<dynamic>
+ return new self::B::named<dynamic>(field1, field2);
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.weak.transformed.expect
new file mode 100644
index 0000000..9294ac3
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/inferred_tear_off.dart.weak.transformed.expect
@@ -0,0 +1,62 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F<unrelated T extends core::Object? = dynamic> = self::A;
+typedef G<unrelated T extends core::num> = self::B<dynamic>;
+class A extends core::Object {
+ field core::int field1 = 0;
+ constructor •(core::int field1) → self::A
+ : self::A::field1 = field1, super core::Object::•()
+ ;
+ constructor named(core::int field1) → self::A
+ : self::A::field1 = field1, super core::Object::•()
+ ;
+ static method _#new#tearOff(core::int field1) → self::A
+ return new self::A::•(field1);
+ static method _#named#tearOff(core::int field1) → self::A
+ return new self::A::named(field1);
+}
+class B<T extends core::Object? = dynamic> extends core::Object implements self::A {
+ field core::int field1;
+ generic-covariant-impl field self::B::T% field2;
+ constructor •(core::int field1, self::B::T% field2) → self::B<self::B::T%>
+ : self::B::field1 = field1, self::B::field2 = field2, super core::Object::•()
+ ;
+ constructor named(core::int field1, self::B::T% field2) → self::B<self::B::T%>
+ : self::B::field1 = field1, self::B::field2 = field2, super core::Object::•()
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>(core::int field1, self::B::_#new#tearOff::T% field2) → self::B<self::B::_#new#tearOff::T%>
+ return new self::B::•<self::B::_#new#tearOff::T%>(field1, field2);
+ static method _#named#tearOff<T extends core::Object? = dynamic>(core::int field1, self::B::_#named#tearOff::T% field2) → self::B<self::B::_#named#tearOff::T%>
+ return new self::B::named<self::B::_#named#tearOff::T%>(field1, field2);
+}
+static field (core::int) → self::A A_new = #C1;
+static field <T extends core::Object? = dynamic>(core::int, T%) → self::B<T%> B_new = #C2;
+static field <unrelated T extends core::Object? = dynamic>(core::int) → self::A F_new = #C3;
+static field <unrelated T extends core::num>(core::int, dynamic) → self::B<dynamic> G_new = #C4;
+static field (core::int) → self::A A_named = #C5;
+static field (core::int, core::int) → self::B<core::int> B_named = #C7;
+static field <unrelated T extends core::Object? = dynamic>(core::int) → self::A F_named = #C8;
+static field (core::int, dynamic) → self::B<dynamic> G_named = #C9;
+static method main() → dynamic {}
+static method _#F#new#tearOff<unrelated T extends core::Object? = dynamic>(core::int field1) → self::A
+ return new self::A::•(field1);
+static method _#F#named#tearOff<unrelated T extends core::Object? = dynamic>(core::int field1) → self::A
+ return new self::A::named(field1);
+static method _#G#new#tearOff<unrelated T extends core::num>(core::int field1, dynamic field2) → self::B<dynamic>
+ return new self::B::•<dynamic>(field1, field2);
+static method _#G#named#tearOff<unrelated T extends core::num>(core::int field1, dynamic field2) → self::B<dynamic>
+ return new self::B::named<dynamic>(field1, field2);
+
+constants {
+ #C1 = static-tearoff self::A::_#new#tearOff
+ #C2 = static-tearoff self::B::_#new#tearOff
+ #C3 = static-tearoff self::_#F#new#tearOff
+ #C4 = static-tearoff self::_#G#new#tearOff
+ #C5 = static-tearoff self::A::_#named#tearOff
+ #C6 = static-tearoff self::B::_#named#tearOff
+ #C7 = instantiation self::B::_#named#tearOff <core::int*>
+ #C8 = static-tearoff self::_#F#named#tearOff
+ #C9 = instantiation self::B::_#named#tearOff <dynamic>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart
new file mode 100644
index 0000000..ed7af3d1
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart
@@ -0,0 +1,14 @@
+// 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 Class {
+ Class._();
+ static Class constructor() => new Class._();
+ static Class Function() field = () => new Class._();
+
+ factory Class.a() = Class.nonexisting;
+ factory Class.b() = Class.constructor;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart.strong.expect
new file mode 100644
index 0000000..d55e231
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart.strong.expect
@@ -0,0 +1,33 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart:10:23: Error: Redirection constructor target not found: 'Class.nonexisting'
+// factory Class.a() = Class.nonexisting;
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart:11:23: Error: Redirection constructor target not found: 'Class.constructor'
+// factory Class.b() = Class.constructor;
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ static field () → self::Class field = () → self::Class => new self::Class::_();
+ static final field dynamic _redirecting# = <dynamic>[self::Class::a, self::Class::b]/*isLegacy*/;
+ constructor _() → self::Class
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff() → self::Class
+ return new self::Class::_();
+ static method constructor() → self::Class
+ return new self::Class::_();
+ static factory a() → self::Class
+ let dynamic #redirecting_factory = "Class.nonexisting" in invalid-expression;
+ static method _#a#tearOff() → self::Class;
+ static factory b() → self::Class
+ let dynamic #redirecting_factory = "Class.constructor" in invalid-expression;
+ static method _#b#tearOff() → self::Class;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart.strong.transformed.expect
new file mode 100644
index 0000000..fe5e039
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart.strong.transformed.expect
@@ -0,0 +1,33 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart:10:23: Error: Redirection constructor target not found: 'Class.nonexisting'
+// factory Class.a() = Class.nonexisting;
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart:11:23: Error: Redirection constructor target not found: 'Class.constructor'
+// factory Class.b() = Class.constructor;
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ static field () → self::Class field = () → self::Class => new self::Class::_();
+ static final field dynamic _redirecting# = <dynamic>[self::Class::a, self::Class::b]/*isLegacy*/;
+ constructor _() → self::Class
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff() → self::Class
+ return new self::Class::_();
+ static method constructor() → self::Class
+ return new self::Class::_();
+ static factory a() → self::Class
+ let core::String* #redirecting_factory = "Class.nonexisting" in invalid-expression;
+ static method _#a#tearOff() → self::Class;
+ static factory b() → self::Class
+ let core::String* #redirecting_factory = "Class.constructor" in invalid-expression;
+ static method _#b#tearOff() → self::Class;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart.textual_outline.expect
new file mode 100644
index 0000000..1dc9515
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart.textual_outline.expect
@@ -0,0 +1,9 @@
+class Class {
+ Class._();
+ static Class constructor() => new Class._();
+ static Class Function() field = () => new Class._();
+ factory Class.a() = Class.nonexisting;
+ factory Class.b() = Class.constructor;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..f765ff19
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart.textual_outline_modelled.expect
@@ -0,0 +1,9 @@
+class Class {
+ Class._();
+ factory Class.a() = Class.nonexisting;
+ factory Class.b() = Class.constructor;
+ static Class Function() field = () => new Class._();
+ static Class constructor() => new Class._();
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart.weak.expect
new file mode 100644
index 0000000..d55e231
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart.weak.expect
@@ -0,0 +1,33 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart:10:23: Error: Redirection constructor target not found: 'Class.nonexisting'
+// factory Class.a() = Class.nonexisting;
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart:11:23: Error: Redirection constructor target not found: 'Class.constructor'
+// factory Class.b() = Class.constructor;
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ static field () → self::Class field = () → self::Class => new self::Class::_();
+ static final field dynamic _redirecting# = <dynamic>[self::Class::a, self::Class::b]/*isLegacy*/;
+ constructor _() → self::Class
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff() → self::Class
+ return new self::Class::_();
+ static method constructor() → self::Class
+ return new self::Class::_();
+ static factory a() → self::Class
+ let dynamic #redirecting_factory = "Class.nonexisting" in invalid-expression;
+ static method _#a#tearOff() → self::Class;
+ static factory b() → self::Class
+ let dynamic #redirecting_factory = "Class.constructor" in invalid-expression;
+ static method _#b#tearOff() → self::Class;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart.weak.outline.expect
new file mode 100644
index 0000000..7a6886a
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart.weak.outline.expect
@@ -0,0 +1,33 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart:10:23: Error: Redirection constructor target not found: 'Class.nonexisting'
+// factory Class.a() = Class.nonexisting;
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart:11:23: Error: Redirection constructor target not found: 'Class.constructor'
+// factory Class.b() = Class.constructor;
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ static field () → self::Class field;
+ static final field dynamic _redirecting# = <dynamic>[self::Class::a, self::Class::b]/*isLegacy*/;
+ constructor _() → self::Class
+ ;
+ static method _#_#tearOff() → self::Class
+ return new self::Class::_();
+ static method constructor() → self::Class
+ ;
+ static factory a() → self::Class
+ let dynamic #redirecting_factory = "Class.nonexisting" in invalid-expression;
+ static method _#a#tearOff() → self::Class;
+ static factory b() → self::Class
+ let dynamic #redirecting_factory = "Class.constructor" in invalid-expression;
+ static method _#b#tearOff() → self::Class;
+}
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart.weak.transformed.expect
new file mode 100644
index 0000000..fe5e039
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart.weak.transformed.expect
@@ -0,0 +1,33 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart:10:23: Error: Redirection constructor target not found: 'Class.nonexisting'
+// factory Class.a() = Class.nonexisting;
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/missing_redirecting_target.dart:11:23: Error: Redirection constructor target not found: 'Class.constructor'
+// factory Class.b() = Class.constructor;
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ static field () → self::Class field = () → self::Class => new self::Class::_();
+ static final field dynamic _redirecting# = <dynamic>[self::Class::a, self::Class::b]/*isLegacy*/;
+ constructor _() → self::Class
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff() → self::Class
+ return new self::Class::_();
+ static method constructor() → self::Class
+ return new self::Class::_();
+ static factory a() → self::Class
+ let core::String* #redirecting_factory = "Class.nonexisting" in invalid-expression;
+ static method _#a#tearOff() → self::Class;
+ static factory b() → self::Class
+ let core::String* #redirecting_factory = "Class.constructor" in invalid-expression;
+ static method _#b#tearOff() → self::Class;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/proper_rename.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/proper_rename.dart
new file mode 100644
index 0000000..1cbbc8e
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/proper_rename.dart
@@ -0,0 +1,62 @@
+// 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 A {}
+
+class B<T> {}
+
+class C<X, Y> {}
+
+class D<X extends num> {}
+
+typedef F = A;
+
+typedef G0 = B;
+typedef G1 = B<int>;
+typedef G2<T> = B<T>;
+typedef G3<T extends num> = B<T>;
+
+typedef H0 = C;
+typedef H1 = C<int, String>;
+typedef H2<T> = C<int, T>;
+typedef H3<T, S> = C<T, S>;
+typedef H4<T, S> = C<S, T>;
+typedef H5<T extends num, S> = C<T, S>;
+typedef H6<T, S extends num> = C<T, S>;
+
+typedef I0 = D;
+typedef I1 = D<num>;
+typedef I2<T extends num> = D<T>;
+typedef I3<T extends int> = D<T>;
+
+main() {
+ var f = F.new;
+
+ var g0 = G0.new;
+ var g1 = G1.new;
+ var g2a = G2.new;
+ var g2b = G2<int>.new;
+ var g3a = G3.new;
+ var g3b = G3<int>.new;
+
+ var h0 = H0.new;
+ var h1 = H1.new;
+ var h2a = H2.new;
+ var h2b = H2<int>.new;
+ var h3a = H3.new;
+ var h3b = H3<int, String>.new;
+ var h4a = H4.new;
+ var h4b = H4<int, String>.new;
+ var h5a = H5.new;
+ var h5b = H5<int, String>.new;
+ var h6a = H6.new;
+ var h6b = H6<String, int>.new;
+
+ var i0 = I0.new;
+ var i1 = I1.new;
+ var i2a = I2.new;
+ var i2b = I2<int>.new;
+ var i3a = I3.new;
+ var i3b = I3<int>.new;
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/proper_rename.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/proper_rename.dart.strong.expect
new file mode 100644
index 0000000..b6e38f4
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/proper_rename.dart.strong.expect
@@ -0,0 +1,108 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F = self::A;
+typedef G0 = self::B<dynamic>;
+typedef G1 = self::B<core::int>;
+typedef G2<T extends core::Object? = dynamic> = self::B<T%>;
+typedef G3<T extends core::num> = self::B<T>;
+typedef H0 = self::C<dynamic, dynamic>;
+typedef H1 = self::C<core::int, core::String>;
+typedef H2<T extends core::Object? = dynamic> = self::C<core::int, T%>;
+typedef H3<T extends core::Object? = dynamic, S extends core::Object? = dynamic> = self::C<T%, S%>;
+typedef H4<T extends core::Object? = dynamic, S extends core::Object? = dynamic> = self::C<S%, T%>;
+typedef H5<T extends core::num, S extends core::Object? = dynamic> = self::C<T, S%>;
+typedef H6<T extends core::Object? = dynamic, S extends core::num> = self::C<T%, S>;
+typedef I0 = self::D<core::num>;
+typedef I1 = self::D<core::num>;
+typedef I2<T extends core::num> = self::D<T>;
+typedef I3<T extends core::int> = self::D<T>;
+class A extends core::Object {
+ synthetic constructor •() → self::A
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff() → self::A
+ return new self::A::•();
+}
+class B<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::B<self::B::T%>
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::B<self::B::_#new#tearOff::T%>
+ return new self::B::•<self::B::_#new#tearOff::T%>();
+}
+class C<X extends core::Object? = dynamic, Y extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::C<self::C::X%, self::C::Y%>
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff<X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → self::C<self::C::_#new#tearOff::X%, self::C::_#new#tearOff::Y%>
+ return new self::C::•<self::C::_#new#tearOff::X%, self::C::_#new#tearOff::Y%>();
+}
+class D<X extends core::num> extends core::Object {
+ synthetic constructor •() → self::D<self::D::X>
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff<X extends core::num>() → self::D<self::D::_#new#tearOff::X>
+ return new self::D::•<self::D::_#new#tearOff::X>();
+}
+static method main() → dynamic {
+ () → self::A f = #C1;
+ () → self::B<dynamic> g0 = #C3;
+ () → self::B<core::int> g1 = #C4;
+ <T extends core::Object? = dynamic>() → self::B<T%> g2a = #C2;
+ () → self::B<core::int> g2b = #C4;
+ <T extends core::num>() → self::B<T> g3a = #C5;
+ () → self::B<core::int> g3b = #C4;
+ () → self::C<dynamic, dynamic> h0 = #C7;
+ () → self::C<core::int, core::String> h1 = #C8;
+ <T extends core::Object? = dynamic>() → self::C<core::int, T%> h2a = #C9;
+ () → self::C<core::int, core::int> h2b = #C10;
+ <X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → self::C<X%, Y%> h3a = #C6;
+ () → self::C<core::int, core::String> h3b = #C8;
+ <T extends core::Object? = dynamic, S extends core::Object? = dynamic>() → self::C<S%, T%> h4a = #C11;
+ () → self::C<core::String, core::int> h4b = #C12;
+ <T extends core::num, S extends core::Object? = dynamic>() → self::C<T, S%> h5a = #C13;
+ () → self::C<core::int, core::String> h5b = #C8;
+ <T extends core::Object? = dynamic, S extends core::num>() → self::C<T%, S> h6a = #C14;
+ () → self::C<core::String, core::int> h6b = #C12;
+ () → self::D<core::num> i0 = #C16;
+ () → self::D<core::num> i1 = #C16;
+ <X extends core::num>() → self::D<X> i2a = #C15;
+ () → self::D<core::int> i2b = #C17;
+ <T extends core::int>() → self::D<T> i3a = #C18;
+ () → self::D<core::int> i3b = #C17;
+}
+static method _#G3#new#tearOff<T extends core::num>() → self::B<self::_#G3#new#tearOff::T>
+ return new self::B::•<self::_#G3#new#tearOff::T>();
+static method _#H2#new#tearOff<T extends core::Object? = dynamic>() → self::C<core::int, self::_#H2#new#tearOff::T%>
+ return new self::C::•<core::int, self::_#H2#new#tearOff::T%>();
+static method _#H4#new#tearOff<T extends core::Object? = dynamic, S extends core::Object? = dynamic>() → self::C<self::_#H4#new#tearOff::S%, self::_#H4#new#tearOff::T%>
+ return new self::C::•<self::_#H4#new#tearOff::S%, self::_#H4#new#tearOff::T%>();
+static method _#H5#new#tearOff<T extends core::num, S extends core::Object? = dynamic>() → self::C<self::_#H5#new#tearOff::T, self::_#H5#new#tearOff::S%>
+ return new self::C::•<self::_#H5#new#tearOff::T, self::_#H5#new#tearOff::S%>();
+static method _#H6#new#tearOff<T extends core::Object? = dynamic, S extends core::num>() → self::C<self::_#H6#new#tearOff::T%, self::_#H6#new#tearOff::S>
+ return new self::C::•<self::_#H6#new#tearOff::T%, self::_#H6#new#tearOff::S>();
+static method _#I3#new#tearOff<T extends core::int>() → self::D<self::_#I3#new#tearOff::T>
+ return new self::D::•<self::_#I3#new#tearOff::T>();
+
+constants {
+ #C1 = static-tearoff self::A::_#new#tearOff
+ #C2 = static-tearoff self::B::_#new#tearOff
+ #C3 = instantiation self::B::_#new#tearOff <dynamic>
+ #C4 = instantiation self::B::_#new#tearOff <core::int>
+ #C5 = static-tearoff self::_#G3#new#tearOff
+ #C6 = static-tearoff self::C::_#new#tearOff
+ #C7 = instantiation self::C::_#new#tearOff <dynamic, dynamic>
+ #C8 = instantiation self::C::_#new#tearOff <core::int, core::String>
+ #C9 = static-tearoff self::_#H2#new#tearOff
+ #C10 = instantiation self::C::_#new#tearOff <core::int, core::int>
+ #C11 = static-tearoff self::_#H4#new#tearOff
+ #C12 = instantiation self::C::_#new#tearOff <core::String, core::int>
+ #C13 = static-tearoff self::_#H5#new#tearOff
+ #C14 = static-tearoff self::_#H6#new#tearOff
+ #C15 = static-tearoff self::D::_#new#tearOff
+ #C16 = instantiation self::D::_#new#tearOff <core::num>
+ #C17 = instantiation self::D::_#new#tearOff <core::int>
+ #C18 = static-tearoff self::_#I3#new#tearOff
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/proper_rename.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/proper_rename.dart.strong.transformed.expect
new file mode 100644
index 0000000..b6e38f4
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/proper_rename.dart.strong.transformed.expect
@@ -0,0 +1,108 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F = self::A;
+typedef G0 = self::B<dynamic>;
+typedef G1 = self::B<core::int>;
+typedef G2<T extends core::Object? = dynamic> = self::B<T%>;
+typedef G3<T extends core::num> = self::B<T>;
+typedef H0 = self::C<dynamic, dynamic>;
+typedef H1 = self::C<core::int, core::String>;
+typedef H2<T extends core::Object? = dynamic> = self::C<core::int, T%>;
+typedef H3<T extends core::Object? = dynamic, S extends core::Object? = dynamic> = self::C<T%, S%>;
+typedef H4<T extends core::Object? = dynamic, S extends core::Object? = dynamic> = self::C<S%, T%>;
+typedef H5<T extends core::num, S extends core::Object? = dynamic> = self::C<T, S%>;
+typedef H6<T extends core::Object? = dynamic, S extends core::num> = self::C<T%, S>;
+typedef I0 = self::D<core::num>;
+typedef I1 = self::D<core::num>;
+typedef I2<T extends core::num> = self::D<T>;
+typedef I3<T extends core::int> = self::D<T>;
+class A extends core::Object {
+ synthetic constructor •() → self::A
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff() → self::A
+ return new self::A::•();
+}
+class B<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::B<self::B::T%>
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::B<self::B::_#new#tearOff::T%>
+ return new self::B::•<self::B::_#new#tearOff::T%>();
+}
+class C<X extends core::Object? = dynamic, Y extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::C<self::C::X%, self::C::Y%>
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff<X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → self::C<self::C::_#new#tearOff::X%, self::C::_#new#tearOff::Y%>
+ return new self::C::•<self::C::_#new#tearOff::X%, self::C::_#new#tearOff::Y%>();
+}
+class D<X extends core::num> extends core::Object {
+ synthetic constructor •() → self::D<self::D::X>
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff<X extends core::num>() → self::D<self::D::_#new#tearOff::X>
+ return new self::D::•<self::D::_#new#tearOff::X>();
+}
+static method main() → dynamic {
+ () → self::A f = #C1;
+ () → self::B<dynamic> g0 = #C3;
+ () → self::B<core::int> g1 = #C4;
+ <T extends core::Object? = dynamic>() → self::B<T%> g2a = #C2;
+ () → self::B<core::int> g2b = #C4;
+ <T extends core::num>() → self::B<T> g3a = #C5;
+ () → self::B<core::int> g3b = #C4;
+ () → self::C<dynamic, dynamic> h0 = #C7;
+ () → self::C<core::int, core::String> h1 = #C8;
+ <T extends core::Object? = dynamic>() → self::C<core::int, T%> h2a = #C9;
+ () → self::C<core::int, core::int> h2b = #C10;
+ <X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → self::C<X%, Y%> h3a = #C6;
+ () → self::C<core::int, core::String> h3b = #C8;
+ <T extends core::Object? = dynamic, S extends core::Object? = dynamic>() → self::C<S%, T%> h4a = #C11;
+ () → self::C<core::String, core::int> h4b = #C12;
+ <T extends core::num, S extends core::Object? = dynamic>() → self::C<T, S%> h5a = #C13;
+ () → self::C<core::int, core::String> h5b = #C8;
+ <T extends core::Object? = dynamic, S extends core::num>() → self::C<T%, S> h6a = #C14;
+ () → self::C<core::String, core::int> h6b = #C12;
+ () → self::D<core::num> i0 = #C16;
+ () → self::D<core::num> i1 = #C16;
+ <X extends core::num>() → self::D<X> i2a = #C15;
+ () → self::D<core::int> i2b = #C17;
+ <T extends core::int>() → self::D<T> i3a = #C18;
+ () → self::D<core::int> i3b = #C17;
+}
+static method _#G3#new#tearOff<T extends core::num>() → self::B<self::_#G3#new#tearOff::T>
+ return new self::B::•<self::_#G3#new#tearOff::T>();
+static method _#H2#new#tearOff<T extends core::Object? = dynamic>() → self::C<core::int, self::_#H2#new#tearOff::T%>
+ return new self::C::•<core::int, self::_#H2#new#tearOff::T%>();
+static method _#H4#new#tearOff<T extends core::Object? = dynamic, S extends core::Object? = dynamic>() → self::C<self::_#H4#new#tearOff::S%, self::_#H4#new#tearOff::T%>
+ return new self::C::•<self::_#H4#new#tearOff::S%, self::_#H4#new#tearOff::T%>();
+static method _#H5#new#tearOff<T extends core::num, S extends core::Object? = dynamic>() → self::C<self::_#H5#new#tearOff::T, self::_#H5#new#tearOff::S%>
+ return new self::C::•<self::_#H5#new#tearOff::T, self::_#H5#new#tearOff::S%>();
+static method _#H6#new#tearOff<T extends core::Object? = dynamic, S extends core::num>() → self::C<self::_#H6#new#tearOff::T%, self::_#H6#new#tearOff::S>
+ return new self::C::•<self::_#H6#new#tearOff::T%, self::_#H6#new#tearOff::S>();
+static method _#I3#new#tearOff<T extends core::int>() → self::D<self::_#I3#new#tearOff::T>
+ return new self::D::•<self::_#I3#new#tearOff::T>();
+
+constants {
+ #C1 = static-tearoff self::A::_#new#tearOff
+ #C2 = static-tearoff self::B::_#new#tearOff
+ #C3 = instantiation self::B::_#new#tearOff <dynamic>
+ #C4 = instantiation self::B::_#new#tearOff <core::int>
+ #C5 = static-tearoff self::_#G3#new#tearOff
+ #C6 = static-tearoff self::C::_#new#tearOff
+ #C7 = instantiation self::C::_#new#tearOff <dynamic, dynamic>
+ #C8 = instantiation self::C::_#new#tearOff <core::int, core::String>
+ #C9 = static-tearoff self::_#H2#new#tearOff
+ #C10 = instantiation self::C::_#new#tearOff <core::int, core::int>
+ #C11 = static-tearoff self::_#H4#new#tearOff
+ #C12 = instantiation self::C::_#new#tearOff <core::String, core::int>
+ #C13 = static-tearoff self::_#H5#new#tearOff
+ #C14 = static-tearoff self::_#H6#new#tearOff
+ #C15 = static-tearoff self::D::_#new#tearOff
+ #C16 = instantiation self::D::_#new#tearOff <core::num>
+ #C17 = instantiation self::D::_#new#tearOff <core::int>
+ #C18 = static-tearoff self::_#I3#new#tearOff
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/proper_rename.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/proper_rename.dart.textual_outline.expect
new file mode 100644
index 0000000..9a7c825
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/proper_rename.dart.textual_outline.expect
@@ -0,0 +1,25 @@
+class A {}
+
+class B<T> {}
+
+class C<X, Y> {}
+
+class D<X extends num> {}
+
+typedef F = A;
+typedef G0 = B;
+typedef G1 = B<int>;
+typedef G2<T> = B<T>;
+typedef G3<T extends num> = B<T>;
+typedef H0 = C;
+typedef H1 = C<int, String>;
+typedef H2<T> = C<int, T>;
+typedef H3<T, S> = C<T, S>;
+typedef H4<T, S> = C<S, T>;
+typedef H5<T extends num, S> = C<T, S>;
+typedef H6<T, S extends num> = C<T, S>;
+typedef I0 = D;
+typedef I1 = D<num>;
+typedef I2<T extends num> = D<T>;
+typedef I3<T extends int> = D<T>;
+main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/proper_rename.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/proper_rename.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..f5f173a
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/proper_rename.dart.textual_outline_modelled.expect
@@ -0,0 +1,25 @@
+class A {}
+
+class B<T> {}
+
+class C<X, Y> {}
+
+class D<X extends num> {}
+
+main() {}
+typedef F = A;
+typedef G0 = B;
+typedef G1 = B<int>;
+typedef G2<T> = B<T>;
+typedef G3<T extends num> = B<T>;
+typedef H0 = C;
+typedef H1 = C<int, String>;
+typedef H2<T> = C<int, T>;
+typedef H3<T, S> = C<T, S>;
+typedef H4<T, S> = C<S, T>;
+typedef H5<T extends num, S> = C<T, S>;
+typedef H6<T, S extends num> = C<T, S>;
+typedef I0 = D;
+typedef I1 = D<num>;
+typedef I2<T extends num> = D<T>;
+typedef I3<T extends int> = D<T>;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/proper_rename.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/proper_rename.dart.weak.expect
new file mode 100644
index 0000000..2d72357
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/proper_rename.dart.weak.expect
@@ -0,0 +1,108 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F = self::A;
+typedef G0 = self::B<dynamic>;
+typedef G1 = self::B<core::int>;
+typedef G2<T extends core::Object? = dynamic> = self::B<T%>;
+typedef G3<T extends core::num> = self::B<T>;
+typedef H0 = self::C<dynamic, dynamic>;
+typedef H1 = self::C<core::int, core::String>;
+typedef H2<T extends core::Object? = dynamic> = self::C<core::int, T%>;
+typedef H3<T extends core::Object? = dynamic, S extends core::Object? = dynamic> = self::C<T%, S%>;
+typedef H4<T extends core::Object? = dynamic, S extends core::Object? = dynamic> = self::C<S%, T%>;
+typedef H5<T extends core::num, S extends core::Object? = dynamic> = self::C<T, S%>;
+typedef H6<T extends core::Object? = dynamic, S extends core::num> = self::C<T%, S>;
+typedef I0 = self::D<core::num>;
+typedef I1 = self::D<core::num>;
+typedef I2<T extends core::num> = self::D<T>;
+typedef I3<T extends core::int> = self::D<T>;
+class A extends core::Object {
+ synthetic constructor •() → self::A
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff() → self::A
+ return new self::A::•();
+}
+class B<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::B<self::B::T%>
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::B<self::B::_#new#tearOff::T%>
+ return new self::B::•<self::B::_#new#tearOff::T%>();
+}
+class C<X extends core::Object? = dynamic, Y extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::C<self::C::X%, self::C::Y%>
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff<X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → self::C<self::C::_#new#tearOff::X%, self::C::_#new#tearOff::Y%>
+ return new self::C::•<self::C::_#new#tearOff::X%, self::C::_#new#tearOff::Y%>();
+}
+class D<X extends core::num> extends core::Object {
+ synthetic constructor •() → self::D<self::D::X>
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff<X extends core::num>() → self::D<self::D::_#new#tearOff::X>
+ return new self::D::•<self::D::_#new#tearOff::X>();
+}
+static method main() → dynamic {
+ () → self::A f = #C1;
+ () → self::B<dynamic> g0 = #C3;
+ () → self::B<core::int> g1 = #C4;
+ <T extends core::Object? = dynamic>() → self::B<T%> g2a = #C2;
+ () → self::B<core::int> g2b = #C4;
+ <T extends core::num>() → self::B<T> g3a = #C5;
+ () → self::B<core::int> g3b = #C4;
+ () → self::C<dynamic, dynamic> h0 = #C7;
+ () → self::C<core::int, core::String> h1 = #C8;
+ <T extends core::Object? = dynamic>() → self::C<core::int, T%> h2a = #C9;
+ () → self::C<core::int, core::int> h2b = #C10;
+ <X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → self::C<X%, Y%> h3a = #C6;
+ () → self::C<core::int, core::String> h3b = #C8;
+ <T extends core::Object? = dynamic, S extends core::Object? = dynamic>() → self::C<S%, T%> h4a = #C11;
+ () → self::C<core::String, core::int> h4b = #C12;
+ <T extends core::num, S extends core::Object? = dynamic>() → self::C<T, S%> h5a = #C13;
+ () → self::C<core::int, core::String> h5b = #C8;
+ <T extends core::Object? = dynamic, S extends core::num>() → self::C<T%, S> h6a = #C14;
+ () → self::C<core::String, core::int> h6b = #C12;
+ () → self::D<core::num> i0 = #C16;
+ () → self::D<core::num> i1 = #C16;
+ <X extends core::num>() → self::D<X> i2a = #C15;
+ () → self::D<core::int> i2b = #C17;
+ <T extends core::int>() → self::D<T> i3a = #C18;
+ () → self::D<core::int> i3b = #C17;
+}
+static method _#G3#new#tearOff<T extends core::num>() → self::B<self::_#G3#new#tearOff::T>
+ return new self::B::•<self::_#G3#new#tearOff::T>();
+static method _#H2#new#tearOff<T extends core::Object? = dynamic>() → self::C<core::int, self::_#H2#new#tearOff::T%>
+ return new self::C::•<core::int, self::_#H2#new#tearOff::T%>();
+static method _#H4#new#tearOff<T extends core::Object? = dynamic, S extends core::Object? = dynamic>() → self::C<self::_#H4#new#tearOff::S%, self::_#H4#new#tearOff::T%>
+ return new self::C::•<self::_#H4#new#tearOff::S%, self::_#H4#new#tearOff::T%>();
+static method _#H5#new#tearOff<T extends core::num, S extends core::Object? = dynamic>() → self::C<self::_#H5#new#tearOff::T, self::_#H5#new#tearOff::S%>
+ return new self::C::•<self::_#H5#new#tearOff::T, self::_#H5#new#tearOff::S%>();
+static method _#H6#new#tearOff<T extends core::Object? = dynamic, S extends core::num>() → self::C<self::_#H6#new#tearOff::T%, self::_#H6#new#tearOff::S>
+ return new self::C::•<self::_#H6#new#tearOff::T%, self::_#H6#new#tearOff::S>();
+static method _#I3#new#tearOff<T extends core::int>() → self::D<self::_#I3#new#tearOff::T>
+ return new self::D::•<self::_#I3#new#tearOff::T>();
+
+constants {
+ #C1 = static-tearoff self::A::_#new#tearOff
+ #C2 = static-tearoff self::B::_#new#tearOff
+ #C3 = instantiation self::B::_#new#tearOff <dynamic>
+ #C4 = instantiation self::B::_#new#tearOff <core::int*>
+ #C5 = static-tearoff self::_#G3#new#tearOff
+ #C6 = static-tearoff self::C::_#new#tearOff
+ #C7 = instantiation self::C::_#new#tearOff <dynamic, dynamic>
+ #C8 = instantiation self::C::_#new#tearOff <core::int*, core::String*>
+ #C9 = static-tearoff self::_#H2#new#tearOff
+ #C10 = instantiation self::C::_#new#tearOff <core::int*, core::int*>
+ #C11 = static-tearoff self::_#H4#new#tearOff
+ #C12 = instantiation self::C::_#new#tearOff <core::String*, core::int*>
+ #C13 = static-tearoff self::_#H5#new#tearOff
+ #C14 = static-tearoff self::_#H6#new#tearOff
+ #C15 = static-tearoff self::D::_#new#tearOff
+ #C16 = instantiation self::D::_#new#tearOff <core::num*>
+ #C17 = instantiation self::D::_#new#tearOff <core::int*>
+ #C18 = static-tearoff self::_#I3#new#tearOff
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/proper_rename.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/proper_rename.dart.weak.outline.expect
new file mode 100644
index 0000000..3dbbebd
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/proper_rename.dart.weak.outline.expect
@@ -0,0 +1,58 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F = self::A;
+typedef G0 = self::B<dynamic>;
+typedef G1 = self::B<core::int>;
+typedef G2<T extends core::Object? = dynamic> = self::B<T%>;
+typedef G3<T extends core::num> = self::B<T>;
+typedef H0 = self::C<dynamic, dynamic>;
+typedef H1 = self::C<core::int, core::String>;
+typedef H2<T extends core::Object? = dynamic> = self::C<core::int, T%>;
+typedef H3<T extends core::Object? = dynamic, S extends core::Object? = dynamic> = self::C<T%, S%>;
+typedef H4<T extends core::Object? = dynamic, S extends core::Object? = dynamic> = self::C<S%, T%>;
+typedef H5<T extends core::num, S extends core::Object? = dynamic> = self::C<T, S%>;
+typedef H6<T extends core::Object? = dynamic, S extends core::num> = self::C<T%, S>;
+typedef I0 = self::D<core::num>;
+typedef I1 = self::D<core::num>;
+typedef I2<T extends core::num> = self::D<T>;
+typedef I3<T extends core::int> = self::D<T>;
+class A extends core::Object {
+ synthetic constructor •() → self::A
+ ;
+ static method _#new#tearOff() → self::A
+ return new self::A::•();
+}
+class B<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::B<self::B::T%>
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::B<self::B::_#new#tearOff::T%>
+ return new self::B::•<self::B::_#new#tearOff::T%>();
+}
+class C<X extends core::Object? = dynamic, Y extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::C<self::C::X%, self::C::Y%>
+ ;
+ static method _#new#tearOff<X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → self::C<self::C::_#new#tearOff::X%, self::C::_#new#tearOff::Y%>
+ return new self::C::•<self::C::_#new#tearOff::X%, self::C::_#new#tearOff::Y%>();
+}
+class D<X extends core::num> extends core::Object {
+ synthetic constructor •() → self::D<self::D::X>
+ ;
+ static method _#new#tearOff<X extends core::num>() → self::D<self::D::_#new#tearOff::X>
+ return new self::D::•<self::D::_#new#tearOff::X>();
+}
+static method main() → dynamic
+ ;
+static method _#G3#new#tearOff<T extends core::num>() → self::B<self::_#G3#new#tearOff::T>
+ return new self::B::•<self::_#G3#new#tearOff::T>();
+static method _#H2#new#tearOff<T extends core::Object? = dynamic>() → self::C<core::int, self::_#H2#new#tearOff::T%>
+ return new self::C::•<core::int, self::_#H2#new#tearOff::T%>();
+static method _#H4#new#tearOff<T extends core::Object? = dynamic, S extends core::Object? = dynamic>() → self::C<self::_#H4#new#tearOff::S%, self::_#H4#new#tearOff::T%>
+ return new self::C::•<self::_#H4#new#tearOff::S%, self::_#H4#new#tearOff::T%>();
+static method _#H5#new#tearOff<T extends core::num, S extends core::Object? = dynamic>() → self::C<self::_#H5#new#tearOff::T, self::_#H5#new#tearOff::S%>
+ return new self::C::•<self::_#H5#new#tearOff::T, self::_#H5#new#tearOff::S%>();
+static method _#H6#new#tearOff<T extends core::Object? = dynamic, S extends core::num>() → self::C<self::_#H6#new#tearOff::T%, self::_#H6#new#tearOff::S>
+ return new self::C::•<self::_#H6#new#tearOff::T%, self::_#H6#new#tearOff::S>();
+static method _#I3#new#tearOff<T extends core::int>() → self::D<self::_#I3#new#tearOff::T>
+ return new self::D::•<self::_#I3#new#tearOff::T>();
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/proper_rename.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/proper_rename.dart.weak.transformed.expect
new file mode 100644
index 0000000..2d72357
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/proper_rename.dart.weak.transformed.expect
@@ -0,0 +1,108 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef F = self::A;
+typedef G0 = self::B<dynamic>;
+typedef G1 = self::B<core::int>;
+typedef G2<T extends core::Object? = dynamic> = self::B<T%>;
+typedef G3<T extends core::num> = self::B<T>;
+typedef H0 = self::C<dynamic, dynamic>;
+typedef H1 = self::C<core::int, core::String>;
+typedef H2<T extends core::Object? = dynamic> = self::C<core::int, T%>;
+typedef H3<T extends core::Object? = dynamic, S extends core::Object? = dynamic> = self::C<T%, S%>;
+typedef H4<T extends core::Object? = dynamic, S extends core::Object? = dynamic> = self::C<S%, T%>;
+typedef H5<T extends core::num, S extends core::Object? = dynamic> = self::C<T, S%>;
+typedef H6<T extends core::Object? = dynamic, S extends core::num> = self::C<T%, S>;
+typedef I0 = self::D<core::num>;
+typedef I1 = self::D<core::num>;
+typedef I2<T extends core::num> = self::D<T>;
+typedef I3<T extends core::int> = self::D<T>;
+class A extends core::Object {
+ synthetic constructor •() → self::A
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff() → self::A
+ return new self::A::•();
+}
+class B<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::B<self::B::T%>
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::B<self::B::_#new#tearOff::T%>
+ return new self::B::•<self::B::_#new#tearOff::T%>();
+}
+class C<X extends core::Object? = dynamic, Y extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::C<self::C::X%, self::C::Y%>
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff<X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → self::C<self::C::_#new#tearOff::X%, self::C::_#new#tearOff::Y%>
+ return new self::C::•<self::C::_#new#tearOff::X%, self::C::_#new#tearOff::Y%>();
+}
+class D<X extends core::num> extends core::Object {
+ synthetic constructor •() → self::D<self::D::X>
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff<X extends core::num>() → self::D<self::D::_#new#tearOff::X>
+ return new self::D::•<self::D::_#new#tearOff::X>();
+}
+static method main() → dynamic {
+ () → self::A f = #C1;
+ () → self::B<dynamic> g0 = #C3;
+ () → self::B<core::int> g1 = #C4;
+ <T extends core::Object? = dynamic>() → self::B<T%> g2a = #C2;
+ () → self::B<core::int> g2b = #C4;
+ <T extends core::num>() → self::B<T> g3a = #C5;
+ () → self::B<core::int> g3b = #C4;
+ () → self::C<dynamic, dynamic> h0 = #C7;
+ () → self::C<core::int, core::String> h1 = #C8;
+ <T extends core::Object? = dynamic>() → self::C<core::int, T%> h2a = #C9;
+ () → self::C<core::int, core::int> h2b = #C10;
+ <X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → self::C<X%, Y%> h3a = #C6;
+ () → self::C<core::int, core::String> h3b = #C8;
+ <T extends core::Object? = dynamic, S extends core::Object? = dynamic>() → self::C<S%, T%> h4a = #C11;
+ () → self::C<core::String, core::int> h4b = #C12;
+ <T extends core::num, S extends core::Object? = dynamic>() → self::C<T, S%> h5a = #C13;
+ () → self::C<core::int, core::String> h5b = #C8;
+ <T extends core::Object? = dynamic, S extends core::num>() → self::C<T%, S> h6a = #C14;
+ () → self::C<core::String, core::int> h6b = #C12;
+ () → self::D<core::num> i0 = #C16;
+ () → self::D<core::num> i1 = #C16;
+ <X extends core::num>() → self::D<X> i2a = #C15;
+ () → self::D<core::int> i2b = #C17;
+ <T extends core::int>() → self::D<T> i3a = #C18;
+ () → self::D<core::int> i3b = #C17;
+}
+static method _#G3#new#tearOff<T extends core::num>() → self::B<self::_#G3#new#tearOff::T>
+ return new self::B::•<self::_#G3#new#tearOff::T>();
+static method _#H2#new#tearOff<T extends core::Object? = dynamic>() → self::C<core::int, self::_#H2#new#tearOff::T%>
+ return new self::C::•<core::int, self::_#H2#new#tearOff::T%>();
+static method _#H4#new#tearOff<T extends core::Object? = dynamic, S extends core::Object? = dynamic>() → self::C<self::_#H4#new#tearOff::S%, self::_#H4#new#tearOff::T%>
+ return new self::C::•<self::_#H4#new#tearOff::S%, self::_#H4#new#tearOff::T%>();
+static method _#H5#new#tearOff<T extends core::num, S extends core::Object? = dynamic>() → self::C<self::_#H5#new#tearOff::T, self::_#H5#new#tearOff::S%>
+ return new self::C::•<self::_#H5#new#tearOff::T, self::_#H5#new#tearOff::S%>();
+static method _#H6#new#tearOff<T extends core::Object? = dynamic, S extends core::num>() → self::C<self::_#H6#new#tearOff::T%, self::_#H6#new#tearOff::S>
+ return new self::C::•<self::_#H6#new#tearOff::T%, self::_#H6#new#tearOff::S>();
+static method _#I3#new#tearOff<T extends core::int>() → self::D<self::_#I3#new#tearOff::T>
+ return new self::D::•<self::_#I3#new#tearOff::T>();
+
+constants {
+ #C1 = static-tearoff self::A::_#new#tearOff
+ #C2 = static-tearoff self::B::_#new#tearOff
+ #C3 = instantiation self::B::_#new#tearOff <dynamic>
+ #C4 = instantiation self::B::_#new#tearOff <core::int*>
+ #C5 = static-tearoff self::_#G3#new#tearOff
+ #C6 = static-tearoff self::C::_#new#tearOff
+ #C7 = instantiation self::C::_#new#tearOff <dynamic, dynamic>
+ #C8 = instantiation self::C::_#new#tearOff <core::int*, core::String*>
+ #C9 = static-tearoff self::_#H2#new#tearOff
+ #C10 = instantiation self::C::_#new#tearOff <core::int*, core::int*>
+ #C11 = static-tearoff self::_#H4#new#tearOff
+ #C12 = instantiation self::C::_#new#tearOff <core::String*, core::int*>
+ #C13 = static-tearoff self::_#H5#new#tearOff
+ #C14 = static-tearoff self::_#H6#new#tearOff
+ #C15 = static-tearoff self::D::_#new#tearOff
+ #C16 = instantiation self::D::_#new#tearOff <core::num*>
+ #C17 = instantiation self::D::_#new#tearOff <core::int*>
+ #C18 = static-tearoff self::_#I3#new#tearOff
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart
new file mode 100644
index 0000000..765da64
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart
@@ -0,0 +1,194 @@
+// 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.
+
+final bool inSoundMode = <int?>[] is! List<int>;
+
+main() {
+ print('inSoundMode: $inSoundMode');
+ testNoArgs();
+ testArgs();
+}
+
+class Class1 {
+ Class1._();
+ factory Class1() = Class1._;
+}
+
+class Class2 {
+ Class2.__();
+ factory Class2._() => Class2.__();
+ factory Class2.named() = Class2._;
+}
+
+testNoArgs() {
+ var f1a = Class1.new;
+ var c1a = f1a();
+ expect(true, c1a is Class1);
+
+ dynamic f1b = Class1.new;
+ var c1b = f1b();
+ expect(true, c1b is Class1);
+
+ expect(true, identical(f1a, f1b));
+
+ var f2a = Class2.named;
+ var c2a = f2a();
+ expect(true, c2a is Class2);
+
+ dynamic f2b = Class2.named;
+ var c2b = f2b();
+ expect(true, c2b is Class2);
+
+ expect(true, identical(f2a, f2b));
+}
+
+class Class3 {
+ final int field;
+
+ Class3._(this.field);
+ factory Class3(int field) = Class3._;
+}
+
+class Class4 {
+ final int? field;
+
+ Class4._([this.field]);
+ factory Class4([int? field]) = Class4._;
+}
+
+class Class5 {
+ final int field1;
+ final int? field2;
+
+ Class5._(this.field1, [this.field2]);
+ factory Class5(int field1, [int? field2]) = Class5._;
+}
+
+class Class6 {
+ final int field1;
+ final int? field2;
+ final int field3;
+
+ Class6._(this.field1, {this.field2, required this.field3});
+ factory Class6(int field1, {int? field2, required int field3}) =
+ Class6._;
+}
+
+class Class7a implements Class7b {
+ Class7a();
+}
+
+class Class7b {
+ factory Class7b() = Class7a;
+}
+
+class Class8a<T> implements Class8b<T> {
+ Class8a();
+}
+
+class Class8b<T> {
+ factory Class8b() = Class8a<T>;
+}
+
+testArgs() {
+ var f3a = Class3.new;
+ var c3a = f3a(42);
+ expect(42, c3a.field);
+ () {
+ f3a(); // error
+ f3a(42, 87); // error
+ };
+
+ dynamic f3b = Class3.new;
+ var c3b = f3b(87);
+ expect(87, c3b.field);
+ throws(() => f3b());
+ throws(() => f3b(42, 87));
+
+ var f4a = Class4.new;
+ var c4a = f4a();
+ expect(null, c4a.field);
+ var c4b = f4a(42);
+ expect(42, c4b.field);
+ () {
+ f4a(42, 87); // error
+ };
+ dynamic f4b = Class4.new;
+ throws(() => f4b(42, 87));
+
+
+ var f5a = Class5.new;
+ var c5a = f5a(42);
+ expect(42, c5a.field1);
+ expect(null, c5a.field2);
+ var c5b = f5a(87, 42);
+ expect(87, c5b.field1);
+ expect(42, c5b.field2);
+ () {
+ f5a(); // error
+ f5a(42, 87, 123); // error
+ };
+ dynamic f5b = Class5.new;
+ throws(() => f5b());
+ throws(() => f5b(42, 87, 123));
+
+ var f6a = Class6.new;
+ var c6a = f6a(42, field3: 87);
+ expect(42, c6a.field1);
+ expect(null, c6a.field2);
+ expect(87, c6a.field3);
+ () {
+ f6a(); // error
+ f6a(42); // error
+ f6a(42, 87); // error
+ f6a(field1: 87, field2: 87); // error
+ };
+
+ var c6b = f6a(42, field2: 123, field3: 87);
+ expect(42, c6b.field1);
+ expect(123, c6b.field2);
+ expect(87, c6b.field3);
+
+ var c6c = f6a(87, field3: 42, field2: 123);
+ expect(87, c6c.field1);
+ expect(123, c6c.field2);
+ expect(42, c6c.field3);
+
+ dynamic f6b = Class6.new;
+ throws(() => f6b());
+ throws(() => f6b(42), inSoundModeOnly: true);
+ throws(() => f6b(42, 87), inSoundModeOnly: true);
+ throws(() => f6b(field1: 87, field2: 87));
+
+ var f7a = Class7b.new;
+ var c7a = f7a();
+ expect(true, c7a is Class7a);
+ expect(true, c7a is Class7b);
+
+ var f8a = Class8b.new;
+ var c8a = f8a();
+ expect(true, c8a is Class8a);
+ expect(true, c8a is Class8b);
+ var c8b = f8a<int>();
+ expect(true, c8b is Class8a<int>);
+ expect(true, c8b is Class8b<int>);
+ expect(false, c8b is Class8b<String>);
+}
+
+expect(expected, actual) {
+ if (expected != actual) throw 'Expected $expected, actual $actual';
+}
+
+throws(Function() f, {bool inSoundModeOnly: false}) {
+ try {
+ f();
+ } catch (e) {
+ print('Thrown: $e');
+ return;
+ }
+ if (!inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw 'Expected exception';
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.strong.expect
new file mode 100644
index 0000000..a115126
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.strong.expect
@@ -0,0 +1,306 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:99:8: Error: Too few positional arguments: 1 required, 0 given.
+// f3a(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:100:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f3a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:115:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f4a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:129:8: Error: Too few positional arguments: 1 required, 0 given.
+// f5a(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:130:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+// Try removing the extra positional arguments.
+// f5a(42, 87, 123); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:142:8: Error: Too few positional arguments: 1 required, 0 given.
+// f6a(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:143:8: Error: Required named parameter 'field3' must be provided.
+// f6a(42); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:144:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f6a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:145:8: Error: Too few positional arguments: 1 required, 0 given.
+// f6a(field1: 87, field2: 87); // error
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class1::•]/*isLegacy*/;
+ constructor _() → self::Class1
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff() → self::Class1
+ return new self::Class1::_();
+ static factory •() → self::Class1
+ let dynamic #redirecting_factory = self::Class1::_ in invalid-expression;
+ static method _#new#tearOff() → self::Class1
+ return new self::Class1::_();
+}
+class Class2 extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class2::named]/*isLegacy*/;
+ constructor __() → self::Class2
+ : super core::Object::•()
+ ;
+ static method _#__#tearOff() → self::Class2
+ return new self::Class2::__();
+ static factory _() → self::Class2
+ return new self::Class2::__();
+ static method _#_#tearOff() → self::Class2
+ return self::Class2::_();
+ static factory named() → self::Class2
+ let dynamic #redirecting_factory = self::Class2::_ in invalid-expression;
+ static method _#named#tearOff() → self::Class2
+ return self::Class2::_();
+}
+class Class3 extends core::Object {
+ final field core::int field;
+ static final field dynamic _redirecting# = <dynamic>[self::Class3::•]/*isLegacy*/;
+ constructor _(core::int field) → self::Class3
+ : self::Class3::field = field, super core::Object::•()
+ ;
+ static method _#_#tearOff(core::int field) → self::Class3
+ return new self::Class3::_(field);
+ static factory •(core::int field) → self::Class3
+ let dynamic #redirecting_factory = self::Class3::_ in invalid-expression;
+ static method _#new#tearOff(core::int field) → self::Class3
+ return new self::Class3::_(field);
+}
+class Class4 extends core::Object {
+ final field core::int? field;
+ static final field dynamic _redirecting# = <dynamic>[self::Class4::•]/*isLegacy*/;
+ constructor _([core::int? field = #C1]) → self::Class4
+ : self::Class4::field = field, super core::Object::•()
+ ;
+ static method _#_#tearOff([core::int? field = #C1]) → self::Class4
+ return new self::Class4::_(field);
+ static factory •([core::int? field = #C1]) → self::Class4
+ let dynamic #redirecting_factory = self::Class4::_ in invalid-expression;
+ static method _#new#tearOff([core::int? field = #C1]) → self::Class4
+ return new self::Class4::_(field);
+}
+class Class5 extends core::Object {
+ final field core::int field1;
+ final field core::int? field2;
+ static final field dynamic _redirecting# = <dynamic>[self::Class5::•]/*isLegacy*/;
+ constructor _(core::int field1, [core::int? field2 = #C1]) → self::Class5
+ : self::Class5::field1 = field1, self::Class5::field2 = field2, super core::Object::•()
+ ;
+ static method _#_#tearOff(core::int field1, [core::int? field2 = #C1]) → self::Class5
+ return new self::Class5::_(field1, field2);
+ static factory •(core::int field1, [core::int? field2 = #C1]) → self::Class5
+ let dynamic #redirecting_factory = self::Class5::_ in invalid-expression;
+ static method _#new#tearOff(core::int field1, [core::int? field2 = #C1]) → self::Class5
+ return new self::Class5::_(field1, field2);
+}
+class Class6 extends core::Object {
+ final field core::int field1;
+ final field core::int? field2;
+ final field core::int field3;
+ static final field dynamic _redirecting# = <dynamic>[self::Class6::•]/*isLegacy*/;
+ constructor _(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+ : self::Class6::field1 = field1, self::Class6::field2 = field2, self::Class6::field3 = field3, super core::Object::•()
+ ;
+ static method _#_#tearOff(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+ return new self::Class6::_(field1, field2: field2, field3: field3);
+ static factory •(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+ let dynamic #redirecting_factory = self::Class6::_ in invalid-expression;
+ static method _#new#tearOff(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+ return new self::Class6::_(field1, field2: field2, field3: field3);
+}
+class Class7a extends core::Object implements self::Class7b {
+ constructor •() → self::Class7a
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff() → self::Class7a
+ return new self::Class7a::•();
+}
+class Class7b extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class7b::•]/*isLegacy*/;
+ static factory •() → self::Class7b
+ let dynamic #redirecting_factory = self::Class7a::• in invalid-expression;
+ static method _#new#tearOff() → self::Class7b
+ return new self::Class7a::•();
+}
+class Class8a<T extends core::Object? = dynamic> extends core::Object implements self::Class8b<self::Class8a::T%> {
+ constructor •() → self::Class8a<self::Class8a::T%>
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class8a<self::Class8a::_#new#tearOff::T%>
+ return new self::Class8a::•<self::Class8a::_#new#tearOff::T%>();
+}
+class Class8b<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class8b::•]/*isLegacy*/;
+ static factory •<T extends core::Object? = dynamic>() → self::Class8b<self::Class8b::•::T%>
+ let dynamic #redirecting_factory = self::Class8a::• in let self::Class8b::•::T% #typeArg0 = null in invalid-expression;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class8b<self::Class8b::_#new#tearOff::T%>
+ return new self::Class8a::•<self::Class8b::_#new#tearOff::T%>();
+}
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+ core::print("inSoundMode: ${self::inSoundMode}");
+ self::testNoArgs();
+ self::testArgs();
+}
+static method testNoArgs() → dynamic {
+ () → self::Class1 f1a = #C2;
+ self::Class1 c1a = f1a(){() → self::Class1};
+ self::expect(true, c1a is{ForNonNullableByDefault} self::Class1);
+ dynamic f1b = #C2;
+ dynamic c1b = f1b{dynamic}.call();
+ self::expect(true, c1b is{ForNonNullableByDefault} self::Class1);
+ self::expect(true, core::identical(f1a, f1b));
+ () → self::Class2 f2a = #C3;
+ self::Class2 c2a = f2a(){() → self::Class2};
+ self::expect(true, c2a is{ForNonNullableByDefault} self::Class2);
+ dynamic f2b = #C3;
+ dynamic c2b = f2b{dynamic}.call();
+ self::expect(true, c2b is{ForNonNullableByDefault} self::Class2);
+ self::expect(true, core::identical(f2a, f2b));
+}
+static method testArgs() → dynamic {
+ (core::int) → self::Class3 f3a = #C4;
+ self::Class3 c3a = f3a(42){(core::int) → self::Class3};
+ self::expect(42, c3a.{self::Class3::field}{core::int});
+ () → Null {
+ let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:99:8: Error: Too few positional arguments: 1 required, 0 given.
+ f3a(); // error
+ ^" in f3a{<inapplicable>}.();
+ let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:100:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f3a(42, 87); // error
+ ^" in f3a{<inapplicable>}.(42, 87);
+ };
+ dynamic f3b = #C4;
+ dynamic c3b = f3b{dynamic}.call(87);
+ self::expect(87, c3b{dynamic}.field);
+ self::throws(() → dynamic => f3b{dynamic}.call());
+ self::throws(() → dynamic => f3b{dynamic}.call(42, 87));
+ ([core::int?]) → self::Class4 f4a = #C5;
+ self::Class4 c4a = f4a(){([core::int?]) → self::Class4};
+ self::expect(null, c4a.{self::Class4::field}{core::int?});
+ self::Class4 c4b = f4a(42){([core::int?]) → self::Class4};
+ self::expect(42, c4b.{self::Class4::field}{core::int?});
+ () → Null {
+ let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:115:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f4a(42, 87); // error
+ ^" in f4a{<inapplicable>}.(42, 87);
+ };
+ dynamic f4b = #C5;
+ self::throws(() → dynamic => f4b{dynamic}.call(42, 87));
+ (core::int, [core::int?]) → self::Class5 f5a = #C6;
+ self::Class5 c5a = f5a(42){(core::int, [core::int?]) → self::Class5};
+ self::expect(42, c5a.{self::Class5::field1}{core::int});
+ self::expect(null, c5a.{self::Class5::field2}{core::int?});
+ self::Class5 c5b = f5a(87, 42){(core::int, [core::int?]) → self::Class5};
+ self::expect(87, c5b.{self::Class5::field1}{core::int});
+ self::expect(42, c5b.{self::Class5::field2}{core::int?});
+ () → Null {
+ let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:129:8: Error: Too few positional arguments: 1 required, 0 given.
+ f5a(); // error
+ ^" in f5a{<inapplicable>}.();
+ let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:130:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+Try removing the extra positional arguments.
+ f5a(42, 87, 123); // error
+ ^" in f5a{<inapplicable>}.(42, 87, 123);
+ };
+ dynamic f5b = #C6;
+ self::throws(() → dynamic => f5b{dynamic}.call());
+ self::throws(() → dynamic => f5b{dynamic}.call(42, 87, 123));
+ (core::int, {field2: core::int?, required field3: core::int}) → self::Class6 f6a = #C7;
+ self::Class6 c6a = f6a(42, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+ self::expect(42, c6a.{self::Class6::field1}{core::int});
+ self::expect(null, c6a.{self::Class6::field2}{core::int?});
+ self::expect(87, c6a.{self::Class6::field3}{core::int});
+ () → Null {
+ let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:142:8: Error: Too few positional arguments: 1 required, 0 given.
+ f6a(); // error
+ ^" in f6a{<inapplicable>}.();
+ let final Never #t7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:143:8: Error: Required named parameter 'field3' must be provided.
+ f6a(42); // error
+ ^" in f6a{<inapplicable>}.(42);
+ let final Never #t8 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:144:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f6a(42, 87); // error
+ ^" in f6a{<inapplicable>}.(42, 87);
+ let final Never #t9 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:145:8: Error: Too few positional arguments: 1 required, 0 given.
+ f6a(field1: 87, field2: 87); // error
+ ^" in f6a{<inapplicable>}.(field1: 87, field2: 87);
+ };
+ self::Class6 c6b = f6a(42, field2: 123, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+ self::expect(42, c6b.{self::Class6::field1}{core::int});
+ self::expect(123, c6b.{self::Class6::field2}{core::int?});
+ self::expect(87, c6b.{self::Class6::field3}{core::int});
+ self::Class6 c6c = f6a(87, field3: 42, field2: 123){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+ self::expect(87, c6c.{self::Class6::field1}{core::int});
+ self::expect(123, c6c.{self::Class6::field2}{core::int?});
+ self::expect(42, c6c.{self::Class6::field3}{core::int});
+ dynamic f6b = #C7;
+ self::throws(() → dynamic => f6b{dynamic}.call());
+ self::throws(() → dynamic => f6b{dynamic}.call(42), inSoundModeOnly: true);
+ self::throws(() → dynamic => f6b{dynamic}.call(42, 87), inSoundModeOnly: true);
+ self::throws(() → dynamic => f6b{dynamic}.call(field1: 87, field2: 87));
+ () → self::Class7b f7a = #C8;
+ self::Class7b c7a = f7a(){() → self::Class7b};
+ self::expect(true, c7a is{ForNonNullableByDefault} self::Class7a);
+ self::expect(true, c7a is{ForNonNullableByDefault} self::Class7b);
+ <T extends core::Object? = dynamic>() → self::Class8b<T%> f8a = #C9;
+ self::Class8b<dynamic> c8a = f8a<dynamic>(){() → self::Class8b<dynamic>};
+ self::expect(true, c8a is{ForNonNullableByDefault} self::Class8a<dynamic>);
+ self::expect(true, c8a is{ForNonNullableByDefault} self::Class8b<dynamic>);
+ self::Class8b<core::int> c8b = f8a<core::int>(){() → self::Class8b<core::int>};
+ self::expect(true, c8b is{ForNonNullableByDefault} self::Class8a<core::int>);
+ self::expect(true, c8b is{ForNonNullableByDefault} self::Class8b<core::int>);
+ self::expect(false, c8b is{ForNonNullableByDefault} self::Class8b<core::String>);
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C10}) → dynamic {
+ try {
+ f(){() → dynamic};
+ }
+ on core::Object catch(final core::Object e) {
+ core::print("Thrown: ${e}");
+ return;
+ }
+ if(!self::inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw "Expected exception";
+}
+
+constants {
+ #C1 = null
+ #C2 = static-tearoff self::Class1::_#new#tearOff
+ #C3 = static-tearoff self::Class2::_#named#tearOff
+ #C4 = static-tearoff self::Class3::_#new#tearOff
+ #C5 = static-tearoff self::Class4::_#new#tearOff
+ #C6 = static-tearoff self::Class5::_#new#tearOff
+ #C7 = static-tearoff self::Class6::_#new#tearOff
+ #C8 = static-tearoff self::Class7b::_#new#tearOff
+ #C9 = static-tearoff self::Class8b::_#new#tearOff
+ #C10 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.strong.transformed.expect
new file mode 100644
index 0000000..02a4614
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.strong.transformed.expect
@@ -0,0 +1,306 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:99:8: Error: Too few positional arguments: 1 required, 0 given.
+// f3a(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:100:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f3a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:115:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f4a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:129:8: Error: Too few positional arguments: 1 required, 0 given.
+// f5a(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:130:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+// Try removing the extra positional arguments.
+// f5a(42, 87, 123); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:142:8: Error: Too few positional arguments: 1 required, 0 given.
+// f6a(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:143:8: Error: Required named parameter 'field3' must be provided.
+// f6a(42); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:144:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f6a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:145:8: Error: Too few positional arguments: 1 required, 0 given.
+// f6a(field1: 87, field2: 87); // error
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class1::•]/*isLegacy*/;
+ constructor _() → self::Class1
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff() → self::Class1
+ return new self::Class1::_();
+ static factory •() → self::Class1
+ let Never #redirecting_factory = self::Class1::_ in invalid-expression;
+ static method _#new#tearOff() → self::Class1
+ return new self::Class1::_();
+}
+class Class2 extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class2::named]/*isLegacy*/;
+ constructor __() → self::Class2
+ : super core::Object::•()
+ ;
+ static method _#__#tearOff() → self::Class2
+ return new self::Class2::__();
+ static factory _() → self::Class2
+ return new self::Class2::__();
+ static method _#_#tearOff() → self::Class2
+ return self::Class2::_();
+ static factory named() → self::Class2
+ let () → self::Class2 #redirecting_factory = self::Class2::_ in invalid-expression;
+ static method _#named#tearOff() → self::Class2
+ return self::Class2::_();
+}
+class Class3 extends core::Object {
+ final field core::int field;
+ static final field dynamic _redirecting# = <dynamic>[self::Class3::•]/*isLegacy*/;
+ constructor _(core::int field) → self::Class3
+ : self::Class3::field = field, super core::Object::•()
+ ;
+ static method _#_#tearOff(core::int field) → self::Class3
+ return new self::Class3::_(field);
+ static factory •(core::int field) → self::Class3
+ let Never #redirecting_factory = self::Class3::_ in invalid-expression;
+ static method _#new#tearOff(core::int field) → self::Class3
+ return new self::Class3::_(field);
+}
+class Class4 extends core::Object {
+ final field core::int? field;
+ static final field dynamic _redirecting# = <dynamic>[self::Class4::•]/*isLegacy*/;
+ constructor _([core::int? field = #C1]) → self::Class4
+ : self::Class4::field = field, super core::Object::•()
+ ;
+ static method _#_#tearOff([core::int? field = #C1]) → self::Class4
+ return new self::Class4::_(field);
+ static factory •([core::int? field = #C1]) → self::Class4
+ let Never #redirecting_factory = self::Class4::_ in invalid-expression;
+ static method _#new#tearOff([core::int? field = #C1]) → self::Class4
+ return new self::Class4::_(field);
+}
+class Class5 extends core::Object {
+ final field core::int field1;
+ final field core::int? field2;
+ static final field dynamic _redirecting# = <dynamic>[self::Class5::•]/*isLegacy*/;
+ constructor _(core::int field1, [core::int? field2 = #C1]) → self::Class5
+ : self::Class5::field1 = field1, self::Class5::field2 = field2, super core::Object::•()
+ ;
+ static method _#_#tearOff(core::int field1, [core::int? field2 = #C1]) → self::Class5
+ return new self::Class5::_(field1, field2);
+ static factory •(core::int field1, [core::int? field2 = #C1]) → self::Class5
+ let Never #redirecting_factory = self::Class5::_ in invalid-expression;
+ static method _#new#tearOff(core::int field1, [core::int? field2 = #C1]) → self::Class5
+ return new self::Class5::_(field1, field2);
+}
+class Class6 extends core::Object {
+ final field core::int field1;
+ final field core::int? field2;
+ final field core::int field3;
+ static final field dynamic _redirecting# = <dynamic>[self::Class6::•]/*isLegacy*/;
+ constructor _(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+ : self::Class6::field1 = field1, self::Class6::field2 = field2, self::Class6::field3 = field3, super core::Object::•()
+ ;
+ static method _#_#tearOff(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+ return new self::Class6::_(field1, field2: field2, field3: field3);
+ static factory •(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+ let Never #redirecting_factory = self::Class6::_ in invalid-expression;
+ static method _#new#tearOff(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+ return new self::Class6::_(field1, field2: field2, field3: field3);
+}
+class Class7a extends core::Object implements self::Class7b {
+ constructor •() → self::Class7a
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff() → self::Class7a
+ return new self::Class7a::•();
+}
+class Class7b extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class7b::•]/*isLegacy*/;
+ static factory •() → self::Class7b
+ let Never #redirecting_factory = self::Class7a::• in invalid-expression;
+ static method _#new#tearOff() → self::Class7b
+ return new self::Class7a::•();
+}
+class Class8a<T extends core::Object? = dynamic> extends core::Object implements self::Class8b<self::Class8a::T%> {
+ constructor •() → self::Class8a<self::Class8a::T%>
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class8a<self::Class8a::_#new#tearOff::T%>
+ return new self::Class8a::•<self::Class8a::_#new#tearOff::T%>();
+}
+class Class8b<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class8b::•]/*isLegacy*/;
+ static factory •<T extends core::Object? = dynamic>() → self::Class8b<self::Class8b::•::T%>
+ let Never #redirecting_factory = self::Class8a::• in let self::Class8b::•::T% #typeArg0 = null in invalid-expression;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class8b<self::Class8b::_#new#tearOff::T%>
+ return new self::Class8a::•<self::Class8b::_#new#tearOff::T%>();
+}
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+ core::print("inSoundMode: ${self::inSoundMode}");
+ self::testNoArgs();
+ self::testArgs();
+}
+static method testNoArgs() → dynamic {
+ () → self::Class1 f1a = #C2;
+ self::Class1 c1a = f1a(){() → self::Class1};
+ self::expect(true, c1a is{ForNonNullableByDefault} self::Class1);
+ dynamic f1b = #C2;
+ dynamic c1b = f1b{dynamic}.call();
+ self::expect(true, c1b is{ForNonNullableByDefault} self::Class1);
+ self::expect(true, core::identical(f1a, f1b));
+ () → self::Class2 f2a = #C3;
+ self::Class2 c2a = f2a(){() → self::Class2};
+ self::expect(true, c2a is{ForNonNullableByDefault} self::Class2);
+ dynamic f2b = #C3;
+ dynamic c2b = f2b{dynamic}.call();
+ self::expect(true, c2b is{ForNonNullableByDefault} self::Class2);
+ self::expect(true, core::identical(f2a, f2b));
+}
+static method testArgs() → dynamic {
+ (core::int) → self::Class3 f3a = #C4;
+ self::Class3 c3a = f3a(42){(core::int) → self::Class3};
+ self::expect(42, c3a.{self::Class3::field}{core::int});
+ () → Null {
+ let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:99:8: Error: Too few positional arguments: 1 required, 0 given.
+ f3a(); // error
+ ^" in f3a{<inapplicable>}.();
+ let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:100:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f3a(42, 87); // error
+ ^" in f3a{<inapplicable>}.(42, 87);
+ };
+ dynamic f3b = #C4;
+ dynamic c3b = f3b{dynamic}.call(87);
+ self::expect(87, c3b{dynamic}.field);
+ self::throws(() → dynamic => f3b{dynamic}.call());
+ self::throws(() → dynamic => f3b{dynamic}.call(42, 87));
+ ([core::int?]) → self::Class4 f4a = #C5;
+ self::Class4 c4a = f4a(){([core::int?]) → self::Class4};
+ self::expect(null, c4a.{self::Class4::field}{core::int?});
+ self::Class4 c4b = f4a(42){([core::int?]) → self::Class4};
+ self::expect(42, c4b.{self::Class4::field}{core::int?});
+ () → Null {
+ let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:115:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f4a(42, 87); // error
+ ^" in f4a{<inapplicable>}.(42, 87);
+ };
+ dynamic f4b = #C5;
+ self::throws(() → dynamic => f4b{dynamic}.call(42, 87));
+ (core::int, [core::int?]) → self::Class5 f5a = #C6;
+ self::Class5 c5a = f5a(42){(core::int, [core::int?]) → self::Class5};
+ self::expect(42, c5a.{self::Class5::field1}{core::int});
+ self::expect(null, c5a.{self::Class5::field2}{core::int?});
+ self::Class5 c5b = f5a(87, 42){(core::int, [core::int?]) → self::Class5};
+ self::expect(87, c5b.{self::Class5::field1}{core::int});
+ self::expect(42, c5b.{self::Class5::field2}{core::int?});
+ () → Null {
+ let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:129:8: Error: Too few positional arguments: 1 required, 0 given.
+ f5a(); // error
+ ^" in f5a{<inapplicable>}.();
+ let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:130:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+Try removing the extra positional arguments.
+ f5a(42, 87, 123); // error
+ ^" in f5a{<inapplicable>}.(42, 87, 123);
+ };
+ dynamic f5b = #C6;
+ self::throws(() → dynamic => f5b{dynamic}.call());
+ self::throws(() → dynamic => f5b{dynamic}.call(42, 87, 123));
+ (core::int, {field2: core::int?, required field3: core::int}) → self::Class6 f6a = #C7;
+ self::Class6 c6a = f6a(42, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+ self::expect(42, c6a.{self::Class6::field1}{core::int});
+ self::expect(null, c6a.{self::Class6::field2}{core::int?});
+ self::expect(87, c6a.{self::Class6::field3}{core::int});
+ () → Null {
+ let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:142:8: Error: Too few positional arguments: 1 required, 0 given.
+ f6a(); // error
+ ^" in f6a{<inapplicable>}.();
+ let final Never #t7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:143:8: Error: Required named parameter 'field3' must be provided.
+ f6a(42); // error
+ ^" in f6a{<inapplicable>}.(42);
+ let final Never #t8 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:144:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f6a(42, 87); // error
+ ^" in f6a{<inapplicable>}.(42, 87);
+ let final Never #t9 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:145:8: Error: Too few positional arguments: 1 required, 0 given.
+ f6a(field1: 87, field2: 87); // error
+ ^" in f6a{<inapplicable>}.(field1: 87, field2: 87);
+ };
+ self::Class6 c6b = f6a(42, field2: 123, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+ self::expect(42, c6b.{self::Class6::field1}{core::int});
+ self::expect(123, c6b.{self::Class6::field2}{core::int?});
+ self::expect(87, c6b.{self::Class6::field3}{core::int});
+ self::Class6 c6c = f6a(87, field3: 42, field2: 123){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+ self::expect(87, c6c.{self::Class6::field1}{core::int});
+ self::expect(123, c6c.{self::Class6::field2}{core::int?});
+ self::expect(42, c6c.{self::Class6::field3}{core::int});
+ dynamic f6b = #C7;
+ self::throws(() → dynamic => f6b{dynamic}.call());
+ self::throws(() → dynamic => f6b{dynamic}.call(42), inSoundModeOnly: true);
+ self::throws(() → dynamic => f6b{dynamic}.call(42, 87), inSoundModeOnly: true);
+ self::throws(() → dynamic => f6b{dynamic}.call(field1: 87, field2: 87));
+ () → self::Class7b f7a = #C8;
+ self::Class7b c7a = f7a(){() → self::Class7b};
+ self::expect(true, c7a is{ForNonNullableByDefault} self::Class7a);
+ self::expect(true, c7a is{ForNonNullableByDefault} self::Class7b);
+ <T extends core::Object? = dynamic>() → self::Class8b<T%> f8a = #C9;
+ self::Class8b<dynamic> c8a = f8a<dynamic>(){() → self::Class8b<dynamic>};
+ self::expect(true, c8a is{ForNonNullableByDefault} self::Class8a<dynamic>);
+ self::expect(true, c8a is{ForNonNullableByDefault} self::Class8b<dynamic>);
+ self::Class8b<core::int> c8b = f8a<core::int>(){() → self::Class8b<core::int>};
+ self::expect(true, c8b is{ForNonNullableByDefault} self::Class8a<core::int>);
+ self::expect(true, c8b is{ForNonNullableByDefault} self::Class8b<core::int>);
+ self::expect(false, c8b is{ForNonNullableByDefault} self::Class8b<core::String>);
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C10}) → dynamic {
+ try {
+ f(){() → dynamic};
+ }
+ on core::Object catch(final core::Object e) {
+ core::print("Thrown: ${e}");
+ return;
+ }
+ if(!self::inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw "Expected exception";
+}
+
+constants {
+ #C1 = null
+ #C2 = static-tearoff self::Class1::_#new#tearOff
+ #C3 = static-tearoff self::Class2::_#named#tearOff
+ #C4 = static-tearoff self::Class3::_#new#tearOff
+ #C5 = static-tearoff self::Class4::_#new#tearOff
+ #C6 = static-tearoff self::Class5::_#new#tearOff
+ #C7 = static-tearoff self::Class6::_#new#tearOff
+ #C8 = static-tearoff self::Class7b::_#new#tearOff
+ #C9 = static-tearoff self::Class8b::_#new#tearOff
+ #C10 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.textual_outline.expect
new file mode 100644
index 0000000..2fa25d6
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.textual_outline.expect
@@ -0,0 +1,62 @@
+final bool inSoundMode = <int?>[] is! List<int>;
+main() {}
+
+class Class1 {
+ Class1._();
+ factory Class1() = Class1._;
+}
+
+class Class2 {
+ Class2.__();
+ factory Class2._() => Class2.__();
+ factory Class2.named() = Class2._;
+}
+
+testNoArgs() {}
+
+class Class3 {
+ final int field;
+ Class3._(this.field);
+ factory Class3(int field) = Class3._;
+}
+
+class Class4 {
+ final int? field;
+ Class4._([this.field]);
+ factory Class4([int? field]) = Class4._;
+}
+
+class Class5 {
+ final int field1;
+ final int? field2;
+ Class5._(this.field1, [this.field2]);
+ factory Class5(int field1, [int? field2]) = Class5._;
+}
+
+class Class6 {
+ final int field1;
+ final int? field2;
+ final int field3;
+ Class6._(this.field1, {this.field2, required this.field3});
+ factory Class6(int field1, {int? field2, required int field3}) = Class6._;
+}
+
+class Class7a implements Class7b {
+ Class7a();
+}
+
+class Class7b {
+ factory Class7b() = Class7a;
+}
+
+class Class8a<T> implements Class8b<T> {
+ Class8a();
+}
+
+class Class8b<T> {
+ factory Class8b() = Class8a<T>;
+}
+
+testArgs() {}
+expect(expected, actual) {}
+throws(Function() f, {bool inSoundModeOnly: false}) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..0500e74
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.textual_outline_modelled.expect
@@ -0,0 +1,60 @@
+class Class1 {
+ Class1._();
+ factory Class1() = Class1._;
+}
+
+class Class2 {
+ Class2.__();
+ factory Class2._() => Class2.__();
+ factory Class2.named() = Class2._;
+}
+
+class Class3 {
+ Class3._(this.field);
+ factory Class3(int field) = Class3._;
+ final int field;
+}
+
+class Class4 {
+ Class4._([this.field]);
+ factory Class4([int? field]) = Class4._;
+ final int? field;
+}
+
+class Class5 {
+ Class5._(this.field1, [this.field2]);
+ factory Class5(int field1, [int? field2]) = Class5._;
+ final int? field2;
+ final int field1;
+}
+
+class Class6 {
+ Class6._(this.field1, {this.field2, required this.field3});
+ factory Class6(int field1, {int? field2, required int field3}) = Class6._;
+ final int? field2;
+ final int field1;
+ final int field3;
+}
+
+class Class7a implements Class7b {
+ Class7a();
+}
+
+class Class7b {
+ factory Class7b() = Class7a;
+}
+
+class Class8a<T> implements Class8b<T> {
+ Class8a();
+}
+
+class Class8b<T> {
+ factory Class8b() = Class8a<T>;
+}
+
+expect(expected, actual) {}
+final bool inSoundMode = <int?>[] is! List<int>;
+main() {}
+testArgs() {}
+testNoArgs() {}
+throws(Function() f, {bool inSoundModeOnly: false}) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.weak.expect
new file mode 100644
index 0000000..a115126
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.weak.expect
@@ -0,0 +1,306 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:99:8: Error: Too few positional arguments: 1 required, 0 given.
+// f3a(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:100:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f3a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:115:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f4a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:129:8: Error: Too few positional arguments: 1 required, 0 given.
+// f5a(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:130:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+// Try removing the extra positional arguments.
+// f5a(42, 87, 123); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:142:8: Error: Too few positional arguments: 1 required, 0 given.
+// f6a(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:143:8: Error: Required named parameter 'field3' must be provided.
+// f6a(42); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:144:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f6a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:145:8: Error: Too few positional arguments: 1 required, 0 given.
+// f6a(field1: 87, field2: 87); // error
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class1::•]/*isLegacy*/;
+ constructor _() → self::Class1
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff() → self::Class1
+ return new self::Class1::_();
+ static factory •() → self::Class1
+ let dynamic #redirecting_factory = self::Class1::_ in invalid-expression;
+ static method _#new#tearOff() → self::Class1
+ return new self::Class1::_();
+}
+class Class2 extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class2::named]/*isLegacy*/;
+ constructor __() → self::Class2
+ : super core::Object::•()
+ ;
+ static method _#__#tearOff() → self::Class2
+ return new self::Class2::__();
+ static factory _() → self::Class2
+ return new self::Class2::__();
+ static method _#_#tearOff() → self::Class2
+ return self::Class2::_();
+ static factory named() → self::Class2
+ let dynamic #redirecting_factory = self::Class2::_ in invalid-expression;
+ static method _#named#tearOff() → self::Class2
+ return self::Class2::_();
+}
+class Class3 extends core::Object {
+ final field core::int field;
+ static final field dynamic _redirecting# = <dynamic>[self::Class3::•]/*isLegacy*/;
+ constructor _(core::int field) → self::Class3
+ : self::Class3::field = field, super core::Object::•()
+ ;
+ static method _#_#tearOff(core::int field) → self::Class3
+ return new self::Class3::_(field);
+ static factory •(core::int field) → self::Class3
+ let dynamic #redirecting_factory = self::Class3::_ in invalid-expression;
+ static method _#new#tearOff(core::int field) → self::Class3
+ return new self::Class3::_(field);
+}
+class Class4 extends core::Object {
+ final field core::int? field;
+ static final field dynamic _redirecting# = <dynamic>[self::Class4::•]/*isLegacy*/;
+ constructor _([core::int? field = #C1]) → self::Class4
+ : self::Class4::field = field, super core::Object::•()
+ ;
+ static method _#_#tearOff([core::int? field = #C1]) → self::Class4
+ return new self::Class4::_(field);
+ static factory •([core::int? field = #C1]) → self::Class4
+ let dynamic #redirecting_factory = self::Class4::_ in invalid-expression;
+ static method _#new#tearOff([core::int? field = #C1]) → self::Class4
+ return new self::Class4::_(field);
+}
+class Class5 extends core::Object {
+ final field core::int field1;
+ final field core::int? field2;
+ static final field dynamic _redirecting# = <dynamic>[self::Class5::•]/*isLegacy*/;
+ constructor _(core::int field1, [core::int? field2 = #C1]) → self::Class5
+ : self::Class5::field1 = field1, self::Class5::field2 = field2, super core::Object::•()
+ ;
+ static method _#_#tearOff(core::int field1, [core::int? field2 = #C1]) → self::Class5
+ return new self::Class5::_(field1, field2);
+ static factory •(core::int field1, [core::int? field2 = #C1]) → self::Class5
+ let dynamic #redirecting_factory = self::Class5::_ in invalid-expression;
+ static method _#new#tearOff(core::int field1, [core::int? field2 = #C1]) → self::Class5
+ return new self::Class5::_(field1, field2);
+}
+class Class6 extends core::Object {
+ final field core::int field1;
+ final field core::int? field2;
+ final field core::int field3;
+ static final field dynamic _redirecting# = <dynamic>[self::Class6::•]/*isLegacy*/;
+ constructor _(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+ : self::Class6::field1 = field1, self::Class6::field2 = field2, self::Class6::field3 = field3, super core::Object::•()
+ ;
+ static method _#_#tearOff(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+ return new self::Class6::_(field1, field2: field2, field3: field3);
+ static factory •(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+ let dynamic #redirecting_factory = self::Class6::_ in invalid-expression;
+ static method _#new#tearOff(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+ return new self::Class6::_(field1, field2: field2, field3: field3);
+}
+class Class7a extends core::Object implements self::Class7b {
+ constructor •() → self::Class7a
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff() → self::Class7a
+ return new self::Class7a::•();
+}
+class Class7b extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class7b::•]/*isLegacy*/;
+ static factory •() → self::Class7b
+ let dynamic #redirecting_factory = self::Class7a::• in invalid-expression;
+ static method _#new#tearOff() → self::Class7b
+ return new self::Class7a::•();
+}
+class Class8a<T extends core::Object? = dynamic> extends core::Object implements self::Class8b<self::Class8a::T%> {
+ constructor •() → self::Class8a<self::Class8a::T%>
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class8a<self::Class8a::_#new#tearOff::T%>
+ return new self::Class8a::•<self::Class8a::_#new#tearOff::T%>();
+}
+class Class8b<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class8b::•]/*isLegacy*/;
+ static factory •<T extends core::Object? = dynamic>() → self::Class8b<self::Class8b::•::T%>
+ let dynamic #redirecting_factory = self::Class8a::• in let self::Class8b::•::T% #typeArg0 = null in invalid-expression;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class8b<self::Class8b::_#new#tearOff::T%>
+ return new self::Class8a::•<self::Class8b::_#new#tearOff::T%>();
+}
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+ core::print("inSoundMode: ${self::inSoundMode}");
+ self::testNoArgs();
+ self::testArgs();
+}
+static method testNoArgs() → dynamic {
+ () → self::Class1 f1a = #C2;
+ self::Class1 c1a = f1a(){() → self::Class1};
+ self::expect(true, c1a is{ForNonNullableByDefault} self::Class1);
+ dynamic f1b = #C2;
+ dynamic c1b = f1b{dynamic}.call();
+ self::expect(true, c1b is{ForNonNullableByDefault} self::Class1);
+ self::expect(true, core::identical(f1a, f1b));
+ () → self::Class2 f2a = #C3;
+ self::Class2 c2a = f2a(){() → self::Class2};
+ self::expect(true, c2a is{ForNonNullableByDefault} self::Class2);
+ dynamic f2b = #C3;
+ dynamic c2b = f2b{dynamic}.call();
+ self::expect(true, c2b is{ForNonNullableByDefault} self::Class2);
+ self::expect(true, core::identical(f2a, f2b));
+}
+static method testArgs() → dynamic {
+ (core::int) → self::Class3 f3a = #C4;
+ self::Class3 c3a = f3a(42){(core::int) → self::Class3};
+ self::expect(42, c3a.{self::Class3::field}{core::int});
+ () → Null {
+ let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:99:8: Error: Too few positional arguments: 1 required, 0 given.
+ f3a(); // error
+ ^" in f3a{<inapplicable>}.();
+ let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:100:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f3a(42, 87); // error
+ ^" in f3a{<inapplicable>}.(42, 87);
+ };
+ dynamic f3b = #C4;
+ dynamic c3b = f3b{dynamic}.call(87);
+ self::expect(87, c3b{dynamic}.field);
+ self::throws(() → dynamic => f3b{dynamic}.call());
+ self::throws(() → dynamic => f3b{dynamic}.call(42, 87));
+ ([core::int?]) → self::Class4 f4a = #C5;
+ self::Class4 c4a = f4a(){([core::int?]) → self::Class4};
+ self::expect(null, c4a.{self::Class4::field}{core::int?});
+ self::Class4 c4b = f4a(42){([core::int?]) → self::Class4};
+ self::expect(42, c4b.{self::Class4::field}{core::int?});
+ () → Null {
+ let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:115:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f4a(42, 87); // error
+ ^" in f4a{<inapplicable>}.(42, 87);
+ };
+ dynamic f4b = #C5;
+ self::throws(() → dynamic => f4b{dynamic}.call(42, 87));
+ (core::int, [core::int?]) → self::Class5 f5a = #C6;
+ self::Class5 c5a = f5a(42){(core::int, [core::int?]) → self::Class5};
+ self::expect(42, c5a.{self::Class5::field1}{core::int});
+ self::expect(null, c5a.{self::Class5::field2}{core::int?});
+ self::Class5 c5b = f5a(87, 42){(core::int, [core::int?]) → self::Class5};
+ self::expect(87, c5b.{self::Class5::field1}{core::int});
+ self::expect(42, c5b.{self::Class5::field2}{core::int?});
+ () → Null {
+ let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:129:8: Error: Too few positional arguments: 1 required, 0 given.
+ f5a(); // error
+ ^" in f5a{<inapplicable>}.();
+ let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:130:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+Try removing the extra positional arguments.
+ f5a(42, 87, 123); // error
+ ^" in f5a{<inapplicable>}.(42, 87, 123);
+ };
+ dynamic f5b = #C6;
+ self::throws(() → dynamic => f5b{dynamic}.call());
+ self::throws(() → dynamic => f5b{dynamic}.call(42, 87, 123));
+ (core::int, {field2: core::int?, required field3: core::int}) → self::Class6 f6a = #C7;
+ self::Class6 c6a = f6a(42, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+ self::expect(42, c6a.{self::Class6::field1}{core::int});
+ self::expect(null, c6a.{self::Class6::field2}{core::int?});
+ self::expect(87, c6a.{self::Class6::field3}{core::int});
+ () → Null {
+ let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:142:8: Error: Too few positional arguments: 1 required, 0 given.
+ f6a(); // error
+ ^" in f6a{<inapplicable>}.();
+ let final Never #t7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:143:8: Error: Required named parameter 'field3' must be provided.
+ f6a(42); // error
+ ^" in f6a{<inapplicable>}.(42);
+ let final Never #t8 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:144:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f6a(42, 87); // error
+ ^" in f6a{<inapplicable>}.(42, 87);
+ let final Never #t9 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:145:8: Error: Too few positional arguments: 1 required, 0 given.
+ f6a(field1: 87, field2: 87); // error
+ ^" in f6a{<inapplicable>}.(field1: 87, field2: 87);
+ };
+ self::Class6 c6b = f6a(42, field2: 123, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+ self::expect(42, c6b.{self::Class6::field1}{core::int});
+ self::expect(123, c6b.{self::Class6::field2}{core::int?});
+ self::expect(87, c6b.{self::Class6::field3}{core::int});
+ self::Class6 c6c = f6a(87, field3: 42, field2: 123){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+ self::expect(87, c6c.{self::Class6::field1}{core::int});
+ self::expect(123, c6c.{self::Class6::field2}{core::int?});
+ self::expect(42, c6c.{self::Class6::field3}{core::int});
+ dynamic f6b = #C7;
+ self::throws(() → dynamic => f6b{dynamic}.call());
+ self::throws(() → dynamic => f6b{dynamic}.call(42), inSoundModeOnly: true);
+ self::throws(() → dynamic => f6b{dynamic}.call(42, 87), inSoundModeOnly: true);
+ self::throws(() → dynamic => f6b{dynamic}.call(field1: 87, field2: 87));
+ () → self::Class7b f7a = #C8;
+ self::Class7b c7a = f7a(){() → self::Class7b};
+ self::expect(true, c7a is{ForNonNullableByDefault} self::Class7a);
+ self::expect(true, c7a is{ForNonNullableByDefault} self::Class7b);
+ <T extends core::Object? = dynamic>() → self::Class8b<T%> f8a = #C9;
+ self::Class8b<dynamic> c8a = f8a<dynamic>(){() → self::Class8b<dynamic>};
+ self::expect(true, c8a is{ForNonNullableByDefault} self::Class8a<dynamic>);
+ self::expect(true, c8a is{ForNonNullableByDefault} self::Class8b<dynamic>);
+ self::Class8b<core::int> c8b = f8a<core::int>(){() → self::Class8b<core::int>};
+ self::expect(true, c8b is{ForNonNullableByDefault} self::Class8a<core::int>);
+ self::expect(true, c8b is{ForNonNullableByDefault} self::Class8b<core::int>);
+ self::expect(false, c8b is{ForNonNullableByDefault} self::Class8b<core::String>);
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C10}) → dynamic {
+ try {
+ f(){() → dynamic};
+ }
+ on core::Object catch(final core::Object e) {
+ core::print("Thrown: ${e}");
+ return;
+ }
+ if(!self::inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw "Expected exception";
+}
+
+constants {
+ #C1 = null
+ #C2 = static-tearoff self::Class1::_#new#tearOff
+ #C3 = static-tearoff self::Class2::_#named#tearOff
+ #C4 = static-tearoff self::Class3::_#new#tearOff
+ #C5 = static-tearoff self::Class4::_#new#tearOff
+ #C6 = static-tearoff self::Class5::_#new#tearOff
+ #C7 = static-tearoff self::Class6::_#new#tearOff
+ #C8 = static-tearoff self::Class7b::_#new#tearOff
+ #C9 = static-tearoff self::Class8b::_#new#tearOff
+ #C10 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.weak.outline.expect
new file mode 100644
index 0000000..0067daa
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.weak.outline.expect
@@ -0,0 +1,118 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class1::•]/*isLegacy*/;
+ constructor _() → self::Class1
+ ;
+ static method _#_#tearOff() → self::Class1
+ return new self::Class1::_();
+ static factory •() → self::Class1
+ let dynamic #redirecting_factory = self::Class1::_ in invalid-expression;
+ static method _#new#tearOff() → self::Class1
+ return new self::Class1::_();
+}
+class Class2 extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class2::named]/*isLegacy*/;
+ constructor __() → self::Class2
+ ;
+ static method _#__#tearOff() → self::Class2
+ return new self::Class2::__();
+ static factory _() → self::Class2
+ ;
+ static method _#_#tearOff() → self::Class2
+ return self::Class2::_();
+ static factory named() → self::Class2
+ let dynamic #redirecting_factory = self::Class2::_ in invalid-expression;
+ static method _#named#tearOff() → self::Class2
+ return self::Class2::_();
+}
+class Class3 extends core::Object {
+ final field core::int field;
+ static final field dynamic _redirecting# = <dynamic>[self::Class3::•]/*isLegacy*/;
+ constructor _(core::int field) → self::Class3
+ ;
+ static method _#_#tearOff(core::int field) → self::Class3
+ return new self::Class3::_(field);
+ static factory •(core::int field) → self::Class3
+ let dynamic #redirecting_factory = self::Class3::_ in invalid-expression;
+ static method _#new#tearOff(core::int field) → self::Class3
+ return new self::Class3::_(field);
+}
+class Class4 extends core::Object {
+ final field core::int? field;
+ static final field dynamic _redirecting# = <dynamic>[self::Class4::•]/*isLegacy*/;
+ constructor _([core::int? field]) → self::Class4
+ ;
+ static method _#_#tearOff([core::int? field]) → self::Class4
+ return new self::Class4::_(field);
+ static factory •([core::int? field]) → self::Class4
+ let dynamic #redirecting_factory = self::Class4::_ in invalid-expression;
+ static method _#new#tearOff([core::int? field]) → self::Class4
+ return new self::Class4::_(field);
+}
+class Class5 extends core::Object {
+ final field core::int field1;
+ final field core::int? field2;
+ static final field dynamic _redirecting# = <dynamic>[self::Class5::•]/*isLegacy*/;
+ constructor _(core::int field1, [core::int? field2]) → self::Class5
+ ;
+ static method _#_#tearOff(core::int field1, [core::int? field2]) → self::Class5
+ return new self::Class5::_(field1, field2);
+ static factory •(core::int field1, [core::int? field2]) → self::Class5
+ let dynamic #redirecting_factory = self::Class5::_ in invalid-expression;
+ static method _#new#tearOff(core::int field1, [core::int? field2]) → self::Class5
+ return new self::Class5::_(field1, field2);
+}
+class Class6 extends core::Object {
+ final field core::int field1;
+ final field core::int? field2;
+ final field core::int field3;
+ static final field dynamic _redirecting# = <dynamic>[self::Class6::•]/*isLegacy*/;
+ constructor _(core::int field1, {core::int? field2, required core::int field3}) → self::Class6
+ ;
+ static method _#_#tearOff(core::int field1, {core::int? field2, required core::int field3}) → self::Class6
+ return new self::Class6::_(field1, field2: field2, field3: field3);
+ static factory •(core::int field1, {core::int? field2, required core::int field3}) → self::Class6
+ let dynamic #redirecting_factory = self::Class6::_ in invalid-expression;
+ static method _#new#tearOff(core::int field1, {core::int? field2, required core::int field3}) → self::Class6
+ return new self::Class6::_(field1, field2: field2, field3: field3);
+}
+class Class7a extends core::Object implements self::Class7b {
+ constructor •() → self::Class7a
+ ;
+ static method _#new#tearOff() → self::Class7a
+ return new self::Class7a::•();
+}
+class Class7b extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class7b::•]/*isLegacy*/;
+ static factory •() → self::Class7b
+ let dynamic #redirecting_factory = self::Class7a::• in invalid-expression;
+ static method _#new#tearOff() → self::Class7b
+ return new self::Class7a::•();
+}
+class Class8a<T extends core::Object? = dynamic> extends core::Object implements self::Class8b<self::Class8a::T%> {
+ constructor •() → self::Class8a<self::Class8a::T%>
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class8a<self::Class8a::_#new#tearOff::T%>
+ return new self::Class8a::•<self::Class8a::_#new#tearOff::T%>();
+}
+class Class8b<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class8b::•]/*isLegacy*/;
+ static factory •<T extends core::Object? = dynamic>() → self::Class8b<self::Class8b::•::T%>
+ let dynamic #redirecting_factory = self::Class8a::• in let self::Class8b::•::T% #typeArg0 = null in invalid-expression;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class8b<self::Class8b::_#new#tearOff::T%>
+ return new self::Class8a::•<self::Class8b::_#new#tearOff::T%>();
+}
+static final field core::bool inSoundMode;
+static method main() → dynamic
+ ;
+static method testNoArgs() → dynamic
+ ;
+static method testArgs() → dynamic
+ ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+ ;
+static method throws(() → dynamic f, {core::bool inSoundModeOnly}) → dynamic
+ ;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.weak.transformed.expect
new file mode 100644
index 0000000..02a4614
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.weak.transformed.expect
@@ -0,0 +1,306 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:99:8: Error: Too few positional arguments: 1 required, 0 given.
+// f3a(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:100:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f3a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:115:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f4a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:129:8: Error: Too few positional arguments: 1 required, 0 given.
+// f5a(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:130:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+// Try removing the extra positional arguments.
+// f5a(42, 87, 123); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:142:8: Error: Too few positional arguments: 1 required, 0 given.
+// f6a(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:143:8: Error: Required named parameter 'field3' must be provided.
+// f6a(42); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:144:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f6a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:145:8: Error: Too few positional arguments: 1 required, 0 given.
+// f6a(field1: 87, field2: 87); // error
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class1::•]/*isLegacy*/;
+ constructor _() → self::Class1
+ : super core::Object::•()
+ ;
+ static method _#_#tearOff() → self::Class1
+ return new self::Class1::_();
+ static factory •() → self::Class1
+ let Never #redirecting_factory = self::Class1::_ in invalid-expression;
+ static method _#new#tearOff() → self::Class1
+ return new self::Class1::_();
+}
+class Class2 extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class2::named]/*isLegacy*/;
+ constructor __() → self::Class2
+ : super core::Object::•()
+ ;
+ static method _#__#tearOff() → self::Class2
+ return new self::Class2::__();
+ static factory _() → self::Class2
+ return new self::Class2::__();
+ static method _#_#tearOff() → self::Class2
+ return self::Class2::_();
+ static factory named() → self::Class2
+ let () → self::Class2 #redirecting_factory = self::Class2::_ in invalid-expression;
+ static method _#named#tearOff() → self::Class2
+ return self::Class2::_();
+}
+class Class3 extends core::Object {
+ final field core::int field;
+ static final field dynamic _redirecting# = <dynamic>[self::Class3::•]/*isLegacy*/;
+ constructor _(core::int field) → self::Class3
+ : self::Class3::field = field, super core::Object::•()
+ ;
+ static method _#_#tearOff(core::int field) → self::Class3
+ return new self::Class3::_(field);
+ static factory •(core::int field) → self::Class3
+ let Never #redirecting_factory = self::Class3::_ in invalid-expression;
+ static method _#new#tearOff(core::int field) → self::Class3
+ return new self::Class3::_(field);
+}
+class Class4 extends core::Object {
+ final field core::int? field;
+ static final field dynamic _redirecting# = <dynamic>[self::Class4::•]/*isLegacy*/;
+ constructor _([core::int? field = #C1]) → self::Class4
+ : self::Class4::field = field, super core::Object::•()
+ ;
+ static method _#_#tearOff([core::int? field = #C1]) → self::Class4
+ return new self::Class4::_(field);
+ static factory •([core::int? field = #C1]) → self::Class4
+ let Never #redirecting_factory = self::Class4::_ in invalid-expression;
+ static method _#new#tearOff([core::int? field = #C1]) → self::Class4
+ return new self::Class4::_(field);
+}
+class Class5 extends core::Object {
+ final field core::int field1;
+ final field core::int? field2;
+ static final field dynamic _redirecting# = <dynamic>[self::Class5::•]/*isLegacy*/;
+ constructor _(core::int field1, [core::int? field2 = #C1]) → self::Class5
+ : self::Class5::field1 = field1, self::Class5::field2 = field2, super core::Object::•()
+ ;
+ static method _#_#tearOff(core::int field1, [core::int? field2 = #C1]) → self::Class5
+ return new self::Class5::_(field1, field2);
+ static factory •(core::int field1, [core::int? field2 = #C1]) → self::Class5
+ let Never #redirecting_factory = self::Class5::_ in invalid-expression;
+ static method _#new#tearOff(core::int field1, [core::int? field2 = #C1]) → self::Class5
+ return new self::Class5::_(field1, field2);
+}
+class Class6 extends core::Object {
+ final field core::int field1;
+ final field core::int? field2;
+ final field core::int field3;
+ static final field dynamic _redirecting# = <dynamic>[self::Class6::•]/*isLegacy*/;
+ constructor _(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+ : self::Class6::field1 = field1, self::Class6::field2 = field2, self::Class6::field3 = field3, super core::Object::•()
+ ;
+ static method _#_#tearOff(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+ return new self::Class6::_(field1, field2: field2, field3: field3);
+ static factory •(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+ let Never #redirecting_factory = self::Class6::_ in invalid-expression;
+ static method _#new#tearOff(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+ return new self::Class6::_(field1, field2: field2, field3: field3);
+}
+class Class7a extends core::Object implements self::Class7b {
+ constructor •() → self::Class7a
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff() → self::Class7a
+ return new self::Class7a::•();
+}
+class Class7b extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class7b::•]/*isLegacy*/;
+ static factory •() → self::Class7b
+ let Never #redirecting_factory = self::Class7a::• in invalid-expression;
+ static method _#new#tearOff() → self::Class7b
+ return new self::Class7a::•();
+}
+class Class8a<T extends core::Object? = dynamic> extends core::Object implements self::Class8b<self::Class8a::T%> {
+ constructor •() → self::Class8a<self::Class8a::T%>
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class8a<self::Class8a::_#new#tearOff::T%>
+ return new self::Class8a::•<self::Class8a::_#new#tearOff::T%>();
+}
+class Class8b<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class8b::•]/*isLegacy*/;
+ static factory •<T extends core::Object? = dynamic>() → self::Class8b<self::Class8b::•::T%>
+ let Never #redirecting_factory = self::Class8a::• in let self::Class8b::•::T% #typeArg0 = null in invalid-expression;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class8b<self::Class8b::_#new#tearOff::T%>
+ return new self::Class8a::•<self::Class8b::_#new#tearOff::T%>();
+}
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+ core::print("inSoundMode: ${self::inSoundMode}");
+ self::testNoArgs();
+ self::testArgs();
+}
+static method testNoArgs() → dynamic {
+ () → self::Class1 f1a = #C2;
+ self::Class1 c1a = f1a(){() → self::Class1};
+ self::expect(true, c1a is{ForNonNullableByDefault} self::Class1);
+ dynamic f1b = #C2;
+ dynamic c1b = f1b{dynamic}.call();
+ self::expect(true, c1b is{ForNonNullableByDefault} self::Class1);
+ self::expect(true, core::identical(f1a, f1b));
+ () → self::Class2 f2a = #C3;
+ self::Class2 c2a = f2a(){() → self::Class2};
+ self::expect(true, c2a is{ForNonNullableByDefault} self::Class2);
+ dynamic f2b = #C3;
+ dynamic c2b = f2b{dynamic}.call();
+ self::expect(true, c2b is{ForNonNullableByDefault} self::Class2);
+ self::expect(true, core::identical(f2a, f2b));
+}
+static method testArgs() → dynamic {
+ (core::int) → self::Class3 f3a = #C4;
+ self::Class3 c3a = f3a(42){(core::int) → self::Class3};
+ self::expect(42, c3a.{self::Class3::field}{core::int});
+ () → Null {
+ let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:99:8: Error: Too few positional arguments: 1 required, 0 given.
+ f3a(); // error
+ ^" in f3a{<inapplicable>}.();
+ let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:100:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f3a(42, 87); // error
+ ^" in f3a{<inapplicable>}.(42, 87);
+ };
+ dynamic f3b = #C4;
+ dynamic c3b = f3b{dynamic}.call(87);
+ self::expect(87, c3b{dynamic}.field);
+ self::throws(() → dynamic => f3b{dynamic}.call());
+ self::throws(() → dynamic => f3b{dynamic}.call(42, 87));
+ ([core::int?]) → self::Class4 f4a = #C5;
+ self::Class4 c4a = f4a(){([core::int?]) → self::Class4};
+ self::expect(null, c4a.{self::Class4::field}{core::int?});
+ self::Class4 c4b = f4a(42){([core::int?]) → self::Class4};
+ self::expect(42, c4b.{self::Class4::field}{core::int?});
+ () → Null {
+ let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:115:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f4a(42, 87); // error
+ ^" in f4a{<inapplicable>}.(42, 87);
+ };
+ dynamic f4b = #C5;
+ self::throws(() → dynamic => f4b{dynamic}.call(42, 87));
+ (core::int, [core::int?]) → self::Class5 f5a = #C6;
+ self::Class5 c5a = f5a(42){(core::int, [core::int?]) → self::Class5};
+ self::expect(42, c5a.{self::Class5::field1}{core::int});
+ self::expect(null, c5a.{self::Class5::field2}{core::int?});
+ self::Class5 c5b = f5a(87, 42){(core::int, [core::int?]) → self::Class5};
+ self::expect(87, c5b.{self::Class5::field1}{core::int});
+ self::expect(42, c5b.{self::Class5::field2}{core::int?});
+ () → Null {
+ let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:129:8: Error: Too few positional arguments: 1 required, 0 given.
+ f5a(); // error
+ ^" in f5a{<inapplicable>}.();
+ let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:130:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+Try removing the extra positional arguments.
+ f5a(42, 87, 123); // error
+ ^" in f5a{<inapplicable>}.(42, 87, 123);
+ };
+ dynamic f5b = #C6;
+ self::throws(() → dynamic => f5b{dynamic}.call());
+ self::throws(() → dynamic => f5b{dynamic}.call(42, 87, 123));
+ (core::int, {field2: core::int?, required field3: core::int}) → self::Class6 f6a = #C7;
+ self::Class6 c6a = f6a(42, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+ self::expect(42, c6a.{self::Class6::field1}{core::int});
+ self::expect(null, c6a.{self::Class6::field2}{core::int?});
+ self::expect(87, c6a.{self::Class6::field3}{core::int});
+ () → Null {
+ let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:142:8: Error: Too few positional arguments: 1 required, 0 given.
+ f6a(); // error
+ ^" in f6a{<inapplicable>}.();
+ let final Never #t7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:143:8: Error: Required named parameter 'field3' must be provided.
+ f6a(42); // error
+ ^" in f6a{<inapplicable>}.(42);
+ let final Never #t8 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:144:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f6a(42, 87); // error
+ ^" in f6a{<inapplicable>}.(42, 87);
+ let final Never #t9 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:145:8: Error: Too few positional arguments: 1 required, 0 given.
+ f6a(field1: 87, field2: 87); // error
+ ^" in f6a{<inapplicable>}.(field1: 87, field2: 87);
+ };
+ self::Class6 c6b = f6a(42, field2: 123, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+ self::expect(42, c6b.{self::Class6::field1}{core::int});
+ self::expect(123, c6b.{self::Class6::field2}{core::int?});
+ self::expect(87, c6b.{self::Class6::field3}{core::int});
+ self::Class6 c6c = f6a(87, field3: 42, field2: 123){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+ self::expect(87, c6c.{self::Class6::field1}{core::int});
+ self::expect(123, c6c.{self::Class6::field2}{core::int?});
+ self::expect(42, c6c.{self::Class6::field3}{core::int});
+ dynamic f6b = #C7;
+ self::throws(() → dynamic => f6b{dynamic}.call());
+ self::throws(() → dynamic => f6b{dynamic}.call(42), inSoundModeOnly: true);
+ self::throws(() → dynamic => f6b{dynamic}.call(42, 87), inSoundModeOnly: true);
+ self::throws(() → dynamic => f6b{dynamic}.call(field1: 87, field2: 87));
+ () → self::Class7b f7a = #C8;
+ self::Class7b c7a = f7a(){() → self::Class7b};
+ self::expect(true, c7a is{ForNonNullableByDefault} self::Class7a);
+ self::expect(true, c7a is{ForNonNullableByDefault} self::Class7b);
+ <T extends core::Object? = dynamic>() → self::Class8b<T%> f8a = #C9;
+ self::Class8b<dynamic> c8a = f8a<dynamic>(){() → self::Class8b<dynamic>};
+ self::expect(true, c8a is{ForNonNullableByDefault} self::Class8a<dynamic>);
+ self::expect(true, c8a is{ForNonNullableByDefault} self::Class8b<dynamic>);
+ self::Class8b<core::int> c8b = f8a<core::int>(){() → self::Class8b<core::int>};
+ self::expect(true, c8b is{ForNonNullableByDefault} self::Class8a<core::int>);
+ self::expect(true, c8b is{ForNonNullableByDefault} self::Class8b<core::int>);
+ self::expect(false, c8b is{ForNonNullableByDefault} self::Class8b<core::String>);
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C10}) → dynamic {
+ try {
+ f(){() → dynamic};
+ }
+ on core::Object catch(final core::Object e) {
+ core::print("Thrown: ${e}");
+ return;
+ }
+ if(!self::inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw "Expected exception";
+}
+
+constants {
+ #C1 = null
+ #C2 = static-tearoff self::Class1::_#new#tearOff
+ #C3 = static-tearoff self::Class2::_#named#tearOff
+ #C4 = static-tearoff self::Class3::_#new#tearOff
+ #C5 = static-tearoff self::Class4::_#new#tearOff
+ #C6 = static-tearoff self::Class5::_#new#tearOff
+ #C7 = static-tearoff self::Class6::_#new#tearOff
+ #C8 = static-tearoff self::Class7b::_#new#tearOff
+ #C9 = static-tearoff self::Class8b::_#new#tearOff
+ #C10 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart
new file mode 100644
index 0000000..ef380c5
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart
@@ -0,0 +1,75 @@
+// 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.
+
+final bool inSoundMode = <int?>[] is! List<int>;
+
+main() {
+ print('inSoundMode: $inSoundMode');
+ testDefaultValues();
+}
+
+class Class1 {
+ final int field;
+
+ Class1._([this.field = 42]);
+ factory Class1([int field]) = Class1._;
+}
+
+class Class2 {
+ final int field;
+
+ Class2._({this.field: 42});
+ factory Class2({int field}) = Class2._;
+}
+
+void testDefaultValues() {
+ var f1a = Class1.new;
+ var c1a = f1a();
+ expect(42, c1a.field);
+ var c1b = f1a(87);
+ expect(87, c1b.field);
+ () {
+ f1a(42, 87); // error
+ };
+
+ dynamic f1b = Class1.new;
+ var c1c = f1b();
+ expect(42, c1c.field);
+ var c1d = f1b(87);
+ expect(87, c1d.field);
+ throws(() => f1b(42, 87));
+
+ var f2a = Class2.new;
+ var c2a = f2a();
+ expect(42, c2a.field);
+ var c2b = f2a(field: 87);
+ expect(87, c2b.field);
+ () {
+ f2a(87); // error
+ };
+
+ dynamic f2b = Class2.new;
+ var c2c = f2b();
+ expect(42, c2c.field);
+ var c2d = f2b(field: 87);
+ expect(87, c2d.field);
+ throws(() => f2b(87));
+}
+
+expect(expected, actual) {
+ if (expected != actual) throw 'Expected $expected, actual $actual';
+}
+
+throws(Function() f, {bool inSoundModeOnly: false}) {
+ try {
+ f();
+ } catch (e) {
+ print('Thrown: $e');
+ return;
+ }
+ if (!inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw 'Expected exception';
+}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart.strong.expect
new file mode 100644
index 0000000..873e7a9
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart.strong.expect
@@ -0,0 +1,109 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart:33:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f1a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart:49:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+// f2a(87); // error
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+ final field core::int field;
+ static final field dynamic _redirecting# = <dynamic>[self::Class1::•]/*isLegacy*/;
+ constructor _([core::int field = #C1]) → self::Class1
+ : self::Class1::field = field, super core::Object::•()
+ ;
+ static method _#_#tearOff([core::int field = #C1]) → self::Class1
+ return new self::Class1::_(field);
+ static factory •([core::int field = #C2]) → self::Class1
+ let dynamic #redirecting_factory = self::Class1::_ in invalid-expression;
+ static method _#new#tearOff([core::int field = #C1]) → self::Class1
+ return new self::Class1::_(field);
+}
+class Class2 extends core::Object {
+ final field core::int field;
+ static final field dynamic _redirecting# = <dynamic>[self::Class2::•]/*isLegacy*/;
+ constructor _({core::int field = #C1}) → self::Class2
+ : self::Class2::field = field, super core::Object::•()
+ ;
+ static method _#_#tearOff({core::int field = #C1}) → self::Class2
+ return new self::Class2::_(field: field);
+ static factory •({core::int field = #C2}) → self::Class2
+ let dynamic #redirecting_factory = self::Class2::_ in invalid-expression;
+ static method _#new#tearOff({core::int field = #C1}) → self::Class2
+ return new self::Class2::_(field: field);
+}
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+ core::print("inSoundMode: ${self::inSoundMode}");
+ self::testDefaultValues();
+}
+static method testDefaultValues() → void {
+ ([core::int]) → self::Class1 f1a = #C3;
+ self::Class1 c1a = f1a(){([core::int]) → self::Class1};
+ self::expect(42, c1a.{self::Class1::field}{core::int});
+ self::Class1 c1b = f1a(87){([core::int]) → self::Class1};
+ self::expect(87, c1b.{self::Class1::field}{core::int});
+ () → Null {
+ let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart:33:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f1a(42, 87); // error
+ ^" in f1a{<inapplicable>}.(42, 87);
+ };
+ dynamic f1b = #C3;
+ dynamic c1c = f1b{dynamic}.call();
+ self::expect(42, c1c{dynamic}.field);
+ dynamic c1d = f1b{dynamic}.call(87);
+ self::expect(87, c1d{dynamic}.field);
+ self::throws(() → dynamic => f1b{dynamic}.call(42, 87));
+ ({field: core::int}) → self::Class2 f2a = #C4;
+ self::Class2 c2a = f2a(){({field: core::int}) → self::Class2};
+ self::expect(42, c2a.{self::Class2::field}{core::int});
+ self::Class2 c2b = f2a(field: 87){({field: core::int}) → self::Class2};
+ self::expect(87, c2b.{self::Class2::field}{core::int});
+ () → Null {
+ let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart:49:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+ f2a(87); // error
+ ^" in f2a{<inapplicable>}.(87);
+ };
+ dynamic f2b = #C4;
+ dynamic c2c = f2b{dynamic}.call();
+ self::expect(42, c2c{dynamic}.field);
+ dynamic c2d = f2b{dynamic}.call(field: 87);
+ self::expect(87, c2d{dynamic}.field);
+ self::throws(() → dynamic => f2b{dynamic}.call(87));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C5}) → dynamic {
+ try {
+ f(){() → dynamic};
+ }
+ on core::Object catch(final core::Object e) {
+ core::print("Thrown: ${e}");
+ return;
+ }
+ if(!self::inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw "Expected exception";
+}
+
+constants {
+ #C1 = 42
+ #C2 = null
+ #C3 = static-tearoff self::Class1::_#new#tearOff
+ #C4 = static-tearoff self::Class2::_#new#tearOff
+ #C5 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart.strong.transformed.expect
new file mode 100644
index 0000000..fe92fac
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart.strong.transformed.expect
@@ -0,0 +1,109 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart:33:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f1a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart:49:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+// f2a(87); // error
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+ final field core::int field;
+ static final field dynamic _redirecting# = <dynamic>[self::Class1::•]/*isLegacy*/;
+ constructor _([core::int field = #C1]) → self::Class1
+ : self::Class1::field = field, super core::Object::•()
+ ;
+ static method _#_#tearOff([core::int field = #C1]) → self::Class1
+ return new self::Class1::_(field);
+ static factory •([core::int field = #C2]) → self::Class1
+ let Never #redirecting_factory = self::Class1::_ in invalid-expression;
+ static method _#new#tearOff([core::int field = #C1]) → self::Class1
+ return new self::Class1::_(field);
+}
+class Class2 extends core::Object {
+ final field core::int field;
+ static final field dynamic _redirecting# = <dynamic>[self::Class2::•]/*isLegacy*/;
+ constructor _({core::int field = #C1}) → self::Class2
+ : self::Class2::field = field, super core::Object::•()
+ ;
+ static method _#_#tearOff({core::int field = #C1}) → self::Class2
+ return new self::Class2::_(field: field);
+ static factory •({core::int field = #C2}) → self::Class2
+ let Never #redirecting_factory = self::Class2::_ in invalid-expression;
+ static method _#new#tearOff({core::int field = #C1}) → self::Class2
+ return new self::Class2::_(field: field);
+}
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+ core::print("inSoundMode: ${self::inSoundMode}");
+ self::testDefaultValues();
+}
+static method testDefaultValues() → void {
+ ([core::int]) → self::Class1 f1a = #C3;
+ self::Class1 c1a = f1a(){([core::int]) → self::Class1};
+ self::expect(42, c1a.{self::Class1::field}{core::int});
+ self::Class1 c1b = f1a(87){([core::int]) → self::Class1};
+ self::expect(87, c1b.{self::Class1::field}{core::int});
+ () → Null {
+ let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart:33:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f1a(42, 87); // error
+ ^" in f1a{<inapplicable>}.(42, 87);
+ };
+ dynamic f1b = #C3;
+ dynamic c1c = f1b{dynamic}.call();
+ self::expect(42, c1c{dynamic}.field);
+ dynamic c1d = f1b{dynamic}.call(87);
+ self::expect(87, c1d{dynamic}.field);
+ self::throws(() → dynamic => f1b{dynamic}.call(42, 87));
+ ({field: core::int}) → self::Class2 f2a = #C4;
+ self::Class2 c2a = f2a(){({field: core::int}) → self::Class2};
+ self::expect(42, c2a.{self::Class2::field}{core::int});
+ self::Class2 c2b = f2a(field: 87){({field: core::int}) → self::Class2};
+ self::expect(87, c2b.{self::Class2::field}{core::int});
+ () → Null {
+ let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart:49:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+ f2a(87); // error
+ ^" in f2a{<inapplicable>}.(87);
+ };
+ dynamic f2b = #C4;
+ dynamic c2c = f2b{dynamic}.call();
+ self::expect(42, c2c{dynamic}.field);
+ dynamic c2d = f2b{dynamic}.call(field: 87);
+ self::expect(87, c2d{dynamic}.field);
+ self::throws(() → dynamic => f2b{dynamic}.call(87));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C5}) → dynamic {
+ try {
+ f(){() → dynamic};
+ }
+ on core::Object catch(final core::Object e) {
+ core::print("Thrown: ${e}");
+ return;
+ }
+ if(!self::inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw "Expected exception";
+}
+
+constants {
+ #C1 = 42
+ #C2 = null
+ #C3 = static-tearoff self::Class1::_#new#tearOff
+ #C4 = static-tearoff self::Class2::_#new#tearOff
+ #C5 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart.textual_outline.expect
new file mode 100644
index 0000000..1194776
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart.textual_outline.expect
@@ -0,0 +1,18 @@
+final bool inSoundMode = <int?>[] is! List<int>;
+main() {}
+
+class Class1 {
+ final int field;
+ Class1._([this.field = 42]);
+ factory Class1([int field]) = Class1._;
+}
+
+class Class2 {
+ final int field;
+ Class2._({this.field: 42});
+ factory Class2({int field}) = Class2._;
+}
+
+void testDefaultValues() {}
+expect(expected, actual) {}
+throws(Function() f, {bool inSoundModeOnly: false}) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..c51e203
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart.textual_outline_modelled.expect
@@ -0,0 +1,17 @@
+class Class1 {
+ Class1._([this.field = 42]);
+ factory Class1([int field]) = Class1._;
+ final int field;
+}
+
+class Class2 {
+ Class2._({this.field: 42});
+ factory Class2({int field}) = Class2._;
+ final int field;
+}
+
+expect(expected, actual) {}
+final bool inSoundMode = <int?>[] is! List<int>;
+main() {}
+throws(Function() f, {bool inSoundModeOnly: false}) {}
+void testDefaultValues() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart.weak.expect
new file mode 100644
index 0000000..873e7a9
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart.weak.expect
@@ -0,0 +1,109 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart:33:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f1a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart:49:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+// f2a(87); // error
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+ final field core::int field;
+ static final field dynamic _redirecting# = <dynamic>[self::Class1::•]/*isLegacy*/;
+ constructor _([core::int field = #C1]) → self::Class1
+ : self::Class1::field = field, super core::Object::•()
+ ;
+ static method _#_#tearOff([core::int field = #C1]) → self::Class1
+ return new self::Class1::_(field);
+ static factory •([core::int field = #C2]) → self::Class1
+ let dynamic #redirecting_factory = self::Class1::_ in invalid-expression;
+ static method _#new#tearOff([core::int field = #C1]) → self::Class1
+ return new self::Class1::_(field);
+}
+class Class2 extends core::Object {
+ final field core::int field;
+ static final field dynamic _redirecting# = <dynamic>[self::Class2::•]/*isLegacy*/;
+ constructor _({core::int field = #C1}) → self::Class2
+ : self::Class2::field = field, super core::Object::•()
+ ;
+ static method _#_#tearOff({core::int field = #C1}) → self::Class2
+ return new self::Class2::_(field: field);
+ static factory •({core::int field = #C2}) → self::Class2
+ let dynamic #redirecting_factory = self::Class2::_ in invalid-expression;
+ static method _#new#tearOff({core::int field = #C1}) → self::Class2
+ return new self::Class2::_(field: field);
+}
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+ core::print("inSoundMode: ${self::inSoundMode}");
+ self::testDefaultValues();
+}
+static method testDefaultValues() → void {
+ ([core::int]) → self::Class1 f1a = #C3;
+ self::Class1 c1a = f1a(){([core::int]) → self::Class1};
+ self::expect(42, c1a.{self::Class1::field}{core::int});
+ self::Class1 c1b = f1a(87){([core::int]) → self::Class1};
+ self::expect(87, c1b.{self::Class1::field}{core::int});
+ () → Null {
+ let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart:33:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f1a(42, 87); // error
+ ^" in f1a{<inapplicable>}.(42, 87);
+ };
+ dynamic f1b = #C3;
+ dynamic c1c = f1b{dynamic}.call();
+ self::expect(42, c1c{dynamic}.field);
+ dynamic c1d = f1b{dynamic}.call(87);
+ self::expect(87, c1d{dynamic}.field);
+ self::throws(() → dynamic => f1b{dynamic}.call(42, 87));
+ ({field: core::int}) → self::Class2 f2a = #C4;
+ self::Class2 c2a = f2a(){({field: core::int}) → self::Class2};
+ self::expect(42, c2a.{self::Class2::field}{core::int});
+ self::Class2 c2b = f2a(field: 87){({field: core::int}) → self::Class2};
+ self::expect(87, c2b.{self::Class2::field}{core::int});
+ () → Null {
+ let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart:49:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+ f2a(87); // error
+ ^" in f2a{<inapplicable>}.(87);
+ };
+ dynamic f2b = #C4;
+ dynamic c2c = f2b{dynamic}.call();
+ self::expect(42, c2c{dynamic}.field);
+ dynamic c2d = f2b{dynamic}.call(field: 87);
+ self::expect(87, c2d{dynamic}.field);
+ self::throws(() → dynamic => f2b{dynamic}.call(87));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C5}) → dynamic {
+ try {
+ f(){() → dynamic};
+ }
+ on core::Object catch(final core::Object e) {
+ core::print("Thrown: ${e}");
+ return;
+ }
+ if(!self::inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw "Expected exception";
+}
+
+constants {
+ #C1 = 42
+ #C2 = null
+ #C3 = static-tearoff self::Class1::_#new#tearOff
+ #C4 = static-tearoff self::Class2::_#new#tearOff
+ #C5 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart.weak.outline.expect
new file mode 100644
index 0000000..e6fbbd5
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart.weak.outline.expect
@@ -0,0 +1,37 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+ final field core::int field;
+ static final field dynamic _redirecting# = <dynamic>[self::Class1::•]/*isLegacy*/;
+ constructor _([core::int field]) → self::Class1
+ ;
+ static method _#_#tearOff([core::int field]) → self::Class1
+ return new self::Class1::_(field);
+ static factory •([core::int field]) → self::Class1
+ let dynamic #redirecting_factory = self::Class1::_ in invalid-expression;
+ static method _#new#tearOff([core::int field]) → self::Class1
+ return new self::Class1::_(field);
+}
+class Class2 extends core::Object {
+ final field core::int field;
+ static final field dynamic _redirecting# = <dynamic>[self::Class2::•]/*isLegacy*/;
+ constructor _({core::int field}) → self::Class2
+ ;
+ static method _#_#tearOff({core::int field}) → self::Class2
+ return new self::Class2::_(field: field);
+ static factory •({core::int field}) → self::Class2
+ let dynamic #redirecting_factory = self::Class2::_ in invalid-expression;
+ static method _#new#tearOff({core::int field}) → self::Class2
+ return new self::Class2::_(field: field);
+}
+static final field core::bool inSoundMode;
+static method main() → dynamic
+ ;
+static method testDefaultValues() → void
+ ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+ ;
+static method throws(() → dynamic f, {core::bool inSoundModeOnly}) → dynamic
+ ;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart.weak.transformed.expect
new file mode 100644
index 0000000..fe92fac
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart.weak.transformed.expect
@@ -0,0 +1,109 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart:33:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f1a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart:49:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+// f2a(87); // error
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+ final field core::int field;
+ static final field dynamic _redirecting# = <dynamic>[self::Class1::•]/*isLegacy*/;
+ constructor _([core::int field = #C1]) → self::Class1
+ : self::Class1::field = field, super core::Object::•()
+ ;
+ static method _#_#tearOff([core::int field = #C1]) → self::Class1
+ return new self::Class1::_(field);
+ static factory •([core::int field = #C2]) → self::Class1
+ let Never #redirecting_factory = self::Class1::_ in invalid-expression;
+ static method _#new#tearOff([core::int field = #C1]) → self::Class1
+ return new self::Class1::_(field);
+}
+class Class2 extends core::Object {
+ final field core::int field;
+ static final field dynamic _redirecting# = <dynamic>[self::Class2::•]/*isLegacy*/;
+ constructor _({core::int field = #C1}) → self::Class2
+ : self::Class2::field = field, super core::Object::•()
+ ;
+ static method _#_#tearOff({core::int field = #C1}) → self::Class2
+ return new self::Class2::_(field: field);
+ static factory •({core::int field = #C2}) → self::Class2
+ let Never #redirecting_factory = self::Class2::_ in invalid-expression;
+ static method _#new#tearOff({core::int field = #C1}) → self::Class2
+ return new self::Class2::_(field: field);
+}
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+ core::print("inSoundMode: ${self::inSoundMode}");
+ self::testDefaultValues();
+}
+static method testDefaultValues() → void {
+ ([core::int]) → self::Class1 f1a = #C3;
+ self::Class1 c1a = f1a(){([core::int]) → self::Class1};
+ self::expect(42, c1a.{self::Class1::field}{core::int});
+ self::Class1 c1b = f1a(87){([core::int]) → self::Class1};
+ self::expect(87, c1b.{self::Class1::field}{core::int});
+ () → Null {
+ let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart:33:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f1a(42, 87); // error
+ ^" in f1a{<inapplicable>}.(42, 87);
+ };
+ dynamic f1b = #C3;
+ dynamic c1c = f1b{dynamic}.call();
+ self::expect(42, c1c{dynamic}.field);
+ dynamic c1d = f1b{dynamic}.call(87);
+ self::expect(87, c1d{dynamic}.field);
+ self::throws(() → dynamic => f1b{dynamic}.call(42, 87));
+ ({field: core::int}) → self::Class2 f2a = #C4;
+ self::Class2 c2a = f2a(){({field: core::int}) → self::Class2};
+ self::expect(42, c2a.{self::Class2::field}{core::int});
+ self::Class2 c2b = f2a(field: 87){({field: core::int}) → self::Class2};
+ self::expect(87, c2b.{self::Class2::field}{core::int});
+ () → Null {
+ let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values.dart:49:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+ f2a(87); // error
+ ^" in f2a{<inapplicable>}.(87);
+ };
+ dynamic f2b = #C4;
+ dynamic c2c = f2b{dynamic}.call();
+ self::expect(42, c2c{dynamic}.field);
+ dynamic c2d = f2b{dynamic}.call(field: 87);
+ self::expect(87, c2d{dynamic}.field);
+ self::throws(() → dynamic => f2b{dynamic}.call(87));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C5}) → dynamic {
+ try {
+ f(){() → dynamic};
+ }
+ on core::Object catch(final core::Object e) {
+ core::print("Thrown: ${e}");
+ return;
+ }
+ if(!self::inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw "Expected exception";
+}
+
+constants {
+ #C1 = 42
+ #C2 = null
+ #C3 = static-tearoff self::Class1::_#new#tearOff
+ #C4 = static-tearoff self::Class2::_#new#tearOff
+ #C5 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart
new file mode 100644
index 0000000..605ae05
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart
@@ -0,0 +1,152 @@
+// 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.
+
+final bool inSoundMode = <int?>[] is! List<int>;
+
+main() {
+ print('inSoundMode: $inSoundMode');
+ testDefaultValues();
+}
+
+class Class1 {
+ final int field1;
+ final int field2;
+
+ Class1.positional([this.field1 = 1, this.field2 = 2]);
+
+ factory Class1.redirectPositionalSame([int field1, int field2]) =
+ Class1.positional;
+
+ factory Class1.redirectPositionalFewer1([int field1]) = Class1.positional;
+
+ factory Class1.redirectPositionalFewer2() = Class1.positional;
+
+ Class1.named({this.field1 = 1, this.field2 = 2});
+
+ factory Class1.redirectNamedSame({int field1, int field2}) = Class1.named;
+
+ factory Class1.redirectNamedReorder({int field2, int field1}) = Class1.named;
+
+ factory Class1.redirectNamedFewer1({int field1}) = Class1.named;
+
+ factory Class1.redirectNamedFewer2({int field2}) = Class1.named;
+
+ factory Class1.redirectNamedFewer3() = Class1.named;
+}
+
+testDefaultValues() {
+ var f1a = Class1.redirectPositionalSame;
+ var c1a = f1a();
+ expect(1, c1a.field1);
+ expect(2, c1a.field2);
+ var c1b = f1a(42);
+ expect(42, c1b.field1);
+ expect(2, c1b.field2);
+ var c1c = f1a(42, 87);
+ expect(42, c1c.field1);
+ expect(87, c1c.field2);
+
+ var f1b = Class1.redirectPositionalFewer1;
+ var c1d = f1b();
+ expect(1, c1d.field1);
+ expect(2, c1d.field2);
+ var c1e = f1b(42);
+ expect(42, c1e.field1);
+ expect(2, c1e.field2);
+ () {
+ f1b(42, 87); // error
+ };
+
+ var f1c = Class1.redirectPositionalFewer2;
+ var c1f = f1c();
+ expect(1, c1f.field1);
+ expect(2, c1f.field2);
+ () {
+ f1c(42); // error
+ f1c(42, 87); // error
+ };
+
+ var f2a = Class1.redirectNamedSame;
+ var c2a = f2a();
+ expect(1, c2a.field1);
+ expect(2, c2a.field2);
+ var c2b = f2a(field1: 42);
+ expect(42, c2b.field1);
+ expect(2, c2b.field2);
+ var c2c = f2a(field1: 42, field2: 87);
+ expect(42, c2c.field1);
+ expect(87, c2c.field2);
+ var c2d = f2a(field2: 87);
+ expect(1, c2d.field1);
+ expect(87, c2d.field2);
+ var c2e = f2a(field2: 87, field1: 42);
+ expect(42, c2e.field1);
+ expect(87, c2e.field2);
+
+ var f2b = Class1.redirectNamedReorder;
+ var c3a = f2b();
+ expect(1, c3a.field1);
+ expect(2, c3a.field2);
+ var c3b = f2b(field1: 42);
+ expect(42, c3b.field1);
+ expect(2, c3b.field2);
+ var c3c = f2b(field1: 42, field2: 87);
+ expect(42, c3c.field1);
+ expect(87, c3c.field2);
+ var c3d = f2b(field2: 87);
+ expect(1, c3d.field1);
+ expect(87, c3d.field2);
+ var c3e = f2b(field2: 87, field1: 42);
+ expect(42, c3e.field1);
+ expect(87, c3e.field2);
+
+ var f2c = Class1.redirectNamedFewer1;
+ var c4a = f2c();
+ expect(1, c4a.field1);
+ expect(2, c4a.field2);
+ var c4b = f2c(field1: 42);
+ expect(42, c4b.field1);
+ expect(2, c4b.field2);
+ () {
+ f2c(field1: 42, field2: 87); // error
+ };
+
+ var f2d = Class1.redirectNamedFewer2;
+ var c5a = f2d();
+ expect(1, c5a.field1);
+ expect(2, c5a.field2);
+ var c5b = f2d(field2: 87);
+ expect(1, c5b.field1);
+ expect(87, c5b.field2);
+ () {
+ f2d(field1: 42, field2: 87); // error
+ };
+
+ var f2e = Class1.redirectNamedFewer3;
+ var c6a = f2e();
+ expect(1, c6a.field1);
+ expect(2, c6a.field2);
+ () {
+ f2e(field1: 42); // error
+ f2e(field2: 87); // error
+ f2e(field1: 42, field2: 87); // error
+ };
+}
+
+expect(expected, actual) {
+ if (expected != actual) throw 'Expected $expected, actual $actual';
+}
+
+throws(Function() f, {bool inSoundModeOnly: false}) {
+ try {
+ f();
+ } catch (e) {
+ print('Thrown: $e');
+ return;
+ }
+ if (!inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw 'Expected exception';
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart.strong.expect
new file mode 100644
index 0000000..6d9d205
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart.strong.expect
@@ -0,0 +1,236 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:58:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f1b(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:66:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+// f1c(42); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:67:8: Error: Too many positional arguments: 0 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f1c(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:112:21: Error: No named parameter with the name 'field2'.
+// f2c(field1: 42, field2: 87); // error
+// ^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:123:9: Error: No named parameter with the name 'field1'.
+// f2d(field1: 42, field2: 87); // error
+// ^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:131:9: Error: No named parameter with the name 'field1'.
+// f2e(field1: 42); // error
+// ^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:132:9: Error: No named parameter with the name 'field2'.
+// f2e(field2: 87); // error
+// ^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:133:9: Error: No named parameter with the name 'field1'.
+// f2e(field1: 42, field2: 87); // error
+// ^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+ final field core::int field1;
+ final field core::int field2;
+ static final field dynamic _redirecting# = <dynamic>[self::Class1::redirectPositionalSame, self::Class1::redirectPositionalFewer1, self::Class1::redirectPositionalFewer2, self::Class1::redirectNamedSame, self::Class1::redirectNamedReorder, self::Class1::redirectNamedFewer1, self::Class1::redirectNamedFewer2, self::Class1::redirectNamedFewer3]/*isLegacy*/;
+ constructor positional([core::int field1 = #C1, core::int field2 = #C2]) → self::Class1
+ : self::Class1::field1 = field1, self::Class1::field2 = field2, super core::Object::•()
+ ;
+ constructor named({core::int field1 = #C1, core::int field2 = #C2}) → self::Class1
+ : self::Class1::field1 = field1, self::Class1::field2 = field2, super core::Object::•()
+ ;
+ static method _#positional#tearOff([core::int field1 = #C1, core::int field2 = #C2]) → self::Class1
+ return new self::Class1::positional(field1, field2);
+ static factory redirectPositionalSame([core::int field1 = #C3, core::int field2 = #C3]) → self::Class1
+ let dynamic #redirecting_factory = self::Class1::positional in invalid-expression;
+ static method _#redirectPositionalSame#tearOff([core::int field1 = #C1, core::int field2 = #C2]) → self::Class1
+ return new self::Class1::positional(field1, field2);
+ static factory redirectPositionalFewer1([core::int field1 = #C3]) → self::Class1
+ let dynamic #redirecting_factory = self::Class1::positional in invalid-expression;
+ static method _#redirectPositionalFewer1#tearOff([core::int field1 = #C1]) → self::Class1
+ return new self::Class1::positional(field1);
+ static factory redirectPositionalFewer2() → self::Class1
+ let dynamic #redirecting_factory = self::Class1::positional in invalid-expression;
+ static method _#redirectPositionalFewer2#tearOff() → self::Class1
+ return new self::Class1::positional();
+ static method _#named#tearOff({core::int field1 = #C1, core::int field2 = #C2}) → self::Class1
+ return new self::Class1::named(field1: field1, field2: field2);
+ static factory redirectNamedSame({core::int field1 = #C3, core::int field2 = #C3}) → self::Class1
+ let dynamic #redirecting_factory = self::Class1::named in invalid-expression;
+ static method _#redirectNamedSame#tearOff({core::int field1 = #C1, core::int field2 = #C2}) → self::Class1
+ return new self::Class1::named(field1: field1, field2: field2);
+ static factory redirectNamedReorder({core::int field2 = #C3, core::int field1 = #C3}) → self::Class1
+ let dynamic #redirecting_factory = self::Class1::named in invalid-expression;
+ static method _#redirectNamedReorder#tearOff({core::int field2 = #C2, core::int field1 = #C1}) → self::Class1
+ return new self::Class1::named(field2: field2, field1: field1);
+ static factory redirectNamedFewer1({core::int field1 = #C3}) → self::Class1
+ let dynamic #redirecting_factory = self::Class1::named in invalid-expression;
+ static method _#redirectNamedFewer1#tearOff({core::int field1 = #C1}) → self::Class1
+ return new self::Class1::named(field1: field1);
+ static factory redirectNamedFewer2({core::int field2 = #C3}) → self::Class1
+ let dynamic #redirecting_factory = self::Class1::named in invalid-expression;
+ static method _#redirectNamedFewer2#tearOff({core::int field2 = #C2}) → self::Class1
+ return new self::Class1::named(field2: field2);
+ static factory redirectNamedFewer3() → self::Class1
+ let dynamic #redirecting_factory = self::Class1::named in invalid-expression;
+ static method _#redirectNamedFewer3#tearOff() → self::Class1
+ return new self::Class1::named();
+}
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+ core::print("inSoundMode: ${self::inSoundMode}");
+ self::testDefaultValues();
+}
+static method testDefaultValues() → dynamic {
+ ([core::int, core::int]) → self::Class1 f1a = #C4;
+ self::Class1 c1a = f1a(){([core::int, core::int]) → self::Class1};
+ self::expect(1, c1a.{self::Class1::field1}{core::int});
+ self::expect(2, c1a.{self::Class1::field2}{core::int});
+ self::Class1 c1b = f1a(42){([core::int, core::int]) → self::Class1};
+ self::expect(42, c1b.{self::Class1::field1}{core::int});
+ self::expect(2, c1b.{self::Class1::field2}{core::int});
+ self::Class1 c1c = f1a(42, 87){([core::int, core::int]) → self::Class1};
+ self::expect(42, c1c.{self::Class1::field1}{core::int});
+ self::expect(87, c1c.{self::Class1::field2}{core::int});
+ ([core::int]) → self::Class1 f1b = #C5;
+ self::Class1 c1d = f1b(){([core::int]) → self::Class1};
+ self::expect(1, c1d.{self::Class1::field1}{core::int});
+ self::expect(2, c1d.{self::Class1::field2}{core::int});
+ self::Class1 c1e = f1b(42){([core::int]) → self::Class1};
+ self::expect(42, c1e.{self::Class1::field1}{core::int});
+ self::expect(2, c1e.{self::Class1::field2}{core::int});
+ () → Null {
+ let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:58:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f1b(42, 87); // error
+ ^" in f1b{<inapplicable>}.(42, 87);
+ };
+ () → self::Class1 f1c = #C6;
+ self::Class1 c1f = f1c(){() → self::Class1};
+ self::expect(1, c1f.{self::Class1::field1}{core::int});
+ self::expect(2, c1f.{self::Class1::field2}{core::int});
+ () → Null {
+ let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:66:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+ f1c(42); // error
+ ^" in f1c{<inapplicable>}.(42);
+ let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:67:8: Error: Too many positional arguments: 0 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f1c(42, 87); // error
+ ^" in f1c{<inapplicable>}.(42, 87);
+ };
+ ({field1: core::int, field2: core::int}) → self::Class1 f2a = #C7;
+ self::Class1 c2a = f2a(){({field1: core::int, field2: core::int}) → self::Class1};
+ self::expect(1, c2a.{self::Class1::field1}{core::int});
+ self::expect(2, c2a.{self::Class1::field2}{core::int});
+ self::Class1 c2b = f2a(field1: 42){({field1: core::int, field2: core::int}) → self::Class1};
+ self::expect(42, c2b.{self::Class1::field1}{core::int});
+ self::expect(2, c2b.{self::Class1::field2}{core::int});
+ self::Class1 c2c = f2a(field1: 42, field2: 87){({field1: core::int, field2: core::int}) → self::Class1};
+ self::expect(42, c2c.{self::Class1::field1}{core::int});
+ self::expect(87, c2c.{self::Class1::field2}{core::int});
+ self::Class1 c2d = f2a(field2: 87){({field1: core::int, field2: core::int}) → self::Class1};
+ self::expect(1, c2d.{self::Class1::field1}{core::int});
+ self::expect(87, c2d.{self::Class1::field2}{core::int});
+ self::Class1 c2e = f2a(field2: 87, field1: 42){({field1: core::int, field2: core::int}) → self::Class1};
+ self::expect(42, c2e.{self::Class1::field1}{core::int});
+ self::expect(87, c2e.{self::Class1::field2}{core::int});
+ ({field1: core::int, field2: core::int}) → self::Class1 f2b = #C8;
+ self::Class1 c3a = f2b(){({field1: core::int, field2: core::int}) → self::Class1};
+ self::expect(1, c3a.{self::Class1::field1}{core::int});
+ self::expect(2, c3a.{self::Class1::field2}{core::int});
+ self::Class1 c3b = f2b(field1: 42){({field1: core::int, field2: core::int}) → self::Class1};
+ self::expect(42, c3b.{self::Class1::field1}{core::int});
+ self::expect(2, c3b.{self::Class1::field2}{core::int});
+ self::Class1 c3c = f2b(field1: 42, field2: 87){({field1: core::int, field2: core::int}) → self::Class1};
+ self::expect(42, c3c.{self::Class1::field1}{core::int});
+ self::expect(87, c3c.{self::Class1::field2}{core::int});
+ self::Class1 c3d = f2b(field2: 87){({field1: core::int, field2: core::int}) → self::Class1};
+ self::expect(1, c3d.{self::Class1::field1}{core::int});
+ self::expect(87, c3d.{self::Class1::field2}{core::int});
+ self::Class1 c3e = f2b(field2: 87, field1: 42){({field1: core::int, field2: core::int}) → self::Class1};
+ self::expect(42, c3e.{self::Class1::field1}{core::int});
+ self::expect(87, c3e.{self::Class1::field2}{core::int});
+ ({field1: core::int}) → self::Class1 f2c = #C9;
+ self::Class1 c4a = f2c(){({field1: core::int}) → self::Class1};
+ self::expect(1, c4a.{self::Class1::field1}{core::int});
+ self::expect(2, c4a.{self::Class1::field2}{core::int});
+ self::Class1 c4b = f2c(field1: 42){({field1: core::int}) → self::Class1};
+ self::expect(42, c4b.{self::Class1::field1}{core::int});
+ self::expect(2, c4b.{self::Class1::field2}{core::int});
+ () → Null {
+ let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:112:21: Error: No named parameter with the name 'field2'.
+ f2c(field1: 42, field2: 87); // error
+ ^^^^^^" in f2c{<inapplicable>}.(field1: 42, field2: 87);
+ };
+ ({field2: core::int}) → self::Class1 f2d = #C10;
+ self::Class1 c5a = f2d(){({field2: core::int}) → self::Class1};
+ self::expect(1, c5a.{self::Class1::field1}{core::int});
+ self::expect(2, c5a.{self::Class1::field2}{core::int});
+ self::Class1 c5b = f2d(field2: 87){({field2: core::int}) → self::Class1};
+ self::expect(1, c5b.{self::Class1::field1}{core::int});
+ self::expect(87, c5b.{self::Class1::field2}{core::int});
+ () → Null {
+ let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:123:9: Error: No named parameter with the name 'field1'.
+ f2d(field1: 42, field2: 87); // error
+ ^^^^^^" in f2d{<inapplicable>}.(field1: 42, field2: 87);
+ };
+ () → self::Class1 f2e = #C11;
+ self::Class1 c6a = f2e(){() → self::Class1};
+ self::expect(1, c6a.{self::Class1::field1}{core::int});
+ self::expect(2, c6a.{self::Class1::field2}{core::int});
+ () → Null {
+ let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:131:9: Error: No named parameter with the name 'field1'.
+ f2e(field1: 42); // error
+ ^^^^^^" in f2e{<inapplicable>}.(field1: 42);
+ let final Never #t7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:132:9: Error: No named parameter with the name 'field2'.
+ f2e(field2: 87); // error
+ ^^^^^^" in f2e{<inapplicable>}.(field2: 87);
+ let final Never #t8 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:133:9: Error: No named parameter with the name 'field1'.
+ f2e(field1: 42, field2: 87); // error
+ ^^^^^^" in f2e{<inapplicable>}.(field1: 42, field2: 87);
+ };
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C12}) → dynamic {
+ try {
+ f(){() → dynamic};
+ }
+ on core::Object catch(final core::Object e) {
+ core::print("Thrown: ${e}");
+ return;
+ }
+ if(!self::inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw "Expected exception";
+}
+
+constants {
+ #C1 = 1
+ #C2 = 2
+ #C3 = null
+ #C4 = static-tearoff self::Class1::_#redirectPositionalSame#tearOff
+ #C5 = static-tearoff self::Class1::_#redirectPositionalFewer1#tearOff
+ #C6 = static-tearoff self::Class1::_#redirectPositionalFewer2#tearOff
+ #C7 = static-tearoff self::Class1::_#redirectNamedSame#tearOff
+ #C8 = static-tearoff self::Class1::_#redirectNamedReorder#tearOff
+ #C9 = static-tearoff self::Class1::_#redirectNamedFewer1#tearOff
+ #C10 = static-tearoff self::Class1::_#redirectNamedFewer2#tearOff
+ #C11 = static-tearoff self::Class1::_#redirectNamedFewer3#tearOff
+ #C12 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart.strong.transformed.expect
new file mode 100644
index 0000000..ae52285
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart.strong.transformed.expect
@@ -0,0 +1,236 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:58:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f1b(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:66:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+// f1c(42); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:67:8: Error: Too many positional arguments: 0 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f1c(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:112:21: Error: No named parameter with the name 'field2'.
+// f2c(field1: 42, field2: 87); // error
+// ^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:123:9: Error: No named parameter with the name 'field1'.
+// f2d(field1: 42, field2: 87); // error
+// ^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:131:9: Error: No named parameter with the name 'field1'.
+// f2e(field1: 42); // error
+// ^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:132:9: Error: No named parameter with the name 'field2'.
+// f2e(field2: 87); // error
+// ^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:133:9: Error: No named parameter with the name 'field1'.
+// f2e(field1: 42, field2: 87); // error
+// ^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+ final field core::int field1;
+ final field core::int field2;
+ static final field dynamic _redirecting# = <dynamic>[self::Class1::redirectPositionalSame, self::Class1::redirectPositionalFewer1, self::Class1::redirectPositionalFewer2, self::Class1::redirectNamedSame, self::Class1::redirectNamedReorder, self::Class1::redirectNamedFewer1, self::Class1::redirectNamedFewer2, self::Class1::redirectNamedFewer3]/*isLegacy*/;
+ constructor positional([core::int field1 = #C1, core::int field2 = #C2]) → self::Class1
+ : self::Class1::field1 = field1, self::Class1::field2 = field2, super core::Object::•()
+ ;
+ constructor named({core::int field1 = #C1, core::int field2 = #C2}) → self::Class1
+ : self::Class1::field1 = field1, self::Class1::field2 = field2, super core::Object::•()
+ ;
+ static method _#positional#tearOff([core::int field1 = #C1, core::int field2 = #C2]) → self::Class1
+ return new self::Class1::positional(field1, field2);
+ static factory redirectPositionalSame([core::int field1 = #C3, core::int field2 = #C3]) → self::Class1
+ let Never #redirecting_factory = self::Class1::positional in invalid-expression;
+ static method _#redirectPositionalSame#tearOff([core::int field1 = #C1, core::int field2 = #C2]) → self::Class1
+ return new self::Class1::positional(field1, field2);
+ static factory redirectPositionalFewer1([core::int field1 = #C3]) → self::Class1
+ let Never #redirecting_factory = self::Class1::positional in invalid-expression;
+ static method _#redirectPositionalFewer1#tearOff([core::int field1 = #C1]) → self::Class1
+ return new self::Class1::positional(field1);
+ static factory redirectPositionalFewer2() → self::Class1
+ let Never #redirecting_factory = self::Class1::positional in invalid-expression;
+ static method _#redirectPositionalFewer2#tearOff() → self::Class1
+ return new self::Class1::positional();
+ static method _#named#tearOff({core::int field1 = #C1, core::int field2 = #C2}) → self::Class1
+ return new self::Class1::named(field1: field1, field2: field2);
+ static factory redirectNamedSame({core::int field1 = #C3, core::int field2 = #C3}) → self::Class1
+ let Never #redirecting_factory = self::Class1::named in invalid-expression;
+ static method _#redirectNamedSame#tearOff({core::int field1 = #C1, core::int field2 = #C2}) → self::Class1
+ return new self::Class1::named(field1: field1, field2: field2);
+ static factory redirectNamedReorder({core::int field2 = #C3, core::int field1 = #C3}) → self::Class1
+ let Never #redirecting_factory = self::Class1::named in invalid-expression;
+ static method _#redirectNamedReorder#tearOff({core::int field2 = #C2, core::int field1 = #C1}) → self::Class1
+ return new self::Class1::named(field2: field2, field1: field1);
+ static factory redirectNamedFewer1({core::int field1 = #C3}) → self::Class1
+ let Never #redirecting_factory = self::Class1::named in invalid-expression;
+ static method _#redirectNamedFewer1#tearOff({core::int field1 = #C1}) → self::Class1
+ return new self::Class1::named(field1: field1);
+ static factory redirectNamedFewer2({core::int field2 = #C3}) → self::Class1
+ let Never #redirecting_factory = self::Class1::named in invalid-expression;
+ static method _#redirectNamedFewer2#tearOff({core::int field2 = #C2}) → self::Class1
+ return new self::Class1::named(field2: field2);
+ static factory redirectNamedFewer3() → self::Class1
+ let Never #redirecting_factory = self::Class1::named in invalid-expression;
+ static method _#redirectNamedFewer3#tearOff() → self::Class1
+ return new self::Class1::named();
+}
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+ core::print("inSoundMode: ${self::inSoundMode}");
+ self::testDefaultValues();
+}
+static method testDefaultValues() → dynamic {
+ ([core::int, core::int]) → self::Class1 f1a = #C4;
+ self::Class1 c1a = f1a(){([core::int, core::int]) → self::Class1};
+ self::expect(1, c1a.{self::Class1::field1}{core::int});
+ self::expect(2, c1a.{self::Class1::field2}{core::int});
+ self::Class1 c1b = f1a(42){([core::int, core::int]) → self::Class1};
+ self::expect(42, c1b.{self::Class1::field1}{core::int});
+ self::expect(2, c1b.{self::Class1::field2}{core::int});
+ self::Class1 c1c = f1a(42, 87){([core::int, core::int]) → self::Class1};
+ self::expect(42, c1c.{self::Class1::field1}{core::int});
+ self::expect(87, c1c.{self::Class1::field2}{core::int});
+ ([core::int]) → self::Class1 f1b = #C5;
+ self::Class1 c1d = f1b(){([core::int]) → self::Class1};
+ self::expect(1, c1d.{self::Class1::field1}{core::int});
+ self::expect(2, c1d.{self::Class1::field2}{core::int});
+ self::Class1 c1e = f1b(42){([core::int]) → self::Class1};
+ self::expect(42, c1e.{self::Class1::field1}{core::int});
+ self::expect(2, c1e.{self::Class1::field2}{core::int});
+ () → Null {
+ let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:58:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f1b(42, 87); // error
+ ^" in f1b{<inapplicable>}.(42, 87);
+ };
+ () → self::Class1 f1c = #C6;
+ self::Class1 c1f = f1c(){() → self::Class1};
+ self::expect(1, c1f.{self::Class1::field1}{core::int});
+ self::expect(2, c1f.{self::Class1::field2}{core::int});
+ () → Null {
+ let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:66:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+ f1c(42); // error
+ ^" in f1c{<inapplicable>}.(42);
+ let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:67:8: Error: Too many positional arguments: 0 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f1c(42, 87); // error
+ ^" in f1c{<inapplicable>}.(42, 87);
+ };
+ ({field1: core::int, field2: core::int}) → self::Class1 f2a = #C7;
+ self::Class1 c2a = f2a(){({field1: core::int, field2: core::int}) → self::Class1};
+ self::expect(1, c2a.{self::Class1::field1}{core::int});
+ self::expect(2, c2a.{self::Class1::field2}{core::int});
+ self::Class1 c2b = f2a(field1: 42){({field1: core::int, field2: core::int}) → self::Class1};
+ self::expect(42, c2b.{self::Class1::field1}{core::int});
+ self::expect(2, c2b.{self::Class1::field2}{core::int});
+ self::Class1 c2c = f2a(field1: 42, field2: 87){({field1: core::int, field2: core::int}) → self::Class1};
+ self::expect(42, c2c.{self::Class1::field1}{core::int});
+ self::expect(87, c2c.{self::Class1::field2}{core::int});
+ self::Class1 c2d = f2a(field2: 87){({field1: core::int, field2: core::int}) → self::Class1};
+ self::expect(1, c2d.{self::Class1::field1}{core::int});
+ self::expect(87, c2d.{self::Class1::field2}{core::int});
+ self::Class1 c2e = f2a(field2: 87, field1: 42){({field1: core::int, field2: core::int}) → self::Class1};
+ self::expect(42, c2e.{self::Class1::field1}{core::int});
+ self::expect(87, c2e.{self::Class1::field2}{core::int});
+ ({field1: core::int, field2: core::int}) → self::Class1 f2b = #C8;
+ self::Class1 c3a = f2b(){({field1: core::int, field2: core::int}) → self::Class1};
+ self::expect(1, c3a.{self::Class1::field1}{core::int});
+ self::expect(2, c3a.{self::Class1::field2}{core::int});
+ self::Class1 c3b = f2b(field1: 42){({field1: core::int, field2: core::int}) → self::Class1};
+ self::expect(42, c3b.{self::Class1::field1}{core::int});
+ self::expect(2, c3b.{self::Class1::field2}{core::int});
+ self::Class1 c3c = f2b(field1: 42, field2: 87){({field1: core::int, field2: core::int}) → self::Class1};
+ self::expect(42, c3c.{self::Class1::field1}{core::int});
+ self::expect(87, c3c.{self::Class1::field2}{core::int});
+ self::Class1 c3d = f2b(field2: 87){({field1: core::int, field2: core::int}) → self::Class1};
+ self::expect(1, c3d.{self::Class1::field1}{core::int});
+ self::expect(87, c3d.{self::Class1::field2}{core::int});
+ self::Class1 c3e = f2b(field2: 87, field1: 42){({field1: core::int, field2: core::int}) → self::Class1};
+ self::expect(42, c3e.{self::Class1::field1}{core::int});
+ self::expect(87, c3e.{self::Class1::field2}{core::int});
+ ({field1: core::int}) → self::Class1 f2c = #C9;
+ self::Class1 c4a = f2c(){({field1: core::int}) → self::Class1};
+ self::expect(1, c4a.{self::Class1::field1}{core::int});
+ self::expect(2, c4a.{self::Class1::field2}{core::int});
+ self::Class1 c4b = f2c(field1: 42){({field1: core::int}) → self::Class1};
+ self::expect(42, c4b.{self::Class1::field1}{core::int});
+ self::expect(2, c4b.{self::Class1::field2}{core::int});
+ () → Null {
+ let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:112:21: Error: No named parameter with the name 'field2'.
+ f2c(field1: 42, field2: 87); // error
+ ^^^^^^" in f2c{<inapplicable>}.(field1: 42, field2: 87);
+ };
+ ({field2: core::int}) → self::Class1 f2d = #C10;
+ self::Class1 c5a = f2d(){({field2: core::int}) → self::Class1};
+ self::expect(1, c5a.{self::Class1::field1}{core::int});
+ self::expect(2, c5a.{self::Class1::field2}{core::int});
+ self::Class1 c5b = f2d(field2: 87){({field2: core::int}) → self::Class1};
+ self::expect(1, c5b.{self::Class1::field1}{core::int});
+ self::expect(87, c5b.{self::Class1::field2}{core::int});
+ () → Null {
+ let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:123:9: Error: No named parameter with the name 'field1'.
+ f2d(field1: 42, field2: 87); // error
+ ^^^^^^" in f2d{<inapplicable>}.(field1: 42, field2: 87);
+ };
+ () → self::Class1 f2e = #C11;
+ self::Class1 c6a = f2e(){() → self::Class1};
+ self::expect(1, c6a.{self::Class1::field1}{core::int});
+ self::expect(2, c6a.{self::Class1::field2}{core::int});
+ () → Null {
+ let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:131:9: Error: No named parameter with the name 'field1'.
+ f2e(field1: 42); // error
+ ^^^^^^" in f2e{<inapplicable>}.(field1: 42);
+ let final Never #t7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:132:9: Error: No named parameter with the name 'field2'.
+ f2e(field2: 87); // error
+ ^^^^^^" in f2e{<inapplicable>}.(field2: 87);
+ let final Never #t8 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:133:9: Error: No named parameter with the name 'field1'.
+ f2e(field1: 42, field2: 87); // error
+ ^^^^^^" in f2e{<inapplicable>}.(field1: 42, field2: 87);
+ };
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C12}) → dynamic {
+ try {
+ f(){() → dynamic};
+ }
+ on core::Object catch(final core::Object e) {
+ core::print("Thrown: ${e}");
+ return;
+ }
+ if(!self::inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw "Expected exception";
+}
+
+constants {
+ #C1 = 1
+ #C2 = 2
+ #C3 = null
+ #C4 = static-tearoff self::Class1::_#redirectPositionalSame#tearOff
+ #C5 = static-tearoff self::Class1::_#redirectPositionalFewer1#tearOff
+ #C6 = static-tearoff self::Class1::_#redirectPositionalFewer2#tearOff
+ #C7 = static-tearoff self::Class1::_#redirectNamedSame#tearOff
+ #C8 = static-tearoff self::Class1::_#redirectNamedReorder#tearOff
+ #C9 = static-tearoff self::Class1::_#redirectNamedFewer1#tearOff
+ #C10 = static-tearoff self::Class1::_#redirectNamedFewer2#tearOff
+ #C11 = static-tearoff self::Class1::_#redirectNamedFewer3#tearOff
+ #C12 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart.textual_outline.expect
new file mode 100644
index 0000000..90fc9da
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart.textual_outline.expect
@@ -0,0 +1,22 @@
+final bool inSoundMode = <int?>[] is! List<int>;
+main() {}
+
+class Class1 {
+ final int field1;
+ final int field2;
+ Class1.positional([this.field1 = 1, this.field2 = 2]);
+ factory Class1.redirectPositionalSame([int field1, int field2]) =
+ Class1.positional;
+ factory Class1.redirectPositionalFewer1([int field1]) = Class1.positional;
+ factory Class1.redirectPositionalFewer2() = Class1.positional;
+ Class1.named({this.field1 = 1, this.field2 = 2});
+ factory Class1.redirectNamedSame({int field1, int field2}) = Class1.named;
+ factory Class1.redirectNamedReorder({int field2, int field1}) = Class1.named;
+ factory Class1.redirectNamedFewer1({int field1}) = Class1.named;
+ factory Class1.redirectNamedFewer2({int field2}) = Class1.named;
+ factory Class1.redirectNamedFewer3() = Class1.named;
+}
+
+testDefaultValues() {}
+expect(expected, actual) {}
+throws(Function() f, {bool inSoundModeOnly: false}) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..5735aef
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart.textual_outline_modelled.expect
@@ -0,0 +1,21 @@
+class Class1 {
+ Class1.named({this.field1 = 1, this.field2 = 2});
+ Class1.positional([this.field1 = 1, this.field2 = 2]);
+ factory Class1.redirectNamedFewer1({int field1}) = Class1.named;
+ factory Class1.redirectNamedFewer2({int field2}) = Class1.named;
+ factory Class1.redirectNamedFewer3() = Class1.named;
+ factory Class1.redirectNamedReorder({int field2, int field1}) = Class1.named;
+ factory Class1.redirectNamedSame({int field1, int field2}) = Class1.named;
+ factory Class1.redirectPositionalFewer1([int field1]) = Class1.positional;
+ factory Class1.redirectPositionalFewer2() = Class1.positional;
+ factory Class1.redirectPositionalSame([int field1, int field2]) =
+ Class1.positional;
+ final int field1;
+ final int field2;
+}
+
+expect(expected, actual) {}
+final bool inSoundMode = <int?>[] is! List<int>;
+main() {}
+testDefaultValues() {}
+throws(Function() f, {bool inSoundModeOnly: false}) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart.weak.expect
new file mode 100644
index 0000000..6d9d205
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart.weak.expect
@@ -0,0 +1,236 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:58:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f1b(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:66:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+// f1c(42); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:67:8: Error: Too many positional arguments: 0 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f1c(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:112:21: Error: No named parameter with the name 'field2'.
+// f2c(field1: 42, field2: 87); // error
+// ^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:123:9: Error: No named parameter with the name 'field1'.
+// f2d(field1: 42, field2: 87); // error
+// ^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:131:9: Error: No named parameter with the name 'field1'.
+// f2e(field1: 42); // error
+// ^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:132:9: Error: No named parameter with the name 'field2'.
+// f2e(field2: 87); // error
+// ^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:133:9: Error: No named parameter with the name 'field1'.
+// f2e(field1: 42, field2: 87); // error
+// ^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+ final field core::int field1;
+ final field core::int field2;
+ static final field dynamic _redirecting# = <dynamic>[self::Class1::redirectPositionalSame, self::Class1::redirectPositionalFewer1, self::Class1::redirectPositionalFewer2, self::Class1::redirectNamedSame, self::Class1::redirectNamedReorder, self::Class1::redirectNamedFewer1, self::Class1::redirectNamedFewer2, self::Class1::redirectNamedFewer3]/*isLegacy*/;
+ constructor positional([core::int field1 = #C1, core::int field2 = #C2]) → self::Class1
+ : self::Class1::field1 = field1, self::Class1::field2 = field2, super core::Object::•()
+ ;
+ constructor named({core::int field1 = #C1, core::int field2 = #C2}) → self::Class1
+ : self::Class1::field1 = field1, self::Class1::field2 = field2, super core::Object::•()
+ ;
+ static method _#positional#tearOff([core::int field1 = #C1, core::int field2 = #C2]) → self::Class1
+ return new self::Class1::positional(field1, field2);
+ static factory redirectPositionalSame([core::int field1 = #C3, core::int field2 = #C3]) → self::Class1
+ let dynamic #redirecting_factory = self::Class1::positional in invalid-expression;
+ static method _#redirectPositionalSame#tearOff([core::int field1 = #C1, core::int field2 = #C2]) → self::Class1
+ return new self::Class1::positional(field1, field2);
+ static factory redirectPositionalFewer1([core::int field1 = #C3]) → self::Class1
+ let dynamic #redirecting_factory = self::Class1::positional in invalid-expression;
+ static method _#redirectPositionalFewer1#tearOff([core::int field1 = #C1]) → self::Class1
+ return new self::Class1::positional(field1);
+ static factory redirectPositionalFewer2() → self::Class1
+ let dynamic #redirecting_factory = self::Class1::positional in invalid-expression;
+ static method _#redirectPositionalFewer2#tearOff() → self::Class1
+ return new self::Class1::positional();
+ static method _#named#tearOff({core::int field1 = #C1, core::int field2 = #C2}) → self::Class1
+ return new self::Class1::named(field1: field1, field2: field2);
+ static factory redirectNamedSame({core::int field1 = #C3, core::int field2 = #C3}) → self::Class1
+ let dynamic #redirecting_factory = self::Class1::named in invalid-expression;
+ static method _#redirectNamedSame#tearOff({core::int field1 = #C1, core::int field2 = #C2}) → self::Class1
+ return new self::Class1::named(field1: field1, field2: field2);
+ static factory redirectNamedReorder({core::int field2 = #C3, core::int field1 = #C3}) → self::Class1
+ let dynamic #redirecting_factory = self::Class1::named in invalid-expression;
+ static method _#redirectNamedReorder#tearOff({core::int field2 = #C2, core::int field1 = #C1}) → self::Class1
+ return new self::Class1::named(field2: field2, field1: field1);
+ static factory redirectNamedFewer1({core::int field1 = #C3}) → self::Class1
+ let dynamic #redirecting_factory = self::Class1::named in invalid-expression;
+ static method _#redirectNamedFewer1#tearOff({core::int field1 = #C1}) → self::Class1
+ return new self::Class1::named(field1: field1);
+ static factory redirectNamedFewer2({core::int field2 = #C3}) → self::Class1
+ let dynamic #redirecting_factory = self::Class1::named in invalid-expression;
+ static method _#redirectNamedFewer2#tearOff({core::int field2 = #C2}) → self::Class1
+ return new self::Class1::named(field2: field2);
+ static factory redirectNamedFewer3() → self::Class1
+ let dynamic #redirecting_factory = self::Class1::named in invalid-expression;
+ static method _#redirectNamedFewer3#tearOff() → self::Class1
+ return new self::Class1::named();
+}
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+ core::print("inSoundMode: ${self::inSoundMode}");
+ self::testDefaultValues();
+}
+static method testDefaultValues() → dynamic {
+ ([core::int, core::int]) → self::Class1 f1a = #C4;
+ self::Class1 c1a = f1a(){([core::int, core::int]) → self::Class1};
+ self::expect(1, c1a.{self::Class1::field1}{core::int});
+ self::expect(2, c1a.{self::Class1::field2}{core::int});
+ self::Class1 c1b = f1a(42){([core::int, core::int]) → self::Class1};
+ self::expect(42, c1b.{self::Class1::field1}{core::int});
+ self::expect(2, c1b.{self::Class1::field2}{core::int});
+ self::Class1 c1c = f1a(42, 87){([core::int, core::int]) → self::Class1};
+ self::expect(42, c1c.{self::Class1::field1}{core::int});
+ self::expect(87, c1c.{self::Class1::field2}{core::int});
+ ([core::int]) → self::Class1 f1b = #C5;
+ self::Class1 c1d = f1b(){([core::int]) → self::Class1};
+ self::expect(1, c1d.{self::Class1::field1}{core::int});
+ self::expect(2, c1d.{self::Class1::field2}{core::int});
+ self::Class1 c1e = f1b(42){([core::int]) → self::Class1};
+ self::expect(42, c1e.{self::Class1::field1}{core::int});
+ self::expect(2, c1e.{self::Class1::field2}{core::int});
+ () → Null {
+ let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:58:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f1b(42, 87); // error
+ ^" in f1b{<inapplicable>}.(42, 87);
+ };
+ () → self::Class1 f1c = #C6;
+ self::Class1 c1f = f1c(){() → self::Class1};
+ self::expect(1, c1f.{self::Class1::field1}{core::int});
+ self::expect(2, c1f.{self::Class1::field2}{core::int});
+ () → Null {
+ let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:66:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+ f1c(42); // error
+ ^" in f1c{<inapplicable>}.(42);
+ let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:67:8: Error: Too many positional arguments: 0 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f1c(42, 87); // error
+ ^" in f1c{<inapplicable>}.(42, 87);
+ };
+ ({field1: core::int, field2: core::int}) → self::Class1 f2a = #C7;
+ self::Class1 c2a = f2a(){({field1: core::int, field2: core::int}) → self::Class1};
+ self::expect(1, c2a.{self::Class1::field1}{core::int});
+ self::expect(2, c2a.{self::Class1::field2}{core::int});
+ self::Class1 c2b = f2a(field1: 42){({field1: core::int, field2: core::int}) → self::Class1};
+ self::expect(42, c2b.{self::Class1::field1}{core::int});
+ self::expect(2, c2b.{self::Class1::field2}{core::int});
+ self::Class1 c2c = f2a(field1: 42, field2: 87){({field1: core::int, field2: core::int}) → self::Class1};
+ self::expect(42, c2c.{self::Class1::field1}{core::int});
+ self::expect(87, c2c.{self::Class1::field2}{core::int});
+ self::Class1 c2d = f2a(field2: 87){({field1: core::int, field2: core::int}) → self::Class1};
+ self::expect(1, c2d.{self::Class1::field1}{core::int});
+ self::expect(87, c2d.{self::Class1::field2}{core::int});
+ self::Class1 c2e = f2a(field2: 87, field1: 42){({field1: core::int, field2: core::int}) → self::Class1};
+ self::expect(42, c2e.{self::Class1::field1}{core::int});
+ self::expect(87, c2e.{self::Class1::field2}{core::int});
+ ({field1: core::int, field2: core::int}) → self::Class1 f2b = #C8;
+ self::Class1 c3a = f2b(){({field1: core::int, field2: core::int}) → self::Class1};
+ self::expect(1, c3a.{self::Class1::field1}{core::int});
+ self::expect(2, c3a.{self::Class1::field2}{core::int});
+ self::Class1 c3b = f2b(field1: 42){({field1: core::int, field2: core::int}) → self::Class1};
+ self::expect(42, c3b.{self::Class1::field1}{core::int});
+ self::expect(2, c3b.{self::Class1::field2}{core::int});
+ self::Class1 c3c = f2b(field1: 42, field2: 87){({field1: core::int, field2: core::int}) → self::Class1};
+ self::expect(42, c3c.{self::Class1::field1}{core::int});
+ self::expect(87, c3c.{self::Class1::field2}{core::int});
+ self::Class1 c3d = f2b(field2: 87){({field1: core::int, field2: core::int}) → self::Class1};
+ self::expect(1, c3d.{self::Class1::field1}{core::int});
+ self::expect(87, c3d.{self::Class1::field2}{core::int});
+ self::Class1 c3e = f2b(field2: 87, field1: 42){({field1: core::int, field2: core::int}) → self::Class1};
+ self::expect(42, c3e.{self::Class1::field1}{core::int});
+ self::expect(87, c3e.{self::Class1::field2}{core::int});
+ ({field1: core::int}) → self::Class1 f2c = #C9;
+ self::Class1 c4a = f2c(){({field1: core::int}) → self::Class1};
+ self::expect(1, c4a.{self::Class1::field1}{core::int});
+ self::expect(2, c4a.{self::Class1::field2}{core::int});
+ self::Class1 c4b = f2c(field1: 42){({field1: core::int}) → self::Class1};
+ self::expect(42, c4b.{self::Class1::field1}{core::int});
+ self::expect(2, c4b.{self::Class1::field2}{core::int});
+ () → Null {
+ let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:112:21: Error: No named parameter with the name 'field2'.
+ f2c(field1: 42, field2: 87); // error
+ ^^^^^^" in f2c{<inapplicable>}.(field1: 42, field2: 87);
+ };
+ ({field2: core::int}) → self::Class1 f2d = #C10;
+ self::Class1 c5a = f2d(){({field2: core::int}) → self::Class1};
+ self::expect(1, c5a.{self::Class1::field1}{core::int});
+ self::expect(2, c5a.{self::Class1::field2}{core::int});
+ self::Class1 c5b = f2d(field2: 87){({field2: core::int}) → self::Class1};
+ self::expect(1, c5b.{self::Class1::field1}{core::int});
+ self::expect(87, c5b.{self::Class1::field2}{core::int});
+ () → Null {
+ let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:123:9: Error: No named parameter with the name 'field1'.
+ f2d(field1: 42, field2: 87); // error
+ ^^^^^^" in f2d{<inapplicable>}.(field1: 42, field2: 87);
+ };
+ () → self::Class1 f2e = #C11;
+ self::Class1 c6a = f2e(){() → self::Class1};
+ self::expect(1, c6a.{self::Class1::field1}{core::int});
+ self::expect(2, c6a.{self::Class1::field2}{core::int});
+ () → Null {
+ let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:131:9: Error: No named parameter with the name 'field1'.
+ f2e(field1: 42); // error
+ ^^^^^^" in f2e{<inapplicable>}.(field1: 42);
+ let final Never #t7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:132:9: Error: No named parameter with the name 'field2'.
+ f2e(field2: 87); // error
+ ^^^^^^" in f2e{<inapplicable>}.(field2: 87);
+ let final Never #t8 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:133:9: Error: No named parameter with the name 'field1'.
+ f2e(field1: 42, field2: 87); // error
+ ^^^^^^" in f2e{<inapplicable>}.(field1: 42, field2: 87);
+ };
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C12}) → dynamic {
+ try {
+ f(){() → dynamic};
+ }
+ on core::Object catch(final core::Object e) {
+ core::print("Thrown: ${e}");
+ return;
+ }
+ if(!self::inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw "Expected exception";
+}
+
+constants {
+ #C1 = 1
+ #C2 = 2
+ #C3 = null
+ #C4 = static-tearoff self::Class1::_#redirectPositionalSame#tearOff
+ #C5 = static-tearoff self::Class1::_#redirectPositionalFewer1#tearOff
+ #C6 = static-tearoff self::Class1::_#redirectPositionalFewer2#tearOff
+ #C7 = static-tearoff self::Class1::_#redirectNamedSame#tearOff
+ #C8 = static-tearoff self::Class1::_#redirectNamedReorder#tearOff
+ #C9 = static-tearoff self::Class1::_#redirectNamedFewer1#tearOff
+ #C10 = static-tearoff self::Class1::_#redirectNamedFewer2#tearOff
+ #C11 = static-tearoff self::Class1::_#redirectNamedFewer3#tearOff
+ #C12 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart.weak.outline.expect
new file mode 100644
index 0000000..9ef35eb
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart.weak.outline.expect
@@ -0,0 +1,58 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+ final field core::int field1;
+ final field core::int field2;
+ static final field dynamic _redirecting# = <dynamic>[self::Class1::redirectPositionalSame, self::Class1::redirectPositionalFewer1, self::Class1::redirectPositionalFewer2, self::Class1::redirectNamedSame, self::Class1::redirectNamedReorder, self::Class1::redirectNamedFewer1, self::Class1::redirectNamedFewer2, self::Class1::redirectNamedFewer3]/*isLegacy*/;
+ constructor positional([core::int field1, core::int field2]) → self::Class1
+ ;
+ constructor named({core::int field1, core::int field2}) → self::Class1
+ ;
+ static method _#positional#tearOff([core::int field1, core::int field2]) → self::Class1
+ return new self::Class1::positional(field1, field2);
+ static factory redirectPositionalSame([core::int field1, core::int field2]) → self::Class1
+ let dynamic #redirecting_factory = self::Class1::positional in invalid-expression;
+ static method _#redirectPositionalSame#tearOff([core::int field1, core::int field2]) → self::Class1
+ return new self::Class1::positional(field1, field2);
+ static factory redirectPositionalFewer1([core::int field1]) → self::Class1
+ let dynamic #redirecting_factory = self::Class1::positional in invalid-expression;
+ static method _#redirectPositionalFewer1#tearOff([core::int field1]) → self::Class1
+ return new self::Class1::positional(field1);
+ static factory redirectPositionalFewer2() → self::Class1
+ let dynamic #redirecting_factory = self::Class1::positional in invalid-expression;
+ static method _#redirectPositionalFewer2#tearOff() → self::Class1
+ return new self::Class1::positional();
+ static method _#named#tearOff({core::int field1, core::int field2}) → self::Class1
+ return new self::Class1::named(field1: field1, field2: field2);
+ static factory redirectNamedSame({core::int field1, core::int field2}) → self::Class1
+ let dynamic #redirecting_factory = self::Class1::named in invalid-expression;
+ static method _#redirectNamedSame#tearOff({core::int field1, core::int field2}) → self::Class1
+ return new self::Class1::named(field1: field1, field2: field2);
+ static factory redirectNamedReorder({core::int field2, core::int field1}) → self::Class1
+ let dynamic #redirecting_factory = self::Class1::named in invalid-expression;
+ static method _#redirectNamedReorder#tearOff({core::int field2, core::int field1}) → self::Class1
+ return new self::Class1::named(field2: field2, field1: field1);
+ static factory redirectNamedFewer1({core::int field1}) → self::Class1
+ let dynamic #redirecting_factory = self::Class1::named in invalid-expression;
+ static method _#redirectNamedFewer1#tearOff({core::int field1}) → self::Class1
+ return new self::Class1::named(field1: field1);
+ static factory redirectNamedFewer2({core::int field2}) → self::Class1
+ let dynamic #redirecting_factory = self::Class1::named in invalid-expression;
+ static method _#redirectNamedFewer2#tearOff({core::int field2}) → self::Class1
+ return new self::Class1::named(field2: field2);
+ static factory redirectNamedFewer3() → self::Class1
+ let dynamic #redirecting_factory = self::Class1::named in invalid-expression;
+ static method _#redirectNamedFewer3#tearOff() → self::Class1
+ return new self::Class1::named();
+}
+static final field core::bool inSoundMode;
+static method main() → dynamic
+ ;
+static method testDefaultValues() → dynamic
+ ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+ ;
+static method throws(() → dynamic f, {core::bool inSoundModeOnly}) → dynamic
+ ;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart.weak.transformed.expect
new file mode 100644
index 0000000..ae52285
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart.weak.transformed.expect
@@ -0,0 +1,236 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:58:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f1b(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:66:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+// f1c(42); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:67:8: Error: Too many positional arguments: 0 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f1c(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:112:21: Error: No named parameter with the name 'field2'.
+// f2c(field1: 42, field2: 87); // error
+// ^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:123:9: Error: No named parameter with the name 'field1'.
+// f2d(field1: 42, field2: 87); // error
+// ^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:131:9: Error: No named parameter with the name 'field1'.
+// f2e(field1: 42); // error
+// ^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:132:9: Error: No named parameter with the name 'field2'.
+// f2e(field2: 87); // error
+// ^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:133:9: Error: No named parameter with the name 'field1'.
+// f2e(field1: 42, field2: 87); // error
+// ^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+ final field core::int field1;
+ final field core::int field2;
+ static final field dynamic _redirecting# = <dynamic>[self::Class1::redirectPositionalSame, self::Class1::redirectPositionalFewer1, self::Class1::redirectPositionalFewer2, self::Class1::redirectNamedSame, self::Class1::redirectNamedReorder, self::Class1::redirectNamedFewer1, self::Class1::redirectNamedFewer2, self::Class1::redirectNamedFewer3]/*isLegacy*/;
+ constructor positional([core::int field1 = #C1, core::int field2 = #C2]) → self::Class1
+ : self::Class1::field1 = field1, self::Class1::field2 = field2, super core::Object::•()
+ ;
+ constructor named({core::int field1 = #C1, core::int field2 = #C2}) → self::Class1
+ : self::Class1::field1 = field1, self::Class1::field2 = field2, super core::Object::•()
+ ;
+ static method _#positional#tearOff([core::int field1 = #C1, core::int field2 = #C2]) → self::Class1
+ return new self::Class1::positional(field1, field2);
+ static factory redirectPositionalSame([core::int field1 = #C3, core::int field2 = #C3]) → self::Class1
+ let Never #redirecting_factory = self::Class1::positional in invalid-expression;
+ static method _#redirectPositionalSame#tearOff([core::int field1 = #C1, core::int field2 = #C2]) → self::Class1
+ return new self::Class1::positional(field1, field2);
+ static factory redirectPositionalFewer1([core::int field1 = #C3]) → self::Class1
+ let Never #redirecting_factory = self::Class1::positional in invalid-expression;
+ static method _#redirectPositionalFewer1#tearOff([core::int field1 = #C1]) → self::Class1
+ return new self::Class1::positional(field1);
+ static factory redirectPositionalFewer2() → self::Class1
+ let Never #redirecting_factory = self::Class1::positional in invalid-expression;
+ static method _#redirectPositionalFewer2#tearOff() → self::Class1
+ return new self::Class1::positional();
+ static method _#named#tearOff({core::int field1 = #C1, core::int field2 = #C2}) → self::Class1
+ return new self::Class1::named(field1: field1, field2: field2);
+ static factory redirectNamedSame({core::int field1 = #C3, core::int field2 = #C3}) → self::Class1
+ let Never #redirecting_factory = self::Class1::named in invalid-expression;
+ static method _#redirectNamedSame#tearOff({core::int field1 = #C1, core::int field2 = #C2}) → self::Class1
+ return new self::Class1::named(field1: field1, field2: field2);
+ static factory redirectNamedReorder({core::int field2 = #C3, core::int field1 = #C3}) → self::Class1
+ let Never #redirecting_factory = self::Class1::named in invalid-expression;
+ static method _#redirectNamedReorder#tearOff({core::int field2 = #C2, core::int field1 = #C1}) → self::Class1
+ return new self::Class1::named(field2: field2, field1: field1);
+ static factory redirectNamedFewer1({core::int field1 = #C3}) → self::Class1
+ let Never #redirecting_factory = self::Class1::named in invalid-expression;
+ static method _#redirectNamedFewer1#tearOff({core::int field1 = #C1}) → self::Class1
+ return new self::Class1::named(field1: field1);
+ static factory redirectNamedFewer2({core::int field2 = #C3}) → self::Class1
+ let Never #redirecting_factory = self::Class1::named in invalid-expression;
+ static method _#redirectNamedFewer2#tearOff({core::int field2 = #C2}) → self::Class1
+ return new self::Class1::named(field2: field2);
+ static factory redirectNamedFewer3() → self::Class1
+ let Never #redirecting_factory = self::Class1::named in invalid-expression;
+ static method _#redirectNamedFewer3#tearOff() → self::Class1
+ return new self::Class1::named();
+}
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+ core::print("inSoundMode: ${self::inSoundMode}");
+ self::testDefaultValues();
+}
+static method testDefaultValues() → dynamic {
+ ([core::int, core::int]) → self::Class1 f1a = #C4;
+ self::Class1 c1a = f1a(){([core::int, core::int]) → self::Class1};
+ self::expect(1, c1a.{self::Class1::field1}{core::int});
+ self::expect(2, c1a.{self::Class1::field2}{core::int});
+ self::Class1 c1b = f1a(42){([core::int, core::int]) → self::Class1};
+ self::expect(42, c1b.{self::Class1::field1}{core::int});
+ self::expect(2, c1b.{self::Class1::field2}{core::int});
+ self::Class1 c1c = f1a(42, 87){([core::int, core::int]) → self::Class1};
+ self::expect(42, c1c.{self::Class1::field1}{core::int});
+ self::expect(87, c1c.{self::Class1::field2}{core::int});
+ ([core::int]) → self::Class1 f1b = #C5;
+ self::Class1 c1d = f1b(){([core::int]) → self::Class1};
+ self::expect(1, c1d.{self::Class1::field1}{core::int});
+ self::expect(2, c1d.{self::Class1::field2}{core::int});
+ self::Class1 c1e = f1b(42){([core::int]) → self::Class1};
+ self::expect(42, c1e.{self::Class1::field1}{core::int});
+ self::expect(2, c1e.{self::Class1::field2}{core::int});
+ () → Null {
+ let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:58:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f1b(42, 87); // error
+ ^" in f1b{<inapplicable>}.(42, 87);
+ };
+ () → self::Class1 f1c = #C6;
+ self::Class1 c1f = f1c(){() → self::Class1};
+ self::expect(1, c1f.{self::Class1::field1}{core::int});
+ self::expect(2, c1f.{self::Class1::field2}{core::int});
+ () → Null {
+ let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:66:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+ f1c(42); // error
+ ^" in f1c{<inapplicable>}.(42);
+ let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:67:8: Error: Too many positional arguments: 0 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f1c(42, 87); // error
+ ^" in f1c{<inapplicable>}.(42, 87);
+ };
+ ({field1: core::int, field2: core::int}) → self::Class1 f2a = #C7;
+ self::Class1 c2a = f2a(){({field1: core::int, field2: core::int}) → self::Class1};
+ self::expect(1, c2a.{self::Class1::field1}{core::int});
+ self::expect(2, c2a.{self::Class1::field2}{core::int});
+ self::Class1 c2b = f2a(field1: 42){({field1: core::int, field2: core::int}) → self::Class1};
+ self::expect(42, c2b.{self::Class1::field1}{core::int});
+ self::expect(2, c2b.{self::Class1::field2}{core::int});
+ self::Class1 c2c = f2a(field1: 42, field2: 87){({field1: core::int, field2: core::int}) → self::Class1};
+ self::expect(42, c2c.{self::Class1::field1}{core::int});
+ self::expect(87, c2c.{self::Class1::field2}{core::int});
+ self::Class1 c2d = f2a(field2: 87){({field1: core::int, field2: core::int}) → self::Class1};
+ self::expect(1, c2d.{self::Class1::field1}{core::int});
+ self::expect(87, c2d.{self::Class1::field2}{core::int});
+ self::Class1 c2e = f2a(field2: 87, field1: 42){({field1: core::int, field2: core::int}) → self::Class1};
+ self::expect(42, c2e.{self::Class1::field1}{core::int});
+ self::expect(87, c2e.{self::Class1::field2}{core::int});
+ ({field1: core::int, field2: core::int}) → self::Class1 f2b = #C8;
+ self::Class1 c3a = f2b(){({field1: core::int, field2: core::int}) → self::Class1};
+ self::expect(1, c3a.{self::Class1::field1}{core::int});
+ self::expect(2, c3a.{self::Class1::field2}{core::int});
+ self::Class1 c3b = f2b(field1: 42){({field1: core::int, field2: core::int}) → self::Class1};
+ self::expect(42, c3b.{self::Class1::field1}{core::int});
+ self::expect(2, c3b.{self::Class1::field2}{core::int});
+ self::Class1 c3c = f2b(field1: 42, field2: 87){({field1: core::int, field2: core::int}) → self::Class1};
+ self::expect(42, c3c.{self::Class1::field1}{core::int});
+ self::expect(87, c3c.{self::Class1::field2}{core::int});
+ self::Class1 c3d = f2b(field2: 87){({field1: core::int, field2: core::int}) → self::Class1};
+ self::expect(1, c3d.{self::Class1::field1}{core::int});
+ self::expect(87, c3d.{self::Class1::field2}{core::int});
+ self::Class1 c3e = f2b(field2: 87, field1: 42){({field1: core::int, field2: core::int}) → self::Class1};
+ self::expect(42, c3e.{self::Class1::field1}{core::int});
+ self::expect(87, c3e.{self::Class1::field2}{core::int});
+ ({field1: core::int}) → self::Class1 f2c = #C9;
+ self::Class1 c4a = f2c(){({field1: core::int}) → self::Class1};
+ self::expect(1, c4a.{self::Class1::field1}{core::int});
+ self::expect(2, c4a.{self::Class1::field2}{core::int});
+ self::Class1 c4b = f2c(field1: 42){({field1: core::int}) → self::Class1};
+ self::expect(42, c4b.{self::Class1::field1}{core::int});
+ self::expect(2, c4b.{self::Class1::field2}{core::int});
+ () → Null {
+ let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:112:21: Error: No named parameter with the name 'field2'.
+ f2c(field1: 42, field2: 87); // error
+ ^^^^^^" in f2c{<inapplicable>}.(field1: 42, field2: 87);
+ };
+ ({field2: core::int}) → self::Class1 f2d = #C10;
+ self::Class1 c5a = f2d(){({field2: core::int}) → self::Class1};
+ self::expect(1, c5a.{self::Class1::field1}{core::int});
+ self::expect(2, c5a.{self::Class1::field2}{core::int});
+ self::Class1 c5b = f2d(field2: 87){({field2: core::int}) → self::Class1};
+ self::expect(1, c5b.{self::Class1::field1}{core::int});
+ self::expect(87, c5b.{self::Class1::field2}{core::int});
+ () → Null {
+ let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:123:9: Error: No named parameter with the name 'field1'.
+ f2d(field1: 42, field2: 87); // error
+ ^^^^^^" in f2d{<inapplicable>}.(field1: 42, field2: 87);
+ };
+ () → self::Class1 f2e = #C11;
+ self::Class1 c6a = f2e(){() → self::Class1};
+ self::expect(1, c6a.{self::Class1::field1}{core::int});
+ self::expect(2, c6a.{self::Class1::field2}{core::int});
+ () → Null {
+ let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:131:9: Error: No named parameter with the name 'field1'.
+ f2e(field1: 42); // error
+ ^^^^^^" in f2e{<inapplicable>}.(field1: 42);
+ let final Never #t7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:132:9: Error: No named parameter with the name 'field2'.
+ f2e(field2: 87); // error
+ ^^^^^^" in f2e{<inapplicable>}.(field2: 87);
+ let final Never #t8 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off_default_values_complex.dart:133:9: Error: No named parameter with the name 'field1'.
+ f2e(field1: 42, field2: 87); // error
+ ^^^^^^" in f2e{<inapplicable>}.(field1: 42, field2: 87);
+ };
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C12}) → dynamic {
+ try {
+ f(){() → dynamic};
+ }
+ on core::Object catch(final core::Object e) {
+ core::print("Thrown: ${e}");
+ return;
+ }
+ if(!self::inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw "Expected exception";
+}
+
+constants {
+ #C1 = 1
+ #C2 = 2
+ #C3 = null
+ #C4 = static-tearoff self::Class1::_#redirectPositionalSame#tearOff
+ #C5 = static-tearoff self::Class1::_#redirectPositionalFewer1#tearOff
+ #C6 = static-tearoff self::Class1::_#redirectPositionalFewer2#tearOff
+ #C7 = static-tearoff self::Class1::_#redirectNamedSame#tearOff
+ #C8 = static-tearoff self::Class1::_#redirectNamedReorder#tearOff
+ #C9 = static-tearoff self::Class1::_#redirectNamedFewer1#tearOff
+ #C10 = static-tearoff self::Class1::_#redirectNamedFewer2#tearOff
+ #C11 = static-tearoff self::Class1::_#redirectNamedFewer3#tearOff
+ #C12 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart
new file mode 100644
index 0000000..aa3ec2f
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart
@@ -0,0 +1,78 @@
+// 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.
+
+import 'main_lib.dart';
+
+typedef H<X, Y> = A<Y>;
+
+// TODO(johnniwinther): Use 'var' here when dependency on inferred parameter
+// types is handled.
+dynamic H_new = H.new;
+dynamic H_named = H.named;
+dynamic H_fact = H.fact;
+dynamic H_redirect = H.redirect;
+
+dynamic F_new = F.new;
+dynamic F_named = F.named;
+dynamic F_fact = F.fact;
+dynamic F_redirect = F.redirect;
+
+main() {
+ expect(true, identical(F_new, F_new_lib));
+ expect(false, identical(F_new, F_named_lib));
+ expect(false, identical(F_new, F_fact_lib));
+ expect(false, identical(F_new, F_redirect_lib));
+ expect(false, identical(F_new, G_new_lib));
+ expect(false, identical(F_new, G_named_lib));
+ expect(false, identical(F_new, G_fact_lib));
+ expect(false, identical(F_new, G_redirect_lib));
+ expect(false, identical(F_new, H_new));
+ expect(false, identical(F_new, H_named));
+ expect(false, identical(F_new, H_fact));
+ expect(false, identical(F_new, H_redirect));
+
+ expect(false, identical(F_named, F_new_lib));
+ expect(true, identical(F_named, F_named_lib));
+ expect(false, identical(F_named, F_fact_lib));
+ expect(false, identical(F_named, F_redirect_lib));
+ expect(false, identical(F_named, G_new_lib));
+ expect(false, identical(F_named, G_named_lib));
+ expect(false, identical(F_named, G_fact_lib));
+ expect(false, identical(F_named, G_redirect_lib));
+ expect(false, identical(F_named, H_new));
+ expect(false, identical(F_named, H_named));
+ expect(false, identical(F_named, H_fact));
+ expect(false, identical(F_named, H_redirect));
+
+ expect(false, identical(F_fact, F_new_lib));
+ expect(false, identical(F_fact, F_named_lib));
+ expect(true, identical(F_fact, F_fact_lib));
+ expect(false, identical(F_fact, F_redirect_lib));
+ expect(false, identical(F_fact, G_new_lib));
+ expect(false, identical(F_fact, G_named_lib));
+ expect(false, identical(F_fact, G_fact_lib));
+ expect(false, identical(F_fact, G_redirect_lib));
+ expect(false, identical(F_fact, H_new));
+ expect(false, identical(F_fact, H_named));
+ expect(false, identical(F_fact, H_fact));
+ expect(false, identical(F_fact, H_redirect));
+
+ expect(false, identical(F_redirect, F_new_lib));
+ expect(false, identical(F_redirect, F_named_lib));
+ expect(false, identical(F_redirect, F_fact_lib));
+ expect(true, identical(F_redirect, F_redirect_lib));
+ expect(false, identical(F_redirect, G_new_lib));
+ expect(false, identical(F_redirect, G_named_lib));
+ expect(false, identical(F_redirect, G_fact_lib));
+ expect(false, identical(F_redirect, G_redirect_lib));
+ expect(false, identical(F_redirect, H_new));
+ expect(false, identical(F_redirect, H_named));
+ expect(false, identical(F_redirect, H_fact));
+ expect(false, identical(F_redirect, H_redirect));
+}
+
+
+expect(expected, actual) {
+ if (expected != actual) throw 'Expected $expected, actual $actual';
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.strong.expect
new file mode 100644
index 0000000..2dc1f69
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.strong.expect
@@ -0,0 +1,147 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "main_lib.dart" as mai;
+
+import "org-dartlang-testcase:///main_lib.dart";
+
+typedef H<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = mai::A<Y%>;
+static field dynamic H_new = #C1;
+static field dynamic H_named = #C2;
+static field dynamic H_fact = #C3;
+static field dynamic H_redirect = #C4;
+static field dynamic F_new = #C5;
+static field dynamic F_named = #C6;
+static field dynamic F_fact = #C7;
+static field dynamic F_redirect = #C8;
+static method main() → dynamic {
+ self::expect(true, core::identical(self::F_new, mai::F_new_lib));
+ self::expect(false, core::identical(self::F_new, mai::F_named_lib));
+ self::expect(false, core::identical(self::F_new, mai::F_fact_lib));
+ self::expect(false, core::identical(self::F_new, mai::F_redirect_lib));
+ self::expect(false, core::identical(self::F_new, mai::G_new_lib));
+ self::expect(false, core::identical(self::F_new, mai::G_named_lib));
+ self::expect(false, core::identical(self::F_new, mai::G_fact_lib));
+ self::expect(false, core::identical(self::F_new, mai::G_redirect_lib));
+ self::expect(false, core::identical(self::F_new, self::H_new));
+ self::expect(false, core::identical(self::F_new, self::H_named));
+ self::expect(false, core::identical(self::F_new, self::H_fact));
+ self::expect(false, core::identical(self::F_new, self::H_redirect));
+ self::expect(false, core::identical(self::F_named, mai::F_new_lib));
+ self::expect(true, core::identical(self::F_named, mai::F_named_lib));
+ self::expect(false, core::identical(self::F_named, mai::F_fact_lib));
+ self::expect(false, core::identical(self::F_named, mai::F_redirect_lib));
+ self::expect(false, core::identical(self::F_named, mai::G_new_lib));
+ self::expect(false, core::identical(self::F_named, mai::G_named_lib));
+ self::expect(false, core::identical(self::F_named, mai::G_fact_lib));
+ self::expect(false, core::identical(self::F_named, mai::G_redirect_lib));
+ self::expect(false, core::identical(self::F_named, self::H_new));
+ self::expect(false, core::identical(self::F_named, self::H_named));
+ self::expect(false, core::identical(self::F_named, self::H_fact));
+ self::expect(false, core::identical(self::F_named, self::H_redirect));
+ self::expect(false, core::identical(self::F_fact, mai::F_new_lib));
+ self::expect(false, core::identical(self::F_fact, mai::F_named_lib));
+ self::expect(true, core::identical(self::F_fact, mai::F_fact_lib));
+ self::expect(false, core::identical(self::F_fact, mai::F_redirect_lib));
+ self::expect(false, core::identical(self::F_fact, mai::G_new_lib));
+ self::expect(false, core::identical(self::F_fact, mai::G_named_lib));
+ self::expect(false, core::identical(self::F_fact, mai::G_fact_lib));
+ self::expect(false, core::identical(self::F_fact, mai::G_redirect_lib));
+ self::expect(false, core::identical(self::F_fact, self::H_new));
+ self::expect(false, core::identical(self::F_fact, self::H_named));
+ self::expect(false, core::identical(self::F_fact, self::H_fact));
+ self::expect(false, core::identical(self::F_fact, self::H_redirect));
+ self::expect(false, core::identical(self::F_redirect, mai::F_new_lib));
+ self::expect(false, core::identical(self::F_redirect, mai::F_named_lib));
+ self::expect(false, core::identical(self::F_redirect, mai::F_fact_lib));
+ self::expect(true, core::identical(self::F_redirect, mai::F_redirect_lib));
+ self::expect(false, core::identical(self::F_redirect, mai::G_new_lib));
+ self::expect(false, core::identical(self::F_redirect, mai::G_named_lib));
+ self::expect(false, core::identical(self::F_redirect, mai::G_fact_lib));
+ self::expect(false, core::identical(self::F_redirect, mai::G_redirect_lib));
+ self::expect(false, core::identical(self::F_redirect, self::H_new));
+ self::expect(false, core::identical(self::F_redirect, self::H_named));
+ self::expect(false, core::identical(self::F_redirect, self::H_fact));
+ self::expect(false, core::identical(self::F_redirect, self::H_redirect));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method _#H#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<self::_#H#fact#tearOff::Y%>
+ return mai::A::fact<self::_#H#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#H#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<self::_#H#redirect#tearOff::Y%>
+ return mai::A::_#redirect#tearOff<self::_#H#redirect#tearOff::Y%>();
+static method _#H#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<self::_#H#new#tearOff::Y%>
+ return new mai::A::•<self::_#H#new#tearOff::Y%>();
+static method _#H#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#named#tearOff::Y% a, [core::int? b = #C9]) → mai::A<self::_#H#named#tearOff::Y%>
+ return new mai::A::named<self::_#H#named#tearOff::Y%>(a, b);
+
+library /*isNonNullableByDefault*/;
+import self as mai;
+import "dart:core" as core;
+
+typedef F<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = mai::A<Y%>;
+typedef G<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = mai::A<Y%>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[mai::A::redirect]/*isLegacy*/;
+ constructor •() → mai::A<mai::A::T%>
+ : super core::Object::•()
+ ;
+ constructor named(mai::A::T% a, [core::int? b = #C9]) → mai::A<mai::A::T%>
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → mai::A<mai::A::_#new#tearOff::T%>
+ return new mai::A::•<mai::A::_#new#tearOff::T%>();
+ static method _#named#tearOff<T extends core::Object? = dynamic>(mai::A::_#named#tearOff::T% a, [core::int? b = #C9]) → mai::A<mai::A::_#named#tearOff::T%>
+ return new mai::A::named<mai::A::_#named#tearOff::T%>(a, b);
+ static factory fact<T extends core::Object? = dynamic>(mai::A::fact::T% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<mai::A::fact::T%>
+ return new mai::A::•<mai::A::fact::T%>();
+ static method _#fact#tearOff<T extends core::Object? = dynamic>(mai::A::_#fact#tearOff::T% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<mai::A::_#fact#tearOff::T%>
+ return mai::A::fact<mai::A::_#fact#tearOff::T%>(a, b: b, c: c);
+ static factory redirect<T extends core::Object? = dynamic>() → mai::A<mai::A::redirect::T%>
+ let dynamic #redirecting_factory = mai::A::• in let mai::A::redirect::T% #typeArg0 = null in invalid-expression;
+ static method _#redirect#tearOff<T extends core::Object? = dynamic>() → mai::A<mai::A::_#redirect#tearOff::T%>
+ return new mai::A::•<mai::A::_#redirect#tearOff::T%>();
+}
+static field dynamic F_new_lib = #C5;
+static field dynamic F_named_lib = #C6;
+static field dynamic F_fact_lib = #C7;
+static field dynamic F_redirect_lib = #C8;
+static field dynamic G_new_lib = #C11;
+static field dynamic G_named_lib = #C12;
+static field dynamic G_fact_lib = #C13;
+static field dynamic G_redirect_lib = #C14;
+static method _#F#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#F#new#tearOff::Y%>
+ return new mai::A::•<mai::_#F#new#tearOff::Y%>();
+static method _#F#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#F#named#tearOff::Y% a, [core::int? b = #C9]) → mai::A<mai::_#F#named#tearOff::Y%>
+ return new mai::A::named<mai::_#F#named#tearOff::Y%>(a, b);
+static method _#F#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#F#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<mai::_#F#fact#tearOff::Y%>
+ return mai::A::fact<mai::_#F#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#F#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#F#redirect#tearOff::Y%>
+ return mai::A::_#redirect#tearOff<mai::_#F#redirect#tearOff::Y%>();
+static method _#G#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#G#new#tearOff::Y%>
+ return new mai::A::•<mai::_#G#new#tearOff::Y%>();
+static method _#G#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#G#named#tearOff::Y% a, [core::int? b = #C9]) → mai::A<mai::_#G#named#tearOff::Y%>
+ return new mai::A::named<mai::_#G#named#tearOff::Y%>(a, b);
+static method _#G#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#G#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<mai::_#G#fact#tearOff::Y%>
+ return mai::A::fact<mai::_#G#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#G#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#G#redirect#tearOff::Y%>
+ return mai::A::_#redirect#tearOff<mai::_#G#redirect#tearOff::Y%>();
+
+constants {
+ #C1 = static-tearoff self::_#H#new#tearOff
+ #C2 = static-tearoff self::_#H#named#tearOff
+ #C3 = static-tearoff self::_#H#fact#tearOff
+ #C4 = static-tearoff self::_#H#redirect#tearOff
+ #C5 = static-tearoff mai::_#F#new#tearOff
+ #C6 = static-tearoff mai::_#F#named#tearOff
+ #C7 = static-tearoff mai::_#F#fact#tearOff
+ #C8 = static-tearoff mai::_#F#redirect#tearOff
+ #C9 = null
+ #C10 = 42
+ #C11 = static-tearoff mai::_#G#new#tearOff
+ #C12 = static-tearoff mai::_#G#named#tearOff
+ #C13 = static-tearoff mai::_#G#fact#tearOff
+ #C14 = static-tearoff mai::_#G#redirect#tearOff
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.strong.transformed.expect
new file mode 100644
index 0000000..a5b6962
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.strong.transformed.expect
@@ -0,0 +1,147 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "main_lib.dart" as mai;
+
+import "org-dartlang-testcase:///main_lib.dart";
+
+typedef H<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = mai::A<Y%>;
+static field dynamic H_new = #C1;
+static field dynamic H_named = #C2;
+static field dynamic H_fact = #C3;
+static field dynamic H_redirect = #C4;
+static field dynamic F_new = #C5;
+static field dynamic F_named = #C6;
+static field dynamic F_fact = #C7;
+static field dynamic F_redirect = #C8;
+static method main() → dynamic {
+ self::expect(true, core::identical(self::F_new, mai::F_new_lib));
+ self::expect(false, core::identical(self::F_new, mai::F_named_lib));
+ self::expect(false, core::identical(self::F_new, mai::F_fact_lib));
+ self::expect(false, core::identical(self::F_new, mai::F_redirect_lib));
+ self::expect(false, core::identical(self::F_new, mai::G_new_lib));
+ self::expect(false, core::identical(self::F_new, mai::G_named_lib));
+ self::expect(false, core::identical(self::F_new, mai::G_fact_lib));
+ self::expect(false, core::identical(self::F_new, mai::G_redirect_lib));
+ self::expect(false, core::identical(self::F_new, self::H_new));
+ self::expect(false, core::identical(self::F_new, self::H_named));
+ self::expect(false, core::identical(self::F_new, self::H_fact));
+ self::expect(false, core::identical(self::F_new, self::H_redirect));
+ self::expect(false, core::identical(self::F_named, mai::F_new_lib));
+ self::expect(true, core::identical(self::F_named, mai::F_named_lib));
+ self::expect(false, core::identical(self::F_named, mai::F_fact_lib));
+ self::expect(false, core::identical(self::F_named, mai::F_redirect_lib));
+ self::expect(false, core::identical(self::F_named, mai::G_new_lib));
+ self::expect(false, core::identical(self::F_named, mai::G_named_lib));
+ self::expect(false, core::identical(self::F_named, mai::G_fact_lib));
+ self::expect(false, core::identical(self::F_named, mai::G_redirect_lib));
+ self::expect(false, core::identical(self::F_named, self::H_new));
+ self::expect(false, core::identical(self::F_named, self::H_named));
+ self::expect(false, core::identical(self::F_named, self::H_fact));
+ self::expect(false, core::identical(self::F_named, self::H_redirect));
+ self::expect(false, core::identical(self::F_fact, mai::F_new_lib));
+ self::expect(false, core::identical(self::F_fact, mai::F_named_lib));
+ self::expect(true, core::identical(self::F_fact, mai::F_fact_lib));
+ self::expect(false, core::identical(self::F_fact, mai::F_redirect_lib));
+ self::expect(false, core::identical(self::F_fact, mai::G_new_lib));
+ self::expect(false, core::identical(self::F_fact, mai::G_named_lib));
+ self::expect(false, core::identical(self::F_fact, mai::G_fact_lib));
+ self::expect(false, core::identical(self::F_fact, mai::G_redirect_lib));
+ self::expect(false, core::identical(self::F_fact, self::H_new));
+ self::expect(false, core::identical(self::F_fact, self::H_named));
+ self::expect(false, core::identical(self::F_fact, self::H_fact));
+ self::expect(false, core::identical(self::F_fact, self::H_redirect));
+ self::expect(false, core::identical(self::F_redirect, mai::F_new_lib));
+ self::expect(false, core::identical(self::F_redirect, mai::F_named_lib));
+ self::expect(false, core::identical(self::F_redirect, mai::F_fact_lib));
+ self::expect(true, core::identical(self::F_redirect, mai::F_redirect_lib));
+ self::expect(false, core::identical(self::F_redirect, mai::G_new_lib));
+ self::expect(false, core::identical(self::F_redirect, mai::G_named_lib));
+ self::expect(false, core::identical(self::F_redirect, mai::G_fact_lib));
+ self::expect(false, core::identical(self::F_redirect, mai::G_redirect_lib));
+ self::expect(false, core::identical(self::F_redirect, self::H_new));
+ self::expect(false, core::identical(self::F_redirect, self::H_named));
+ self::expect(false, core::identical(self::F_redirect, self::H_fact));
+ self::expect(false, core::identical(self::F_redirect, self::H_redirect));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method _#H#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<self::_#H#fact#tearOff::Y%>
+ return mai::A::fact<self::_#H#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#H#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<self::_#H#redirect#tearOff::Y%>
+ return mai::A::_#redirect#tearOff<self::_#H#redirect#tearOff::Y%>();
+static method _#H#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<self::_#H#new#tearOff::Y%>
+ return new mai::A::•<self::_#H#new#tearOff::Y%>();
+static method _#H#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#named#tearOff::Y% a, [core::int? b = #C9]) → mai::A<self::_#H#named#tearOff::Y%>
+ return new mai::A::named<self::_#H#named#tearOff::Y%>(a, b);
+
+library /*isNonNullableByDefault*/;
+import self as mai;
+import "dart:core" as core;
+
+typedef F<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = mai::A<Y%>;
+typedef G<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = mai::A<Y%>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[mai::A::redirect]/*isLegacy*/;
+ constructor •() → mai::A<mai::A::T%>
+ : super core::Object::•()
+ ;
+ constructor named(mai::A::T% a, [core::int? b = #C9]) → mai::A<mai::A::T%>
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → mai::A<mai::A::_#new#tearOff::T%>
+ return new mai::A::•<mai::A::_#new#tearOff::T%>();
+ static method _#named#tearOff<T extends core::Object? = dynamic>(mai::A::_#named#tearOff::T% a, [core::int? b = #C9]) → mai::A<mai::A::_#named#tearOff::T%>
+ return new mai::A::named<mai::A::_#named#tearOff::T%>(a, b);
+ static factory fact<T extends core::Object? = dynamic>(mai::A::fact::T% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<mai::A::fact::T%>
+ return new mai::A::•<mai::A::fact::T%>();
+ static method _#fact#tearOff<T extends core::Object? = dynamic>(mai::A::_#fact#tearOff::T% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<mai::A::_#fact#tearOff::T%>
+ return mai::A::fact<mai::A::_#fact#tearOff::T%>(a, b: b, c: c);
+ static factory redirect<T extends core::Object? = dynamic>() → mai::A<mai::A::redirect::T%>
+ let Never #redirecting_factory = mai::A::• in let mai::A::redirect::T% #typeArg0 = null in invalid-expression;
+ static method _#redirect#tearOff<T extends core::Object? = dynamic>() → mai::A<mai::A::_#redirect#tearOff::T%>
+ return new mai::A::•<mai::A::_#redirect#tearOff::T%>();
+}
+static field dynamic F_new_lib = #C5;
+static field dynamic F_named_lib = #C6;
+static field dynamic F_fact_lib = #C7;
+static field dynamic F_redirect_lib = #C8;
+static field dynamic G_new_lib = #C11;
+static field dynamic G_named_lib = #C12;
+static field dynamic G_fact_lib = #C13;
+static field dynamic G_redirect_lib = #C14;
+static method _#F#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#F#new#tearOff::Y%>
+ return new mai::A::•<mai::_#F#new#tearOff::Y%>();
+static method _#F#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#F#named#tearOff::Y% a, [core::int? b = #C9]) → mai::A<mai::_#F#named#tearOff::Y%>
+ return new mai::A::named<mai::_#F#named#tearOff::Y%>(a, b);
+static method _#F#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#F#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<mai::_#F#fact#tearOff::Y%>
+ return mai::A::fact<mai::_#F#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#F#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#F#redirect#tearOff::Y%>
+ return mai::A::_#redirect#tearOff<mai::_#F#redirect#tearOff::Y%>();
+static method _#G#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#G#new#tearOff::Y%>
+ return new mai::A::•<mai::_#G#new#tearOff::Y%>();
+static method _#G#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#G#named#tearOff::Y% a, [core::int? b = #C9]) → mai::A<mai::_#G#named#tearOff::Y%>
+ return new mai::A::named<mai::_#G#named#tearOff::Y%>(a, b);
+static method _#G#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#G#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<mai::_#G#fact#tearOff::Y%>
+ return mai::A::fact<mai::_#G#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#G#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#G#redirect#tearOff::Y%>
+ return mai::A::_#redirect#tearOff<mai::_#G#redirect#tearOff::Y%>();
+
+constants {
+ #C1 = static-tearoff self::_#H#new#tearOff
+ #C2 = static-tearoff self::_#H#named#tearOff
+ #C3 = static-tearoff self::_#H#fact#tearOff
+ #C4 = static-tearoff self::_#H#redirect#tearOff
+ #C5 = static-tearoff mai::_#F#new#tearOff
+ #C6 = static-tearoff mai::_#F#named#tearOff
+ #C7 = static-tearoff mai::_#F#fact#tearOff
+ #C8 = static-tearoff mai::_#F#redirect#tearOff
+ #C9 = null
+ #C10 = 42
+ #C11 = static-tearoff mai::_#G#new#tearOff
+ #C12 = static-tearoff mai::_#G#named#tearOff
+ #C13 = static-tearoff mai::_#G#fact#tearOff
+ #C14 = static-tearoff mai::_#G#redirect#tearOff
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.textual_outline.expect
new file mode 100644
index 0000000..4d2dfc1
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.textual_outline.expect
@@ -0,0 +1,12 @@
+import 'main_lib.dart';
+typedef H<X, Y> = A<Y>;
+dynamic H_new = H.new;
+dynamic H_named = H.named;
+dynamic H_fact = H.fact;
+dynamic H_redirect = H.redirect;
+dynamic F_new = F.new;
+dynamic F_named = F.named;
+dynamic F_fact = F.fact;
+dynamic F_redirect = F.redirect;
+main() {}
+expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.weak.expect
new file mode 100644
index 0000000..2dc1f69
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.weak.expect
@@ -0,0 +1,147 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "main_lib.dart" as mai;
+
+import "org-dartlang-testcase:///main_lib.dart";
+
+typedef H<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = mai::A<Y%>;
+static field dynamic H_new = #C1;
+static field dynamic H_named = #C2;
+static field dynamic H_fact = #C3;
+static field dynamic H_redirect = #C4;
+static field dynamic F_new = #C5;
+static field dynamic F_named = #C6;
+static field dynamic F_fact = #C7;
+static field dynamic F_redirect = #C8;
+static method main() → dynamic {
+ self::expect(true, core::identical(self::F_new, mai::F_new_lib));
+ self::expect(false, core::identical(self::F_new, mai::F_named_lib));
+ self::expect(false, core::identical(self::F_new, mai::F_fact_lib));
+ self::expect(false, core::identical(self::F_new, mai::F_redirect_lib));
+ self::expect(false, core::identical(self::F_new, mai::G_new_lib));
+ self::expect(false, core::identical(self::F_new, mai::G_named_lib));
+ self::expect(false, core::identical(self::F_new, mai::G_fact_lib));
+ self::expect(false, core::identical(self::F_new, mai::G_redirect_lib));
+ self::expect(false, core::identical(self::F_new, self::H_new));
+ self::expect(false, core::identical(self::F_new, self::H_named));
+ self::expect(false, core::identical(self::F_new, self::H_fact));
+ self::expect(false, core::identical(self::F_new, self::H_redirect));
+ self::expect(false, core::identical(self::F_named, mai::F_new_lib));
+ self::expect(true, core::identical(self::F_named, mai::F_named_lib));
+ self::expect(false, core::identical(self::F_named, mai::F_fact_lib));
+ self::expect(false, core::identical(self::F_named, mai::F_redirect_lib));
+ self::expect(false, core::identical(self::F_named, mai::G_new_lib));
+ self::expect(false, core::identical(self::F_named, mai::G_named_lib));
+ self::expect(false, core::identical(self::F_named, mai::G_fact_lib));
+ self::expect(false, core::identical(self::F_named, mai::G_redirect_lib));
+ self::expect(false, core::identical(self::F_named, self::H_new));
+ self::expect(false, core::identical(self::F_named, self::H_named));
+ self::expect(false, core::identical(self::F_named, self::H_fact));
+ self::expect(false, core::identical(self::F_named, self::H_redirect));
+ self::expect(false, core::identical(self::F_fact, mai::F_new_lib));
+ self::expect(false, core::identical(self::F_fact, mai::F_named_lib));
+ self::expect(true, core::identical(self::F_fact, mai::F_fact_lib));
+ self::expect(false, core::identical(self::F_fact, mai::F_redirect_lib));
+ self::expect(false, core::identical(self::F_fact, mai::G_new_lib));
+ self::expect(false, core::identical(self::F_fact, mai::G_named_lib));
+ self::expect(false, core::identical(self::F_fact, mai::G_fact_lib));
+ self::expect(false, core::identical(self::F_fact, mai::G_redirect_lib));
+ self::expect(false, core::identical(self::F_fact, self::H_new));
+ self::expect(false, core::identical(self::F_fact, self::H_named));
+ self::expect(false, core::identical(self::F_fact, self::H_fact));
+ self::expect(false, core::identical(self::F_fact, self::H_redirect));
+ self::expect(false, core::identical(self::F_redirect, mai::F_new_lib));
+ self::expect(false, core::identical(self::F_redirect, mai::F_named_lib));
+ self::expect(false, core::identical(self::F_redirect, mai::F_fact_lib));
+ self::expect(true, core::identical(self::F_redirect, mai::F_redirect_lib));
+ self::expect(false, core::identical(self::F_redirect, mai::G_new_lib));
+ self::expect(false, core::identical(self::F_redirect, mai::G_named_lib));
+ self::expect(false, core::identical(self::F_redirect, mai::G_fact_lib));
+ self::expect(false, core::identical(self::F_redirect, mai::G_redirect_lib));
+ self::expect(false, core::identical(self::F_redirect, self::H_new));
+ self::expect(false, core::identical(self::F_redirect, self::H_named));
+ self::expect(false, core::identical(self::F_redirect, self::H_fact));
+ self::expect(false, core::identical(self::F_redirect, self::H_redirect));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method _#H#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<self::_#H#fact#tearOff::Y%>
+ return mai::A::fact<self::_#H#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#H#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<self::_#H#redirect#tearOff::Y%>
+ return mai::A::_#redirect#tearOff<self::_#H#redirect#tearOff::Y%>();
+static method _#H#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<self::_#H#new#tearOff::Y%>
+ return new mai::A::•<self::_#H#new#tearOff::Y%>();
+static method _#H#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#named#tearOff::Y% a, [core::int? b = #C9]) → mai::A<self::_#H#named#tearOff::Y%>
+ return new mai::A::named<self::_#H#named#tearOff::Y%>(a, b);
+
+library /*isNonNullableByDefault*/;
+import self as mai;
+import "dart:core" as core;
+
+typedef F<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = mai::A<Y%>;
+typedef G<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = mai::A<Y%>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[mai::A::redirect]/*isLegacy*/;
+ constructor •() → mai::A<mai::A::T%>
+ : super core::Object::•()
+ ;
+ constructor named(mai::A::T% a, [core::int? b = #C9]) → mai::A<mai::A::T%>
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → mai::A<mai::A::_#new#tearOff::T%>
+ return new mai::A::•<mai::A::_#new#tearOff::T%>();
+ static method _#named#tearOff<T extends core::Object? = dynamic>(mai::A::_#named#tearOff::T% a, [core::int? b = #C9]) → mai::A<mai::A::_#named#tearOff::T%>
+ return new mai::A::named<mai::A::_#named#tearOff::T%>(a, b);
+ static factory fact<T extends core::Object? = dynamic>(mai::A::fact::T% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<mai::A::fact::T%>
+ return new mai::A::•<mai::A::fact::T%>();
+ static method _#fact#tearOff<T extends core::Object? = dynamic>(mai::A::_#fact#tearOff::T% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<mai::A::_#fact#tearOff::T%>
+ return mai::A::fact<mai::A::_#fact#tearOff::T%>(a, b: b, c: c);
+ static factory redirect<T extends core::Object? = dynamic>() → mai::A<mai::A::redirect::T%>
+ let dynamic #redirecting_factory = mai::A::• in let mai::A::redirect::T% #typeArg0 = null in invalid-expression;
+ static method _#redirect#tearOff<T extends core::Object? = dynamic>() → mai::A<mai::A::_#redirect#tearOff::T%>
+ return new mai::A::•<mai::A::_#redirect#tearOff::T%>();
+}
+static field dynamic F_new_lib = #C5;
+static field dynamic F_named_lib = #C6;
+static field dynamic F_fact_lib = #C7;
+static field dynamic F_redirect_lib = #C8;
+static field dynamic G_new_lib = #C11;
+static field dynamic G_named_lib = #C12;
+static field dynamic G_fact_lib = #C13;
+static field dynamic G_redirect_lib = #C14;
+static method _#F#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#F#new#tearOff::Y%>
+ return new mai::A::•<mai::_#F#new#tearOff::Y%>();
+static method _#F#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#F#named#tearOff::Y% a, [core::int? b = #C9]) → mai::A<mai::_#F#named#tearOff::Y%>
+ return new mai::A::named<mai::_#F#named#tearOff::Y%>(a, b);
+static method _#F#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#F#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<mai::_#F#fact#tearOff::Y%>
+ return mai::A::fact<mai::_#F#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#F#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#F#redirect#tearOff::Y%>
+ return mai::A::_#redirect#tearOff<mai::_#F#redirect#tearOff::Y%>();
+static method _#G#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#G#new#tearOff::Y%>
+ return new mai::A::•<mai::_#G#new#tearOff::Y%>();
+static method _#G#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#G#named#tearOff::Y% a, [core::int? b = #C9]) → mai::A<mai::_#G#named#tearOff::Y%>
+ return new mai::A::named<mai::_#G#named#tearOff::Y%>(a, b);
+static method _#G#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#G#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<mai::_#G#fact#tearOff::Y%>
+ return mai::A::fact<mai::_#G#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#G#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#G#redirect#tearOff::Y%>
+ return mai::A::_#redirect#tearOff<mai::_#G#redirect#tearOff::Y%>();
+
+constants {
+ #C1 = static-tearoff self::_#H#new#tearOff
+ #C2 = static-tearoff self::_#H#named#tearOff
+ #C3 = static-tearoff self::_#H#fact#tearOff
+ #C4 = static-tearoff self::_#H#redirect#tearOff
+ #C5 = static-tearoff mai::_#F#new#tearOff
+ #C6 = static-tearoff mai::_#F#named#tearOff
+ #C7 = static-tearoff mai::_#F#fact#tearOff
+ #C8 = static-tearoff mai::_#F#redirect#tearOff
+ #C9 = null
+ #C10 = 42
+ #C11 = static-tearoff mai::_#G#new#tearOff
+ #C12 = static-tearoff mai::_#G#named#tearOff
+ #C13 = static-tearoff mai::_#G#fact#tearOff
+ #C14 = static-tearoff mai::_#G#redirect#tearOff
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.weak.outline.expect
new file mode 100644
index 0000000..f1af048
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.weak.outline.expect
@@ -0,0 +1,78 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "main_lib.dart" as mai;
+
+import "org-dartlang-testcase:///main_lib.dart";
+
+typedef H<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = mai::A<Y%>;
+static field dynamic H_new;
+static field dynamic H_named;
+static field dynamic H_fact;
+static field dynamic H_redirect;
+static field dynamic F_new;
+static field dynamic F_named;
+static field dynamic F_fact;
+static field dynamic F_redirect;
+static method main() → dynamic
+ ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+ ;
+static method _#H#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#fact#tearOff::Y% a, {core::int? b, core::int c}) → mai::A<self::_#H#fact#tearOff::Y%>
+ return mai::A::fact<self::_#H#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#H#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<self::_#H#redirect#tearOff::Y%>
+ return mai::A::_#redirect#tearOff<self::_#H#redirect#tearOff::Y%>();
+static method _#H#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<self::_#H#new#tearOff::Y%>
+ return new mai::A::•<self::_#H#new#tearOff::Y%>();
+static method _#H#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#named#tearOff::Y% a, [core::int? b]) → mai::A<self::_#H#named#tearOff::Y%>
+ return new mai::A::named<self::_#H#named#tearOff::Y%>(a, b);
+
+library /*isNonNullableByDefault*/;
+import self as mai;
+import "dart:core" as core;
+
+typedef F<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = mai::A<Y%>;
+typedef G<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = mai::A<Y%>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[mai::A::redirect]/*isLegacy*/;
+ constructor •() → mai::A<mai::A::T%>
+ ;
+ constructor named(mai::A::T% a, [core::int? b]) → mai::A<mai::A::T%>
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → mai::A<mai::A::_#new#tearOff::T%>
+ return new mai::A::•<mai::A::_#new#tearOff::T%>();
+ static method _#named#tearOff<T extends core::Object? = dynamic>(mai::A::_#named#tearOff::T% a, [core::int? b]) → mai::A<mai::A::_#named#tearOff::T%>
+ return new mai::A::named<mai::A::_#named#tearOff::T%>(a, b);
+ static factory fact<T extends core::Object? = dynamic>(mai::A::fact::T% a, {core::int? b, core::int c}) → mai::A<mai::A::fact::T%>
+ ;
+ static method _#fact#tearOff<T extends core::Object? = dynamic>(mai::A::_#fact#tearOff::T% a, {core::int? b, core::int c}) → mai::A<mai::A::_#fact#tearOff::T%>
+ return mai::A::fact<mai::A::_#fact#tearOff::T%>(a, b: b, c: c);
+ static factory redirect<T extends core::Object? = dynamic>() → mai::A<mai::A::redirect::T%>
+ let dynamic #redirecting_factory = mai::A::• in let mai::A::redirect::T% #typeArg0 = null in invalid-expression;
+ static method _#redirect#tearOff<T extends core::Object? = dynamic>() → mai::A<mai::A::_#redirect#tearOff::T%>
+ return new mai::A::•<mai::A::_#redirect#tearOff::T%>();
+}
+static field dynamic F_new_lib;
+static field dynamic F_named_lib;
+static field dynamic F_fact_lib;
+static field dynamic F_redirect_lib;
+static field dynamic G_new_lib;
+static field dynamic G_named_lib;
+static field dynamic G_fact_lib;
+static field dynamic G_redirect_lib;
+static method _#F#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#F#new#tearOff::Y%>
+ return new mai::A::•<mai::_#F#new#tearOff::Y%>();
+static method _#F#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#F#named#tearOff::Y% a, [core::int? b]) → mai::A<mai::_#F#named#tearOff::Y%>
+ return new mai::A::named<mai::_#F#named#tearOff::Y%>(a, b);
+static method _#F#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#F#fact#tearOff::Y% a, {core::int? b, core::int c}) → mai::A<mai::_#F#fact#tearOff::Y%>
+ return mai::A::fact<mai::_#F#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#F#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#F#redirect#tearOff::Y%>
+ return mai::A::_#redirect#tearOff<mai::_#F#redirect#tearOff::Y%>();
+static method _#G#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#G#new#tearOff::Y%>
+ return new mai::A::•<mai::_#G#new#tearOff::Y%>();
+static method _#G#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#G#named#tearOff::Y% a, [core::int? b]) → mai::A<mai::_#G#named#tearOff::Y%>
+ return new mai::A::named<mai::_#G#named#tearOff::Y%>(a, b);
+static method _#G#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#G#fact#tearOff::Y% a, {core::int? b, core::int c}) → mai::A<mai::_#G#fact#tearOff::Y%>
+ return mai::A::fact<mai::_#G#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#G#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#G#redirect#tearOff::Y%>
+ return mai::A::_#redirect#tearOff<mai::_#G#redirect#tearOff::Y%>();
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.weak.transformed.expect
new file mode 100644
index 0000000..a5b6962
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main.dart.weak.transformed.expect
@@ -0,0 +1,147 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "main_lib.dart" as mai;
+
+import "org-dartlang-testcase:///main_lib.dart";
+
+typedef H<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = mai::A<Y%>;
+static field dynamic H_new = #C1;
+static field dynamic H_named = #C2;
+static field dynamic H_fact = #C3;
+static field dynamic H_redirect = #C4;
+static field dynamic F_new = #C5;
+static field dynamic F_named = #C6;
+static field dynamic F_fact = #C7;
+static field dynamic F_redirect = #C8;
+static method main() → dynamic {
+ self::expect(true, core::identical(self::F_new, mai::F_new_lib));
+ self::expect(false, core::identical(self::F_new, mai::F_named_lib));
+ self::expect(false, core::identical(self::F_new, mai::F_fact_lib));
+ self::expect(false, core::identical(self::F_new, mai::F_redirect_lib));
+ self::expect(false, core::identical(self::F_new, mai::G_new_lib));
+ self::expect(false, core::identical(self::F_new, mai::G_named_lib));
+ self::expect(false, core::identical(self::F_new, mai::G_fact_lib));
+ self::expect(false, core::identical(self::F_new, mai::G_redirect_lib));
+ self::expect(false, core::identical(self::F_new, self::H_new));
+ self::expect(false, core::identical(self::F_new, self::H_named));
+ self::expect(false, core::identical(self::F_new, self::H_fact));
+ self::expect(false, core::identical(self::F_new, self::H_redirect));
+ self::expect(false, core::identical(self::F_named, mai::F_new_lib));
+ self::expect(true, core::identical(self::F_named, mai::F_named_lib));
+ self::expect(false, core::identical(self::F_named, mai::F_fact_lib));
+ self::expect(false, core::identical(self::F_named, mai::F_redirect_lib));
+ self::expect(false, core::identical(self::F_named, mai::G_new_lib));
+ self::expect(false, core::identical(self::F_named, mai::G_named_lib));
+ self::expect(false, core::identical(self::F_named, mai::G_fact_lib));
+ self::expect(false, core::identical(self::F_named, mai::G_redirect_lib));
+ self::expect(false, core::identical(self::F_named, self::H_new));
+ self::expect(false, core::identical(self::F_named, self::H_named));
+ self::expect(false, core::identical(self::F_named, self::H_fact));
+ self::expect(false, core::identical(self::F_named, self::H_redirect));
+ self::expect(false, core::identical(self::F_fact, mai::F_new_lib));
+ self::expect(false, core::identical(self::F_fact, mai::F_named_lib));
+ self::expect(true, core::identical(self::F_fact, mai::F_fact_lib));
+ self::expect(false, core::identical(self::F_fact, mai::F_redirect_lib));
+ self::expect(false, core::identical(self::F_fact, mai::G_new_lib));
+ self::expect(false, core::identical(self::F_fact, mai::G_named_lib));
+ self::expect(false, core::identical(self::F_fact, mai::G_fact_lib));
+ self::expect(false, core::identical(self::F_fact, mai::G_redirect_lib));
+ self::expect(false, core::identical(self::F_fact, self::H_new));
+ self::expect(false, core::identical(self::F_fact, self::H_named));
+ self::expect(false, core::identical(self::F_fact, self::H_fact));
+ self::expect(false, core::identical(self::F_fact, self::H_redirect));
+ self::expect(false, core::identical(self::F_redirect, mai::F_new_lib));
+ self::expect(false, core::identical(self::F_redirect, mai::F_named_lib));
+ self::expect(false, core::identical(self::F_redirect, mai::F_fact_lib));
+ self::expect(true, core::identical(self::F_redirect, mai::F_redirect_lib));
+ self::expect(false, core::identical(self::F_redirect, mai::G_new_lib));
+ self::expect(false, core::identical(self::F_redirect, mai::G_named_lib));
+ self::expect(false, core::identical(self::F_redirect, mai::G_fact_lib));
+ self::expect(false, core::identical(self::F_redirect, mai::G_redirect_lib));
+ self::expect(false, core::identical(self::F_redirect, self::H_new));
+ self::expect(false, core::identical(self::F_redirect, self::H_named));
+ self::expect(false, core::identical(self::F_redirect, self::H_fact));
+ self::expect(false, core::identical(self::F_redirect, self::H_redirect));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method _#H#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<self::_#H#fact#tearOff::Y%>
+ return mai::A::fact<self::_#H#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#H#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<self::_#H#redirect#tearOff::Y%>
+ return mai::A::_#redirect#tearOff<self::_#H#redirect#tearOff::Y%>();
+static method _#H#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<self::_#H#new#tearOff::Y%>
+ return new mai::A::•<self::_#H#new#tearOff::Y%>();
+static method _#H#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#named#tearOff::Y% a, [core::int? b = #C9]) → mai::A<self::_#H#named#tearOff::Y%>
+ return new mai::A::named<self::_#H#named#tearOff::Y%>(a, b);
+
+library /*isNonNullableByDefault*/;
+import self as mai;
+import "dart:core" as core;
+
+typedef F<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = mai::A<Y%>;
+typedef G<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = mai::A<Y%>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[mai::A::redirect]/*isLegacy*/;
+ constructor •() → mai::A<mai::A::T%>
+ : super core::Object::•()
+ ;
+ constructor named(mai::A::T% a, [core::int? b = #C9]) → mai::A<mai::A::T%>
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → mai::A<mai::A::_#new#tearOff::T%>
+ return new mai::A::•<mai::A::_#new#tearOff::T%>();
+ static method _#named#tearOff<T extends core::Object? = dynamic>(mai::A::_#named#tearOff::T% a, [core::int? b = #C9]) → mai::A<mai::A::_#named#tearOff::T%>
+ return new mai::A::named<mai::A::_#named#tearOff::T%>(a, b);
+ static factory fact<T extends core::Object? = dynamic>(mai::A::fact::T% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<mai::A::fact::T%>
+ return new mai::A::•<mai::A::fact::T%>();
+ static method _#fact#tearOff<T extends core::Object? = dynamic>(mai::A::_#fact#tearOff::T% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<mai::A::_#fact#tearOff::T%>
+ return mai::A::fact<mai::A::_#fact#tearOff::T%>(a, b: b, c: c);
+ static factory redirect<T extends core::Object? = dynamic>() → mai::A<mai::A::redirect::T%>
+ let Never #redirecting_factory = mai::A::• in let mai::A::redirect::T% #typeArg0 = null in invalid-expression;
+ static method _#redirect#tearOff<T extends core::Object? = dynamic>() → mai::A<mai::A::_#redirect#tearOff::T%>
+ return new mai::A::•<mai::A::_#redirect#tearOff::T%>();
+}
+static field dynamic F_new_lib = #C5;
+static field dynamic F_named_lib = #C6;
+static field dynamic F_fact_lib = #C7;
+static field dynamic F_redirect_lib = #C8;
+static field dynamic G_new_lib = #C11;
+static field dynamic G_named_lib = #C12;
+static field dynamic G_fact_lib = #C13;
+static field dynamic G_redirect_lib = #C14;
+static method _#F#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#F#new#tearOff::Y%>
+ return new mai::A::•<mai::_#F#new#tearOff::Y%>();
+static method _#F#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#F#named#tearOff::Y% a, [core::int? b = #C9]) → mai::A<mai::_#F#named#tearOff::Y%>
+ return new mai::A::named<mai::_#F#named#tearOff::Y%>(a, b);
+static method _#F#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#F#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<mai::_#F#fact#tearOff::Y%>
+ return mai::A::fact<mai::_#F#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#F#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#F#redirect#tearOff::Y%>
+ return mai::A::_#redirect#tearOff<mai::_#F#redirect#tearOff::Y%>();
+static method _#G#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#G#new#tearOff::Y%>
+ return new mai::A::•<mai::_#G#new#tearOff::Y%>();
+static method _#G#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#G#named#tearOff::Y% a, [core::int? b = #C9]) → mai::A<mai::_#G#named#tearOff::Y%>
+ return new mai::A::named<mai::_#G#named#tearOff::Y%>(a, b);
+static method _#G#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(mai::_#G#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → mai::A<mai::_#G#fact#tearOff::Y%>
+ return mai::A::fact<mai::_#G#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#G#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → mai::A<mai::_#G#redirect#tearOff::Y%>
+ return mai::A::_#redirect#tearOff<mai::_#G#redirect#tearOff::Y%>();
+
+constants {
+ #C1 = static-tearoff self::_#H#new#tearOff
+ #C2 = static-tearoff self::_#H#named#tearOff
+ #C3 = static-tearoff self::_#H#fact#tearOff
+ #C4 = static-tearoff self::_#H#redirect#tearOff
+ #C5 = static-tearoff mai::_#F#new#tearOff
+ #C6 = static-tearoff mai::_#F#named#tearOff
+ #C7 = static-tearoff mai::_#F#fact#tearOff
+ #C8 = static-tearoff mai::_#F#redirect#tearOff
+ #C9 = null
+ #C10 = 42
+ #C11 = static-tearoff mai::_#G#new#tearOff
+ #C12 = static-tearoff mai::_#G#named#tearOff
+ #C13 = static-tearoff mai::_#G#fact#tearOff
+ #C14 = static-tearoff mai::_#G#redirect#tearOff
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main_lib.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main_lib.dart
new file mode 100644
index 0000000..a57b86b
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/main_lib.dart
@@ -0,0 +1,23 @@
+// 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 A<T> {
+ A();
+ A.named(T a, [int? b]);
+ factory A.fact(T a, {int? b, int c = 42}) => new A();
+ factory A.redirect() = A;
+}
+
+typedef F<X, Y> = A<Y>;
+typedef G<X, Y> = A<Y>;
+
+dynamic F_new_lib = F.new;
+dynamic F_named_lib = F.named;
+dynamic F_fact_lib = F.fact;
+dynamic F_redirect_lib = F.redirect;
+
+dynamic G_new_lib = G.new;
+dynamic G_named_lib = G.named;
+dynamic G_fact_lib = G.fact;
+dynamic G_redirect_lib = G.redirect;
\ No newline at end of file
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/test.options b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/test.options
new file mode 100644
index 0000000..bfe6dc8
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_from_dill/test.options
@@ -0,0 +1 @@
+main_lib.dart
\ No newline at end of file
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart
new file mode 100644
index 0000000..33453f6
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart
@@ -0,0 +1,76 @@
+// 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.
+
+import 'typedef_identical_lib.dart';
+
+typedef H<X, Y> = A<Y>;
+
+var H_new = H.new;
+var H_named = H.named;
+var H_fact = H.fact;
+var H_redirect = H.redirect;
+
+var F_new = F.new;
+var F_named = F.named;
+var F_fact = F.fact;
+var F_redirect = F.redirect;
+
+main() {
+ expect(true, identical(F_new, F_new_lib));
+ expect(false, identical(F_new, F_named_lib));
+ expect(false, identical(F_new, F_fact_lib));
+ expect(false, identical(F_new, F_redirect_lib));
+ expect(false, identical(F_new, G_new_lib));
+ expect(false, identical(F_new, G_named_lib));
+ expect(false, identical(F_new, G_fact_lib));
+ expect(false, identical(F_new, G_redirect_lib));
+ expect(false, identical(F_new, H_new));
+ expect(false, identical(F_new, H_named));
+ expect(false, identical(F_new, H_fact));
+ expect(false, identical(F_new, H_redirect));
+
+ expect(false, identical(F_named, F_new_lib));
+ expect(true, identical(F_named, F_named_lib));
+ expect(false, identical(F_named, F_fact_lib));
+ expect(false, identical(F_named, F_redirect_lib));
+ expect(false, identical(F_named, G_new_lib));
+ expect(false, identical(F_named, G_named_lib));
+ expect(false, identical(F_named, G_fact_lib));
+ expect(false, identical(F_named, G_redirect_lib));
+ expect(false, identical(F_named, H_new));
+ expect(false, identical(F_named, H_named));
+ expect(false, identical(F_named, H_fact));
+ expect(false, identical(F_named, H_redirect));
+
+ expect(false, identical(F_fact, F_new_lib));
+ expect(false, identical(F_fact, F_named_lib));
+ expect(true, identical(F_fact, F_fact_lib));
+ expect(false, identical(F_fact, F_redirect_lib));
+ expect(false, identical(F_fact, G_new_lib));
+ expect(false, identical(F_fact, G_named_lib));
+ expect(false, identical(F_fact, G_fact_lib));
+ expect(false, identical(F_fact, G_redirect_lib));
+ expect(false, identical(F_fact, H_new));
+ expect(false, identical(F_fact, H_named));
+ expect(false, identical(F_fact, H_fact));
+ expect(false, identical(F_fact, H_redirect));
+
+ expect(false, identical(F_redirect, F_new_lib));
+ expect(false, identical(F_redirect, F_named_lib));
+ expect(false, identical(F_redirect, F_fact_lib));
+ expect(true, identical(F_redirect, F_redirect_lib));
+ expect(false, identical(F_redirect, G_new_lib));
+ expect(false, identical(F_redirect, G_named_lib));
+ expect(false, identical(F_redirect, G_fact_lib));
+ expect(false, identical(F_redirect, G_redirect_lib));
+ expect(false, identical(F_redirect, H_new));
+ expect(false, identical(F_redirect, H_named));
+ expect(false, identical(F_redirect, H_fact));
+ expect(false, identical(F_redirect, H_redirect));
+}
+
+
+expect(expected, actual) {
+ if (expected != actual) throw 'Expected $expected, actual $actual';
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.strong.expect
new file mode 100644
index 0000000..3e82a43
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.strong.expect
@@ -0,0 +1,147 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "typedef_identical_lib.dart" as typ;
+
+import "org-dartlang-testcase:///typedef_identical_lib.dart";
+
+typedef H<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = typ::A<Y%>;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> H_new = #C1;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> H_named = #C2;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> H_fact = #C3;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> H_redirect = #C4;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_new = #C5;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> F_named = #C6;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> F_fact = #C7;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_redirect = #C8;
+static method main() → dynamic {
+ self::expect(true, core::identical(self::F_new, typ::F_new_lib));
+ self::expect(false, core::identical(self::F_new, typ::F_named_lib));
+ self::expect(false, core::identical(self::F_new, typ::F_fact_lib));
+ self::expect(false, core::identical(self::F_new, typ::F_redirect_lib));
+ self::expect(false, core::identical(self::F_new, typ::G_new_lib));
+ self::expect(false, core::identical(self::F_new, typ::G_named_lib));
+ self::expect(false, core::identical(self::F_new, typ::G_fact_lib));
+ self::expect(false, core::identical(self::F_new, typ::G_redirect_lib));
+ self::expect(false, core::identical(self::F_new, self::H_new));
+ self::expect(false, core::identical(self::F_new, self::H_named));
+ self::expect(false, core::identical(self::F_new, self::H_fact));
+ self::expect(false, core::identical(self::F_new, self::H_redirect));
+ self::expect(false, core::identical(self::F_named, typ::F_new_lib));
+ self::expect(true, core::identical(self::F_named, typ::F_named_lib));
+ self::expect(false, core::identical(self::F_named, typ::F_fact_lib));
+ self::expect(false, core::identical(self::F_named, typ::F_redirect_lib));
+ self::expect(false, core::identical(self::F_named, typ::G_new_lib));
+ self::expect(false, core::identical(self::F_named, typ::G_named_lib));
+ self::expect(false, core::identical(self::F_named, typ::G_fact_lib));
+ self::expect(false, core::identical(self::F_named, typ::G_redirect_lib));
+ self::expect(false, core::identical(self::F_named, self::H_new));
+ self::expect(false, core::identical(self::F_named, self::H_named));
+ self::expect(false, core::identical(self::F_named, self::H_fact));
+ self::expect(false, core::identical(self::F_named, self::H_redirect));
+ self::expect(false, core::identical(self::F_fact, typ::F_new_lib));
+ self::expect(false, core::identical(self::F_fact, typ::F_named_lib));
+ self::expect(true, core::identical(self::F_fact, typ::F_fact_lib));
+ self::expect(false, core::identical(self::F_fact, typ::F_redirect_lib));
+ self::expect(false, core::identical(self::F_fact, typ::G_new_lib));
+ self::expect(false, core::identical(self::F_fact, typ::G_named_lib));
+ self::expect(false, core::identical(self::F_fact, typ::G_fact_lib));
+ self::expect(false, core::identical(self::F_fact, typ::G_redirect_lib));
+ self::expect(false, core::identical(self::F_fact, self::H_new));
+ self::expect(false, core::identical(self::F_fact, self::H_named));
+ self::expect(false, core::identical(self::F_fact, self::H_fact));
+ self::expect(false, core::identical(self::F_fact, self::H_redirect));
+ self::expect(false, core::identical(self::F_redirect, typ::F_new_lib));
+ self::expect(false, core::identical(self::F_redirect, typ::F_named_lib));
+ self::expect(false, core::identical(self::F_redirect, typ::F_fact_lib));
+ self::expect(true, core::identical(self::F_redirect, typ::F_redirect_lib));
+ self::expect(false, core::identical(self::F_redirect, typ::G_new_lib));
+ self::expect(false, core::identical(self::F_redirect, typ::G_named_lib));
+ self::expect(false, core::identical(self::F_redirect, typ::G_fact_lib));
+ self::expect(false, core::identical(self::F_redirect, typ::G_redirect_lib));
+ self::expect(false, core::identical(self::F_redirect, self::H_new));
+ self::expect(false, core::identical(self::F_redirect, self::H_named));
+ self::expect(false, core::identical(self::F_redirect, self::H_fact));
+ self::expect(false, core::identical(self::F_redirect, self::H_redirect));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method _#H#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<self::_#H#new#tearOff::Y%>
+ return new typ::A::•<self::_#H#new#tearOff::Y%>();
+static method _#H#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#named#tearOff::Y% a, [core::int? b = #C9]) → typ::A<self::_#H#named#tearOff::Y%>
+ return new typ::A::named<self::_#H#named#tearOff::Y%>(a, b);
+static method _#H#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<self::_#H#fact#tearOff::Y%>
+ return typ::A::fact<self::_#H#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#H#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<self::_#H#redirect#tearOff::Y%>
+ return typ::A::_#redirect#tearOff<self::_#H#redirect#tearOff::Y%>();
+
+library /*isNonNullableByDefault*/;
+import self as typ;
+import "dart:core" as core;
+
+typedef F<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = typ::A<Y%>;
+typedef G<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = typ::A<Y%>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[typ::A::redirect]/*isLegacy*/;
+ constructor •() → typ::A<typ::A::T%>
+ : super core::Object::•()
+ ;
+ constructor named(typ::A::T% a, [core::int? b = #C9]) → typ::A<typ::A::T%>
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → typ::A<typ::A::_#new#tearOff::T%>
+ return new typ::A::•<typ::A::_#new#tearOff::T%>();
+ static method _#named#tearOff<T extends core::Object? = dynamic>(typ::A::_#named#tearOff::T% a, [core::int? b = #C9]) → typ::A<typ::A::_#named#tearOff::T%>
+ return new typ::A::named<typ::A::_#named#tearOff::T%>(a, b);
+ static factory fact<T extends core::Object? = dynamic>(typ::A::fact::T% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<typ::A::fact::T%>
+ return new typ::A::•<typ::A::fact::T%>();
+ static method _#fact#tearOff<T extends core::Object? = dynamic>(typ::A::_#fact#tearOff::T% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<typ::A::_#fact#tearOff::T%>
+ return typ::A::fact<typ::A::_#fact#tearOff::T%>(a, b: b, c: c);
+ static factory redirect<T extends core::Object? = dynamic>() → typ::A<typ::A::redirect::T%>
+ let dynamic #redirecting_factory = typ::A::• in let typ::A::redirect::T% #typeArg0 = null in invalid-expression;
+ static method _#redirect#tearOff<T extends core::Object? = dynamic>() → typ::A<typ::A::_#redirect#tearOff::T%>
+ return new typ::A::•<typ::A::_#redirect#tearOff::T%>();
+}
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_new_lib = #C5;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> F_named_lib = #C6;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> F_fact_lib = #C7;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_redirect_lib = #C8;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> G_new_lib = #C11;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> G_named_lib = #C12;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> G_fact_lib = #C13;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> G_redirect_lib = #C14;
+static method _#F#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#F#new#tearOff::Y%>
+ return new typ::A::•<typ::_#F#new#tearOff::Y%>();
+static method _#F#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#F#named#tearOff::Y% a, [core::int? b = #C9]) → typ::A<typ::_#F#named#tearOff::Y%>
+ return new typ::A::named<typ::_#F#named#tearOff::Y%>(a, b);
+static method _#F#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#F#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<typ::_#F#fact#tearOff::Y%>
+ return typ::A::fact<typ::_#F#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#F#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#F#redirect#tearOff::Y%>
+ return typ::A::_#redirect#tearOff<typ::_#F#redirect#tearOff::Y%>();
+static method _#G#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#G#new#tearOff::Y%>
+ return new typ::A::•<typ::_#G#new#tearOff::Y%>();
+static method _#G#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#G#named#tearOff::Y% a, [core::int? b = #C9]) → typ::A<typ::_#G#named#tearOff::Y%>
+ return new typ::A::named<typ::_#G#named#tearOff::Y%>(a, b);
+static method _#G#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#G#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<typ::_#G#fact#tearOff::Y%>
+ return typ::A::fact<typ::_#G#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#G#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#G#redirect#tearOff::Y%>
+ return typ::A::_#redirect#tearOff<typ::_#G#redirect#tearOff::Y%>();
+
+constants {
+ #C1 = static-tearoff self::_#H#new#tearOff
+ #C2 = static-tearoff self::_#H#named#tearOff
+ #C3 = static-tearoff self::_#H#fact#tearOff
+ #C4 = static-tearoff self::_#H#redirect#tearOff
+ #C5 = static-tearoff typ::_#F#new#tearOff
+ #C6 = static-tearoff typ::_#F#named#tearOff
+ #C7 = static-tearoff typ::_#F#fact#tearOff
+ #C8 = static-tearoff typ::_#F#redirect#tearOff
+ #C9 = null
+ #C10 = 42
+ #C11 = static-tearoff typ::_#G#new#tearOff
+ #C12 = static-tearoff typ::_#G#named#tearOff
+ #C13 = static-tearoff typ::_#G#fact#tearOff
+ #C14 = static-tearoff typ::_#G#redirect#tearOff
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.strong.transformed.expect
new file mode 100644
index 0000000..f7eae91
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.strong.transformed.expect
@@ -0,0 +1,147 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "typedef_identical_lib.dart" as typ;
+
+import "org-dartlang-testcase:///typedef_identical_lib.dart";
+
+typedef H<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = typ::A<Y%>;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> H_new = #C1;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> H_named = #C2;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> H_fact = #C3;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> H_redirect = #C4;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_new = #C5;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> F_named = #C6;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> F_fact = #C7;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_redirect = #C8;
+static method main() → dynamic {
+ self::expect(true, core::identical(self::F_new, typ::F_new_lib));
+ self::expect(false, core::identical(self::F_new, typ::F_named_lib));
+ self::expect(false, core::identical(self::F_new, typ::F_fact_lib));
+ self::expect(false, core::identical(self::F_new, typ::F_redirect_lib));
+ self::expect(false, core::identical(self::F_new, typ::G_new_lib));
+ self::expect(false, core::identical(self::F_new, typ::G_named_lib));
+ self::expect(false, core::identical(self::F_new, typ::G_fact_lib));
+ self::expect(false, core::identical(self::F_new, typ::G_redirect_lib));
+ self::expect(false, core::identical(self::F_new, self::H_new));
+ self::expect(false, core::identical(self::F_new, self::H_named));
+ self::expect(false, core::identical(self::F_new, self::H_fact));
+ self::expect(false, core::identical(self::F_new, self::H_redirect));
+ self::expect(false, core::identical(self::F_named, typ::F_new_lib));
+ self::expect(true, core::identical(self::F_named, typ::F_named_lib));
+ self::expect(false, core::identical(self::F_named, typ::F_fact_lib));
+ self::expect(false, core::identical(self::F_named, typ::F_redirect_lib));
+ self::expect(false, core::identical(self::F_named, typ::G_new_lib));
+ self::expect(false, core::identical(self::F_named, typ::G_named_lib));
+ self::expect(false, core::identical(self::F_named, typ::G_fact_lib));
+ self::expect(false, core::identical(self::F_named, typ::G_redirect_lib));
+ self::expect(false, core::identical(self::F_named, self::H_new));
+ self::expect(false, core::identical(self::F_named, self::H_named));
+ self::expect(false, core::identical(self::F_named, self::H_fact));
+ self::expect(false, core::identical(self::F_named, self::H_redirect));
+ self::expect(false, core::identical(self::F_fact, typ::F_new_lib));
+ self::expect(false, core::identical(self::F_fact, typ::F_named_lib));
+ self::expect(true, core::identical(self::F_fact, typ::F_fact_lib));
+ self::expect(false, core::identical(self::F_fact, typ::F_redirect_lib));
+ self::expect(false, core::identical(self::F_fact, typ::G_new_lib));
+ self::expect(false, core::identical(self::F_fact, typ::G_named_lib));
+ self::expect(false, core::identical(self::F_fact, typ::G_fact_lib));
+ self::expect(false, core::identical(self::F_fact, typ::G_redirect_lib));
+ self::expect(false, core::identical(self::F_fact, self::H_new));
+ self::expect(false, core::identical(self::F_fact, self::H_named));
+ self::expect(false, core::identical(self::F_fact, self::H_fact));
+ self::expect(false, core::identical(self::F_fact, self::H_redirect));
+ self::expect(false, core::identical(self::F_redirect, typ::F_new_lib));
+ self::expect(false, core::identical(self::F_redirect, typ::F_named_lib));
+ self::expect(false, core::identical(self::F_redirect, typ::F_fact_lib));
+ self::expect(true, core::identical(self::F_redirect, typ::F_redirect_lib));
+ self::expect(false, core::identical(self::F_redirect, typ::G_new_lib));
+ self::expect(false, core::identical(self::F_redirect, typ::G_named_lib));
+ self::expect(false, core::identical(self::F_redirect, typ::G_fact_lib));
+ self::expect(false, core::identical(self::F_redirect, typ::G_redirect_lib));
+ self::expect(false, core::identical(self::F_redirect, self::H_new));
+ self::expect(false, core::identical(self::F_redirect, self::H_named));
+ self::expect(false, core::identical(self::F_redirect, self::H_fact));
+ self::expect(false, core::identical(self::F_redirect, self::H_redirect));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method _#H#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<self::_#H#new#tearOff::Y%>
+ return new typ::A::•<self::_#H#new#tearOff::Y%>();
+static method _#H#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#named#tearOff::Y% a, [core::int? b = #C9]) → typ::A<self::_#H#named#tearOff::Y%>
+ return new typ::A::named<self::_#H#named#tearOff::Y%>(a, b);
+static method _#H#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<self::_#H#fact#tearOff::Y%>
+ return typ::A::fact<self::_#H#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#H#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<self::_#H#redirect#tearOff::Y%>
+ return typ::A::_#redirect#tearOff<self::_#H#redirect#tearOff::Y%>();
+
+library /*isNonNullableByDefault*/;
+import self as typ;
+import "dart:core" as core;
+
+typedef F<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = typ::A<Y%>;
+typedef G<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = typ::A<Y%>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[typ::A::redirect]/*isLegacy*/;
+ constructor •() → typ::A<typ::A::T%>
+ : super core::Object::•()
+ ;
+ constructor named(typ::A::T% a, [core::int? b = #C9]) → typ::A<typ::A::T%>
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → typ::A<typ::A::_#new#tearOff::T%>
+ return new typ::A::•<typ::A::_#new#tearOff::T%>();
+ static method _#named#tearOff<T extends core::Object? = dynamic>(typ::A::_#named#tearOff::T% a, [core::int? b = #C9]) → typ::A<typ::A::_#named#tearOff::T%>
+ return new typ::A::named<typ::A::_#named#tearOff::T%>(a, b);
+ static factory fact<T extends core::Object? = dynamic>(typ::A::fact::T% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<typ::A::fact::T%>
+ return new typ::A::•<typ::A::fact::T%>();
+ static method _#fact#tearOff<T extends core::Object? = dynamic>(typ::A::_#fact#tearOff::T% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<typ::A::_#fact#tearOff::T%>
+ return typ::A::fact<typ::A::_#fact#tearOff::T%>(a, b: b, c: c);
+ static factory redirect<T extends core::Object? = dynamic>() → typ::A<typ::A::redirect::T%>
+ let Never #redirecting_factory = typ::A::• in let typ::A::redirect::T% #typeArg0 = null in invalid-expression;
+ static method _#redirect#tearOff<T extends core::Object? = dynamic>() → typ::A<typ::A::_#redirect#tearOff::T%>
+ return new typ::A::•<typ::A::_#redirect#tearOff::T%>();
+}
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_new_lib = #C5;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> F_named_lib = #C6;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> F_fact_lib = #C7;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_redirect_lib = #C8;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> G_new_lib = #C11;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> G_named_lib = #C12;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> G_fact_lib = #C13;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> G_redirect_lib = #C14;
+static method _#F#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#F#new#tearOff::Y%>
+ return new typ::A::•<typ::_#F#new#tearOff::Y%>();
+static method _#F#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#F#named#tearOff::Y% a, [core::int? b = #C9]) → typ::A<typ::_#F#named#tearOff::Y%>
+ return new typ::A::named<typ::_#F#named#tearOff::Y%>(a, b);
+static method _#F#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#F#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<typ::_#F#fact#tearOff::Y%>
+ return typ::A::fact<typ::_#F#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#F#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#F#redirect#tearOff::Y%>
+ return typ::A::_#redirect#tearOff<typ::_#F#redirect#tearOff::Y%>();
+static method _#G#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#G#new#tearOff::Y%>
+ return new typ::A::•<typ::_#G#new#tearOff::Y%>();
+static method _#G#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#G#named#tearOff::Y% a, [core::int? b = #C9]) → typ::A<typ::_#G#named#tearOff::Y%>
+ return new typ::A::named<typ::_#G#named#tearOff::Y%>(a, b);
+static method _#G#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#G#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<typ::_#G#fact#tearOff::Y%>
+ return typ::A::fact<typ::_#G#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#G#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#G#redirect#tearOff::Y%>
+ return typ::A::_#redirect#tearOff<typ::_#G#redirect#tearOff::Y%>();
+
+constants {
+ #C1 = static-tearoff self::_#H#new#tearOff
+ #C2 = static-tearoff self::_#H#named#tearOff
+ #C3 = static-tearoff self::_#H#fact#tearOff
+ #C4 = static-tearoff self::_#H#redirect#tearOff
+ #C5 = static-tearoff typ::_#F#new#tearOff
+ #C6 = static-tearoff typ::_#F#named#tearOff
+ #C7 = static-tearoff typ::_#F#fact#tearOff
+ #C8 = static-tearoff typ::_#F#redirect#tearOff
+ #C9 = null
+ #C10 = 42
+ #C11 = static-tearoff typ::_#G#new#tearOff
+ #C12 = static-tearoff typ::_#G#named#tearOff
+ #C13 = static-tearoff typ::_#G#fact#tearOff
+ #C14 = static-tearoff typ::_#G#redirect#tearOff
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.textual_outline.expect
new file mode 100644
index 0000000..8ca6604
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.textual_outline.expect
@@ -0,0 +1,12 @@
+import 'typedef_identical_lib.dart';
+typedef H<X, Y> = A<Y>;
+var H_new = H.new;
+var H_named = H.named;
+var H_fact = H.fact;
+var H_redirect = H.redirect;
+var F_new = F.new;
+var F_named = F.named;
+var F_fact = F.fact;
+var F_redirect = F.redirect;
+main() {}
+expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.weak.expect
new file mode 100644
index 0000000..3e82a43
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.weak.expect
@@ -0,0 +1,147 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "typedef_identical_lib.dart" as typ;
+
+import "org-dartlang-testcase:///typedef_identical_lib.dart";
+
+typedef H<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = typ::A<Y%>;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> H_new = #C1;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> H_named = #C2;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> H_fact = #C3;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> H_redirect = #C4;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_new = #C5;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> F_named = #C6;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> F_fact = #C7;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_redirect = #C8;
+static method main() → dynamic {
+ self::expect(true, core::identical(self::F_new, typ::F_new_lib));
+ self::expect(false, core::identical(self::F_new, typ::F_named_lib));
+ self::expect(false, core::identical(self::F_new, typ::F_fact_lib));
+ self::expect(false, core::identical(self::F_new, typ::F_redirect_lib));
+ self::expect(false, core::identical(self::F_new, typ::G_new_lib));
+ self::expect(false, core::identical(self::F_new, typ::G_named_lib));
+ self::expect(false, core::identical(self::F_new, typ::G_fact_lib));
+ self::expect(false, core::identical(self::F_new, typ::G_redirect_lib));
+ self::expect(false, core::identical(self::F_new, self::H_new));
+ self::expect(false, core::identical(self::F_new, self::H_named));
+ self::expect(false, core::identical(self::F_new, self::H_fact));
+ self::expect(false, core::identical(self::F_new, self::H_redirect));
+ self::expect(false, core::identical(self::F_named, typ::F_new_lib));
+ self::expect(true, core::identical(self::F_named, typ::F_named_lib));
+ self::expect(false, core::identical(self::F_named, typ::F_fact_lib));
+ self::expect(false, core::identical(self::F_named, typ::F_redirect_lib));
+ self::expect(false, core::identical(self::F_named, typ::G_new_lib));
+ self::expect(false, core::identical(self::F_named, typ::G_named_lib));
+ self::expect(false, core::identical(self::F_named, typ::G_fact_lib));
+ self::expect(false, core::identical(self::F_named, typ::G_redirect_lib));
+ self::expect(false, core::identical(self::F_named, self::H_new));
+ self::expect(false, core::identical(self::F_named, self::H_named));
+ self::expect(false, core::identical(self::F_named, self::H_fact));
+ self::expect(false, core::identical(self::F_named, self::H_redirect));
+ self::expect(false, core::identical(self::F_fact, typ::F_new_lib));
+ self::expect(false, core::identical(self::F_fact, typ::F_named_lib));
+ self::expect(true, core::identical(self::F_fact, typ::F_fact_lib));
+ self::expect(false, core::identical(self::F_fact, typ::F_redirect_lib));
+ self::expect(false, core::identical(self::F_fact, typ::G_new_lib));
+ self::expect(false, core::identical(self::F_fact, typ::G_named_lib));
+ self::expect(false, core::identical(self::F_fact, typ::G_fact_lib));
+ self::expect(false, core::identical(self::F_fact, typ::G_redirect_lib));
+ self::expect(false, core::identical(self::F_fact, self::H_new));
+ self::expect(false, core::identical(self::F_fact, self::H_named));
+ self::expect(false, core::identical(self::F_fact, self::H_fact));
+ self::expect(false, core::identical(self::F_fact, self::H_redirect));
+ self::expect(false, core::identical(self::F_redirect, typ::F_new_lib));
+ self::expect(false, core::identical(self::F_redirect, typ::F_named_lib));
+ self::expect(false, core::identical(self::F_redirect, typ::F_fact_lib));
+ self::expect(true, core::identical(self::F_redirect, typ::F_redirect_lib));
+ self::expect(false, core::identical(self::F_redirect, typ::G_new_lib));
+ self::expect(false, core::identical(self::F_redirect, typ::G_named_lib));
+ self::expect(false, core::identical(self::F_redirect, typ::G_fact_lib));
+ self::expect(false, core::identical(self::F_redirect, typ::G_redirect_lib));
+ self::expect(false, core::identical(self::F_redirect, self::H_new));
+ self::expect(false, core::identical(self::F_redirect, self::H_named));
+ self::expect(false, core::identical(self::F_redirect, self::H_fact));
+ self::expect(false, core::identical(self::F_redirect, self::H_redirect));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method _#H#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<self::_#H#new#tearOff::Y%>
+ return new typ::A::•<self::_#H#new#tearOff::Y%>();
+static method _#H#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#named#tearOff::Y% a, [core::int? b = #C9]) → typ::A<self::_#H#named#tearOff::Y%>
+ return new typ::A::named<self::_#H#named#tearOff::Y%>(a, b);
+static method _#H#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<self::_#H#fact#tearOff::Y%>
+ return typ::A::fact<self::_#H#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#H#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<self::_#H#redirect#tearOff::Y%>
+ return typ::A::_#redirect#tearOff<self::_#H#redirect#tearOff::Y%>();
+
+library /*isNonNullableByDefault*/;
+import self as typ;
+import "dart:core" as core;
+
+typedef F<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = typ::A<Y%>;
+typedef G<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = typ::A<Y%>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[typ::A::redirect]/*isLegacy*/;
+ constructor •() → typ::A<typ::A::T%>
+ : super core::Object::•()
+ ;
+ constructor named(typ::A::T% a, [core::int? b = #C9]) → typ::A<typ::A::T%>
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → typ::A<typ::A::_#new#tearOff::T%>
+ return new typ::A::•<typ::A::_#new#tearOff::T%>();
+ static method _#named#tearOff<T extends core::Object? = dynamic>(typ::A::_#named#tearOff::T% a, [core::int? b = #C9]) → typ::A<typ::A::_#named#tearOff::T%>
+ return new typ::A::named<typ::A::_#named#tearOff::T%>(a, b);
+ static factory fact<T extends core::Object? = dynamic>(typ::A::fact::T% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<typ::A::fact::T%>
+ return new typ::A::•<typ::A::fact::T%>();
+ static method _#fact#tearOff<T extends core::Object? = dynamic>(typ::A::_#fact#tearOff::T% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<typ::A::_#fact#tearOff::T%>
+ return typ::A::fact<typ::A::_#fact#tearOff::T%>(a, b: b, c: c);
+ static factory redirect<T extends core::Object? = dynamic>() → typ::A<typ::A::redirect::T%>
+ let dynamic #redirecting_factory = typ::A::• in let typ::A::redirect::T% #typeArg0 = null in invalid-expression;
+ static method _#redirect#tearOff<T extends core::Object? = dynamic>() → typ::A<typ::A::_#redirect#tearOff::T%>
+ return new typ::A::•<typ::A::_#redirect#tearOff::T%>();
+}
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_new_lib = #C5;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> F_named_lib = #C6;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> F_fact_lib = #C7;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_redirect_lib = #C8;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> G_new_lib = #C11;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> G_named_lib = #C12;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> G_fact_lib = #C13;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> G_redirect_lib = #C14;
+static method _#F#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#F#new#tearOff::Y%>
+ return new typ::A::•<typ::_#F#new#tearOff::Y%>();
+static method _#F#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#F#named#tearOff::Y% a, [core::int? b = #C9]) → typ::A<typ::_#F#named#tearOff::Y%>
+ return new typ::A::named<typ::_#F#named#tearOff::Y%>(a, b);
+static method _#F#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#F#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<typ::_#F#fact#tearOff::Y%>
+ return typ::A::fact<typ::_#F#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#F#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#F#redirect#tearOff::Y%>
+ return typ::A::_#redirect#tearOff<typ::_#F#redirect#tearOff::Y%>();
+static method _#G#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#G#new#tearOff::Y%>
+ return new typ::A::•<typ::_#G#new#tearOff::Y%>();
+static method _#G#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#G#named#tearOff::Y% a, [core::int? b = #C9]) → typ::A<typ::_#G#named#tearOff::Y%>
+ return new typ::A::named<typ::_#G#named#tearOff::Y%>(a, b);
+static method _#G#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#G#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<typ::_#G#fact#tearOff::Y%>
+ return typ::A::fact<typ::_#G#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#G#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#G#redirect#tearOff::Y%>
+ return typ::A::_#redirect#tearOff<typ::_#G#redirect#tearOff::Y%>();
+
+constants {
+ #C1 = static-tearoff self::_#H#new#tearOff
+ #C2 = static-tearoff self::_#H#named#tearOff
+ #C3 = static-tearoff self::_#H#fact#tearOff
+ #C4 = static-tearoff self::_#H#redirect#tearOff
+ #C5 = static-tearoff typ::_#F#new#tearOff
+ #C6 = static-tearoff typ::_#F#named#tearOff
+ #C7 = static-tearoff typ::_#F#fact#tearOff
+ #C8 = static-tearoff typ::_#F#redirect#tearOff
+ #C9 = null
+ #C10 = 42
+ #C11 = static-tearoff typ::_#G#new#tearOff
+ #C12 = static-tearoff typ::_#G#named#tearOff
+ #C13 = static-tearoff typ::_#G#fact#tearOff
+ #C14 = static-tearoff typ::_#G#redirect#tearOff
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.weak.outline.expect
new file mode 100644
index 0000000..feafdc3
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.weak.outline.expect
@@ -0,0 +1,78 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "typedef_identical_lib.dart" as typ;
+
+import "org-dartlang-testcase:///typedef_identical_lib.dart";
+
+typedef H<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = typ::A<Y%>;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> H_new;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> H_named;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> H_fact;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> H_redirect;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_new;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> F_named;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> F_fact;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_redirect;
+static method main() → dynamic
+ ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+ ;
+static method _#H#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<self::_#H#new#tearOff::Y%>
+ return new typ::A::•<self::_#H#new#tearOff::Y%>();
+static method _#H#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#named#tearOff::Y% a, [core::int? b]) → typ::A<self::_#H#named#tearOff::Y%>
+ return new typ::A::named<self::_#H#named#tearOff::Y%>(a, b);
+static method _#H#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#fact#tearOff::Y% a, {core::int? b, core::int c}) → typ::A<self::_#H#fact#tearOff::Y%>
+ return typ::A::fact<self::_#H#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#H#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<self::_#H#redirect#tearOff::Y%>
+ return typ::A::_#redirect#tearOff<self::_#H#redirect#tearOff::Y%>();
+
+library /*isNonNullableByDefault*/;
+import self as typ;
+import "dart:core" as core;
+
+typedef F<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = typ::A<Y%>;
+typedef G<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = typ::A<Y%>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[typ::A::redirect]/*isLegacy*/;
+ constructor •() → typ::A<typ::A::T%>
+ ;
+ constructor named(typ::A::T% a, [core::int? b]) → typ::A<typ::A::T%>
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → typ::A<typ::A::_#new#tearOff::T%>
+ return new typ::A::•<typ::A::_#new#tearOff::T%>();
+ static method _#named#tearOff<T extends core::Object? = dynamic>(typ::A::_#named#tearOff::T% a, [core::int? b]) → typ::A<typ::A::_#named#tearOff::T%>
+ return new typ::A::named<typ::A::_#named#tearOff::T%>(a, b);
+ static factory fact<T extends core::Object? = dynamic>(typ::A::fact::T% a, {core::int? b, core::int c}) → typ::A<typ::A::fact::T%>
+ ;
+ static method _#fact#tearOff<T extends core::Object? = dynamic>(typ::A::_#fact#tearOff::T% a, {core::int? b, core::int c}) → typ::A<typ::A::_#fact#tearOff::T%>
+ return typ::A::fact<typ::A::_#fact#tearOff::T%>(a, b: b, c: c);
+ static factory redirect<T extends core::Object? = dynamic>() → typ::A<typ::A::redirect::T%>
+ let dynamic #redirecting_factory = typ::A::• in let typ::A::redirect::T% #typeArg0 = null in invalid-expression;
+ static method _#redirect#tearOff<T extends core::Object? = dynamic>() → typ::A<typ::A::_#redirect#tearOff::T%>
+ return new typ::A::•<typ::A::_#redirect#tearOff::T%>();
+}
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_new_lib;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> F_named_lib;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> F_fact_lib;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_redirect_lib;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> G_new_lib;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> G_named_lib;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> G_fact_lib;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> G_redirect_lib;
+static method _#F#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#F#new#tearOff::Y%>
+ return new typ::A::•<typ::_#F#new#tearOff::Y%>();
+static method _#F#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#F#named#tearOff::Y% a, [core::int? b]) → typ::A<typ::_#F#named#tearOff::Y%>
+ return new typ::A::named<typ::_#F#named#tearOff::Y%>(a, b);
+static method _#F#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#F#fact#tearOff::Y% a, {core::int? b, core::int c}) → typ::A<typ::_#F#fact#tearOff::Y%>
+ return typ::A::fact<typ::_#F#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#F#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#F#redirect#tearOff::Y%>
+ return typ::A::_#redirect#tearOff<typ::_#F#redirect#tearOff::Y%>();
+static method _#G#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#G#new#tearOff::Y%>
+ return new typ::A::•<typ::_#G#new#tearOff::Y%>();
+static method _#G#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#G#named#tearOff::Y% a, [core::int? b]) → typ::A<typ::_#G#named#tearOff::Y%>
+ return new typ::A::named<typ::_#G#named#tearOff::Y%>(a, b);
+static method _#G#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#G#fact#tearOff::Y% a, {core::int? b, core::int c}) → typ::A<typ::_#G#fact#tearOff::Y%>
+ return typ::A::fact<typ::_#G#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#G#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#G#redirect#tearOff::Y%>
+ return typ::A::_#redirect#tearOff<typ::_#G#redirect#tearOff::Y%>();
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.weak.transformed.expect
new file mode 100644
index 0000000..f7eae91
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical.dart.weak.transformed.expect
@@ -0,0 +1,147 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "typedef_identical_lib.dart" as typ;
+
+import "org-dartlang-testcase:///typedef_identical_lib.dart";
+
+typedef H<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = typ::A<Y%>;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> H_new = #C1;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> H_named = #C2;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> H_fact = #C3;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> H_redirect = #C4;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_new = #C5;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> F_named = #C6;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> F_fact = #C7;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_redirect = #C8;
+static method main() → dynamic {
+ self::expect(true, core::identical(self::F_new, typ::F_new_lib));
+ self::expect(false, core::identical(self::F_new, typ::F_named_lib));
+ self::expect(false, core::identical(self::F_new, typ::F_fact_lib));
+ self::expect(false, core::identical(self::F_new, typ::F_redirect_lib));
+ self::expect(false, core::identical(self::F_new, typ::G_new_lib));
+ self::expect(false, core::identical(self::F_new, typ::G_named_lib));
+ self::expect(false, core::identical(self::F_new, typ::G_fact_lib));
+ self::expect(false, core::identical(self::F_new, typ::G_redirect_lib));
+ self::expect(false, core::identical(self::F_new, self::H_new));
+ self::expect(false, core::identical(self::F_new, self::H_named));
+ self::expect(false, core::identical(self::F_new, self::H_fact));
+ self::expect(false, core::identical(self::F_new, self::H_redirect));
+ self::expect(false, core::identical(self::F_named, typ::F_new_lib));
+ self::expect(true, core::identical(self::F_named, typ::F_named_lib));
+ self::expect(false, core::identical(self::F_named, typ::F_fact_lib));
+ self::expect(false, core::identical(self::F_named, typ::F_redirect_lib));
+ self::expect(false, core::identical(self::F_named, typ::G_new_lib));
+ self::expect(false, core::identical(self::F_named, typ::G_named_lib));
+ self::expect(false, core::identical(self::F_named, typ::G_fact_lib));
+ self::expect(false, core::identical(self::F_named, typ::G_redirect_lib));
+ self::expect(false, core::identical(self::F_named, self::H_new));
+ self::expect(false, core::identical(self::F_named, self::H_named));
+ self::expect(false, core::identical(self::F_named, self::H_fact));
+ self::expect(false, core::identical(self::F_named, self::H_redirect));
+ self::expect(false, core::identical(self::F_fact, typ::F_new_lib));
+ self::expect(false, core::identical(self::F_fact, typ::F_named_lib));
+ self::expect(true, core::identical(self::F_fact, typ::F_fact_lib));
+ self::expect(false, core::identical(self::F_fact, typ::F_redirect_lib));
+ self::expect(false, core::identical(self::F_fact, typ::G_new_lib));
+ self::expect(false, core::identical(self::F_fact, typ::G_named_lib));
+ self::expect(false, core::identical(self::F_fact, typ::G_fact_lib));
+ self::expect(false, core::identical(self::F_fact, typ::G_redirect_lib));
+ self::expect(false, core::identical(self::F_fact, self::H_new));
+ self::expect(false, core::identical(self::F_fact, self::H_named));
+ self::expect(false, core::identical(self::F_fact, self::H_fact));
+ self::expect(false, core::identical(self::F_fact, self::H_redirect));
+ self::expect(false, core::identical(self::F_redirect, typ::F_new_lib));
+ self::expect(false, core::identical(self::F_redirect, typ::F_named_lib));
+ self::expect(false, core::identical(self::F_redirect, typ::F_fact_lib));
+ self::expect(true, core::identical(self::F_redirect, typ::F_redirect_lib));
+ self::expect(false, core::identical(self::F_redirect, typ::G_new_lib));
+ self::expect(false, core::identical(self::F_redirect, typ::G_named_lib));
+ self::expect(false, core::identical(self::F_redirect, typ::G_fact_lib));
+ self::expect(false, core::identical(self::F_redirect, typ::G_redirect_lib));
+ self::expect(false, core::identical(self::F_redirect, self::H_new));
+ self::expect(false, core::identical(self::F_redirect, self::H_named));
+ self::expect(false, core::identical(self::F_redirect, self::H_fact));
+ self::expect(false, core::identical(self::F_redirect, self::H_redirect));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method _#H#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<self::_#H#new#tearOff::Y%>
+ return new typ::A::•<self::_#H#new#tearOff::Y%>();
+static method _#H#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#named#tearOff::Y% a, [core::int? b = #C9]) → typ::A<self::_#H#named#tearOff::Y%>
+ return new typ::A::named<self::_#H#named#tearOff::Y%>(a, b);
+static method _#H#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(self::_#H#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<self::_#H#fact#tearOff::Y%>
+ return typ::A::fact<self::_#H#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#H#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<self::_#H#redirect#tearOff::Y%>
+ return typ::A::_#redirect#tearOff<self::_#H#redirect#tearOff::Y%>();
+
+library /*isNonNullableByDefault*/;
+import self as typ;
+import "dart:core" as core;
+
+typedef F<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = typ::A<Y%>;
+typedef G<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic> = typ::A<Y%>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[typ::A::redirect]/*isLegacy*/;
+ constructor •() → typ::A<typ::A::T%>
+ : super core::Object::•()
+ ;
+ constructor named(typ::A::T% a, [core::int? b = #C9]) → typ::A<typ::A::T%>
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → typ::A<typ::A::_#new#tearOff::T%>
+ return new typ::A::•<typ::A::_#new#tearOff::T%>();
+ static method _#named#tearOff<T extends core::Object? = dynamic>(typ::A::_#named#tearOff::T% a, [core::int? b = #C9]) → typ::A<typ::A::_#named#tearOff::T%>
+ return new typ::A::named<typ::A::_#named#tearOff::T%>(a, b);
+ static factory fact<T extends core::Object? = dynamic>(typ::A::fact::T% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<typ::A::fact::T%>
+ return new typ::A::•<typ::A::fact::T%>();
+ static method _#fact#tearOff<T extends core::Object? = dynamic>(typ::A::_#fact#tearOff::T% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<typ::A::_#fact#tearOff::T%>
+ return typ::A::fact<typ::A::_#fact#tearOff::T%>(a, b: b, c: c);
+ static factory redirect<T extends core::Object? = dynamic>() → typ::A<typ::A::redirect::T%>
+ let Never #redirecting_factory = typ::A::• in let typ::A::redirect::T% #typeArg0 = null in invalid-expression;
+ static method _#redirect#tearOff<T extends core::Object? = dynamic>() → typ::A<typ::A::_#redirect#tearOff::T%>
+ return new typ::A::•<typ::A::_#redirect#tearOff::T%>();
+}
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_new_lib = #C5;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> F_named_lib = #C6;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> F_fact_lib = #C7;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> F_redirect_lib = #C8;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> G_new_lib = #C11;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, [core::int?]) → typ::A<Y%> G_named_lib = #C12;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(Y%, {b: core::int?, c: core::int}) → typ::A<Y%> G_fact_lib = #C13;
+static field <unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<Y%> G_redirect_lib = #C14;
+static method _#F#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#F#new#tearOff::Y%>
+ return new typ::A::•<typ::_#F#new#tearOff::Y%>();
+static method _#F#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#F#named#tearOff::Y% a, [core::int? b = #C9]) → typ::A<typ::_#F#named#tearOff::Y%>
+ return new typ::A::named<typ::_#F#named#tearOff::Y%>(a, b);
+static method _#F#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#F#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<typ::_#F#fact#tearOff::Y%>
+ return typ::A::fact<typ::_#F#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#F#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#F#redirect#tearOff::Y%>
+ return typ::A::_#redirect#tearOff<typ::_#F#redirect#tearOff::Y%>();
+static method _#G#new#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#G#new#tearOff::Y%>
+ return new typ::A::•<typ::_#G#new#tearOff::Y%>();
+static method _#G#named#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#G#named#tearOff::Y% a, [core::int? b = #C9]) → typ::A<typ::_#G#named#tearOff::Y%>
+ return new typ::A::named<typ::_#G#named#tearOff::Y%>(a, b);
+static method _#G#fact#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>(typ::_#G#fact#tearOff::Y% a, {core::int? b = #C9, core::int c = #C10}) → typ::A<typ::_#G#fact#tearOff::Y%>
+ return typ::A::fact<typ::_#G#fact#tearOff::Y%>(a, b: b, c: c);
+static method _#G#redirect#tearOff<unrelated X extends core::Object? = dynamic, Y extends core::Object? = dynamic>() → typ::A<typ::_#G#redirect#tearOff::Y%>
+ return typ::A::_#redirect#tearOff<typ::_#G#redirect#tearOff::Y%>();
+
+constants {
+ #C1 = static-tearoff self::_#H#new#tearOff
+ #C2 = static-tearoff self::_#H#named#tearOff
+ #C3 = static-tearoff self::_#H#fact#tearOff
+ #C4 = static-tearoff self::_#H#redirect#tearOff
+ #C5 = static-tearoff typ::_#F#new#tearOff
+ #C6 = static-tearoff typ::_#F#named#tearOff
+ #C7 = static-tearoff typ::_#F#fact#tearOff
+ #C8 = static-tearoff typ::_#F#redirect#tearOff
+ #C9 = null
+ #C10 = 42
+ #C11 = static-tearoff typ::_#G#new#tearOff
+ #C12 = static-tearoff typ::_#G#named#tearOff
+ #C13 = static-tearoff typ::_#G#fact#tearOff
+ #C14 = static-tearoff typ::_#G#redirect#tearOff
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical_lib.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical_lib.dart
new file mode 100644
index 0000000..e21df56
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_identical_lib.dart
@@ -0,0 +1,23 @@
+// 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 A<T> {
+ A();
+ A.named(T a, [int? b]);
+ factory A.fact(T a, {int? b, int c = 42}) => new A();
+ factory A.redirect() = A;
+}
+
+typedef F<X, Y> = A<Y>;
+typedef G<X, Y> = A<Y>;
+
+var F_new_lib = F.new;
+var F_named_lib = F.named;
+var F_fact_lib = F.fact;
+var F_redirect_lib = F.redirect;
+
+var G_new_lib = G.new;
+var G_named_lib = G.named;
+var G_fact_lib = G.fact;
+var G_redirect_lib = G.redirect;
\ No newline at end of file
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart
new file mode 100644
index 0000000..0433631
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart
@@ -0,0 +1,186 @@
+// 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.
+
+final bool inSoundMode = <int?>[] is! List<int>;
+
+class A {}
+
+class B<X> {
+ int field1;
+ String field2;
+
+ B._(this.field1, this.field2);
+ B() : this._(0, '');
+ B.foo(this.field1) : field2 = '';
+ factory B.bar(int i, String j) => new B<X>._(i, j);
+}
+
+typedef DA1 = A;
+
+typedef DA2<X extends num> = A;
+
+typedef DB1 = B<String>;
+
+typedef DB2<X extends num> = B<X>;
+
+typedef DB3<X extends num, Y extends String> = B<X>;
+
+main() {
+ var f1a = DA1.new;
+ var c1a = f1a();
+ expect(true, c1a is A);
+ () {
+ f1a(0); // error
+ };
+
+ dynamic f1b = DA1.new;
+ var c1b = f1b();
+ expect(true, c1b is A);
+ throws(() => f1b(0));
+
+ var f2a = DA2.new;
+ var c2a = f2a();
+ expect(true, c2a is A);
+ () {
+ f2a(0); // error
+ f2a<String>(); // error
+ };
+
+ dynamic f2b = DA2.new;
+ var c2b = f2b();
+ expect(true, c2b is A);
+ var c2c = f2b<int>();
+ expect(true, c2c is A);
+ throws(() => f2b(0));
+ throws(() => f2b<String>());
+
+ var f3a = DB1.new;
+ var c3a = f3a();
+ expect(true, c3a is B<String>);
+ expect(false, c3a is B<int>);
+ expect(0, c3a.field1);
+ expect('', c3a.field2);
+ () {
+ f3a(0); // error
+ f3a<String>(); // error
+ };
+
+ dynamic f3b = DB1.new;
+ var c3b = f3b();
+ expect(true, c3b is B<String>);
+ expect(false, c3b is B<int>);
+ expect(0, c3a.field1);
+ expect('', c3a.field2);
+ throws(() => f3b(0));
+ throws(() => f3b<String>());
+
+ var f3c = DB1.foo;
+ var c3c = f3c(42);
+ expect(true, c3c is B<String>);
+ expect(false, c3c is B<int>);
+ expect(42, c3c.field1);
+ expect('', c3c.field2);
+ () {
+ f3c(); // error
+ f3c(0, 0); // error
+ f3c<String>(0); // error
+ };
+
+ dynamic f3d = DB1.foo;
+ var c3d = f3d(42);
+ expect(true, c3d is B<String>);
+ expect(false, c3d is B<int>);
+ expect(42, c3d.field1);
+ expect('', c3d.field2);
+ throws(() => f3d());
+ throws(() => f3d(0, 0));
+ throws(() => f3d<String>(0));
+
+ var f3e = DB1.bar;
+ var c3e = f3e(42, 'foo');
+ expect(true, c3e is B<String>);
+ expect(false, c3e is B<int>);
+ expect(42, c3e.field1);
+ expect('foo', c3e.field2);
+ () {
+ f3e(); // error
+ f3e(0); // error
+ f3e<String>(0, ''); // error
+ };
+
+ dynamic f3f = DB1.bar;
+ var c3f = f3f(42, 'foo');
+ expect(true, c3f is B<String>);
+ expect(false, c3f is B<int>);
+ expect(42, c3f.field1);
+ expect('foo', c3f.field2);
+ throws(() => c3f());
+ throws(() => c3f(0));
+ throws(() => c3f<String>(0));
+
+ var f4a = DB2.new;
+ var c4a = f4a();
+ expect(true, c4a is B<num>);
+ expect(false, c4a is B<int>);
+ var c4b = f4a<int>();
+ expect(true, c4b is B<int>);
+ expect(false, c4b is B<double>);
+ () {
+ f4a(0); // error
+ f4a<String>(); // error
+ };
+
+ dynamic f4b = DB2.new;
+ var c4c = f4b();
+ expect(true, c4c is B<num>);
+ expect(false, c4c is B<int>);
+ var c4d = f4b<int>();
+ expect(true, c4d is B<int>);
+ expect(false, c4d is B<double>);
+ throws(() => f4b(0));
+ throws(() => f4b<String>());
+
+ var f5a = DB3.new;
+ var c5a = f5a();
+ expect(true, c5a is B<num>);
+ expect(false, c5a is B<int>);
+ var c5b = f5a<int, String>();
+ expect(true, c5b is B<int>);
+ expect(false, c5b is B<double>);
+ () {
+ f5a(0); // error
+ f5a<String>(); // error
+ f5a<String, String>(); // error
+ f5a<num, num>(); // error
+ };
+
+ dynamic f5b = DB3.new;
+ var c5c = f5b();
+ expect(true, c5c is B<num>);
+ expect(false, c5c is B<int>);
+ var c5d = f5b<int, String>();
+ expect(true, c5d is B<int>);
+ expect(false, c5d is B<double>);
+ throws(() => f5b(0));
+ throws(() => f5b<String>());
+ throws(() => f5b<String, String>());
+ throws(() => f5b<num, num>());
+}
+
+expect(expected, actual) {
+ if (expected != actual) throw 'Expected $expected, actual $actual';
+}
+
+throws(Function() f, {bool inSoundModeOnly: false}) {
+ try {
+ f();
+ } catch (e) {
+ print('Thrown: $e');
+ return;
+ }
+ if (!inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw 'Expected exception';
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.strong.expect
new file mode 100644
index 0000000..848dbdd
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.strong.expect
@@ -0,0 +1,330 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:34:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+// f1a(0); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:46:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+// f2a(0); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:47:8: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+// f2a<String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:65:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+// f3a(0); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:66:8: Error: Expected 0 type arguments.
+// f3a<String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:85:8: Error: Too few positional arguments: 1 required, 0 given.
+// f3c(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:86:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f3c(0, 0); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:87:8: Error: Expected 0 type arguments.
+// f3c<String>(0); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:107:8: Error: Too few positional arguments: 2 required, 0 given.
+// f3e(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:108:8: Error: Too few positional arguments: 2 required, 1 given.
+// f3e(0); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:109:8: Error: Expected 0 type arguments.
+// f3e<String>(0, ''); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:130:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+// f4a(0); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:131:8: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+// f4a<String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:152:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+// f5a(0); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:153:8: Error: Expected 2 type arguments.
+// f5a<String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:154:8: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+// f5a<String, String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:155:8: Error: Type argument 'num' doesn't conform to the bound 'String' of the type variable 'Y' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+// f5a<num, num>(); // error
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef DA1 = self::A;
+typedef DA2<unrelated X extends core::num> = self::A;
+typedef DB1 = self::B<core::String>;
+typedef DB2<X extends core::num> = self::B<X>;
+typedef DB3<X extends core::num, unrelated Y extends core::String> = self::B<X>;
+class A extends core::Object {
+ synthetic constructor •() → self::A
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff() → self::A
+ return new self::A::•();
+}
+class B<X extends core::Object? = dynamic> extends core::Object {
+ field core::int field1;
+ field core::String field2;
+ constructor _(core::int field1, core::String field2) → self::B<self::B::X%>
+ : self::B::field1 = field1, self::B::field2 = field2, super core::Object::•()
+ ;
+ constructor •() → self::B<self::B::X%>
+ : this self::B::_(0, "")
+ ;
+ constructor foo(core::int field1) → self::B<self::B::X%>
+ : self::B::field1 = field1, self::B::field2 = "", super core::Object::•()
+ ;
+ static method _#_#tearOff<X extends core::Object? = dynamic>(core::int field1, core::String field2) → self::B<self::B::_#_#tearOff::X%>
+ return new self::B::_<self::B::_#_#tearOff::X%>(field1, field2);
+ static method _#new#tearOff<X extends core::Object? = dynamic>() → self::B<self::B::_#new#tearOff::X%>
+ return new self::B::•<self::B::_#new#tearOff::X%>();
+ static method _#foo#tearOff<X extends core::Object? = dynamic>(core::int field1) → self::B<self::B::_#foo#tearOff::X%>
+ return new self::B::foo<self::B::_#foo#tearOff::X%>(field1);
+ static factory bar<X extends core::Object? = dynamic>(core::int i, core::String j) → self::B<self::B::bar::X%>
+ return new self::B::_<self::B::bar::X%>(i, j);
+ static method _#bar#tearOff<X extends core::Object? = dynamic>(core::int i, core::String j) → self::B<self::B::_#bar#tearOff::X%>
+ return self::B::bar<self::B::_#bar#tearOff::X%>(i, j);
+}
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+ () → self::A f1a = #C1;
+ self::A c1a = f1a(){() → self::A};
+ self::expect(true, c1a is{ForNonNullableByDefault} self::A);
+ () → Null {
+ let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:34:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+ f1a(0); // error
+ ^" in f1a{<inapplicable>}.(0);
+ };
+ dynamic f1b = #C1;
+ dynamic c1b = f1b{dynamic}.call();
+ self::expect(true, c1b is{ForNonNullableByDefault} self::A);
+ self::throws(() → dynamic => f1b{dynamic}.call(0));
+ <unrelated X extends core::num>() → self::A f2a = #C2;
+ self::A c2a = f2a<core::num>(){() → self::A};
+ self::expect(true, c2a is{ForNonNullableByDefault} self::A);
+ () → Null {
+ let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:46:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+ f2a(0); // error
+ ^" in f2a{<inapplicable>}.<core::num>(0);
+ f2a<core::String>(){() → self::A};
+ };
+ dynamic f2b = #C2;
+ dynamic c2b = f2b{dynamic}.call();
+ self::expect(true, c2b is{ForNonNullableByDefault} self::A);
+ dynamic c2c = f2b{dynamic}.call<core::int>();
+ self::expect(true, c2c is{ForNonNullableByDefault} self::A);
+ self::throws(() → dynamic => f2b{dynamic}.call(0));
+ self::throws(() → dynamic => f2b{dynamic}.call<core::String>());
+ () → self::B<core::String> f3a = #C4;
+ self::B<core::String> c3a = f3a(){() → self::B<core::String>};
+ self::expect(true, c3a is{ForNonNullableByDefault} self::B<core::String>);
+ self::expect(false, c3a is{ForNonNullableByDefault} self::B<core::int>);
+ self::expect(0, c3a.{self::B::field1}{core::int});
+ self::expect("", c3a.{self::B::field2}{core::String});
+ () → Null {
+ let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:65:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+ f3a(0); // error
+ ^" in f3a{<inapplicable>}.(0);
+ let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:66:8: Error: Expected 0 type arguments.
+ f3a<String>(); // error
+ ^" in f3a{<inapplicable>}.<core::String>();
+ };
+ dynamic f3b = #C4;
+ dynamic c3b = f3b{dynamic}.call();
+ self::expect(true, c3b is{ForNonNullableByDefault} self::B<core::String>);
+ self::expect(false, c3b is{ForNonNullableByDefault} self::B<core::int>);
+ self::expect(0, c3a.{self::B::field1}{core::int});
+ self::expect("", c3a.{self::B::field2}{core::String});
+ self::throws(() → dynamic => f3b{dynamic}.call(0));
+ self::throws(() → dynamic => f3b{dynamic}.call<core::String>());
+ (core::int) → self::B<core::String> f3c = #C6;
+ self::B<core::String> c3c = f3c(42){(core::int) → self::B<core::String>};
+ self::expect(true, c3c is{ForNonNullableByDefault} self::B<core::String>);
+ self::expect(false, c3c is{ForNonNullableByDefault} self::B<core::int>);
+ self::expect(42, c3c.{self::B::field1}{core::int});
+ self::expect("", c3c.{self::B::field2}{core::String});
+ () → Null {
+ let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:85:8: Error: Too few positional arguments: 1 required, 0 given.
+ f3c(); // error
+ ^" in f3c{<inapplicable>}.();
+ let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:86:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f3c(0, 0); // error
+ ^" in f3c{<inapplicable>}.(0, 0);
+ let final Never #t7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:87:8: Error: Expected 0 type arguments.
+ f3c<String>(0); // error
+ ^" in f3c{<inapplicable>}.<core::String>(0);
+ };
+ dynamic f3d = #C6;
+ dynamic c3d = f3d{dynamic}.call(42);
+ self::expect(true, c3d is{ForNonNullableByDefault} self::B<core::String>);
+ self::expect(false, c3d is{ForNonNullableByDefault} self::B<core::int>);
+ self::expect(42, c3d{dynamic}.field1);
+ self::expect("", c3d{dynamic}.field2);
+ self::throws(() → dynamic => f3d{dynamic}.call());
+ self::throws(() → dynamic => f3d{dynamic}.call(0, 0));
+ self::throws(() → dynamic => f3d{dynamic}.call<core::String>(0));
+ (core::int, core::String) → self::B<core::String> f3e = #C8;
+ self::B<core::String> c3e = f3e(42, "foo"){(core::int, core::String) → self::B<core::String>};
+ self::expect(true, c3e is{ForNonNullableByDefault} self::B<core::String>);
+ self::expect(false, c3e is{ForNonNullableByDefault} self::B<core::int>);
+ self::expect(42, c3e.{self::B::field1}{core::int});
+ self::expect("foo", c3e.{self::B::field2}{core::String});
+ () → Null {
+ let final Never #t8 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:107:8: Error: Too few positional arguments: 2 required, 0 given.
+ f3e(); // error
+ ^" in f3e{<inapplicable>}.();
+ let final Never #t9 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:108:8: Error: Too few positional arguments: 2 required, 1 given.
+ f3e(0); // error
+ ^" in f3e{<inapplicable>}.(0);
+ let final Never #t10 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:109:8: Error: Expected 0 type arguments.
+ f3e<String>(0, ''); // error
+ ^" in f3e{<inapplicable>}.<core::String>(0, "");
+ };
+ dynamic f3f = #C8;
+ dynamic c3f = f3f{dynamic}.call(42, "foo");
+ self::expect(true, c3f is{ForNonNullableByDefault} self::B<core::String>);
+ self::expect(false, c3f is{ForNonNullableByDefault} self::B<core::int>);
+ self::expect(42, c3f{dynamic}.field1);
+ self::expect("foo", c3f{dynamic}.field2);
+ self::throws(() → dynamic => c3f{dynamic}.call());
+ self::throws(() → dynamic => c3f{dynamic}.call(0));
+ self::throws(() → dynamic => c3f{dynamic}.call<core::String>(0));
+ <X extends core::num>() → self::B<X> f4a = #C9;
+ self::B<core::num> c4a = f4a<core::num>(){() → self::B<core::num>};
+ self::expect(true, c4a is{ForNonNullableByDefault} self::B<core::num>);
+ self::expect(false, c4a is{ForNonNullableByDefault} self::B<core::int>);
+ self::B<core::int> c4b = f4a<core::int>(){() → self::B<core::int>};
+ self::expect(true, c4b is{ForNonNullableByDefault} self::B<core::int>);
+ self::expect(false, c4b is{ForNonNullableByDefault} self::B<core::double>);
+ () → Null {
+ let final Never #t11 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:130:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+ f4a(0); // error
+ ^" in f4a{<inapplicable>}.<core::num>(0);
+ f4a<core::String>(){() → self::B<core::String>};
+ };
+ dynamic f4b = #C9;
+ dynamic c4c = f4b{dynamic}.call();
+ self::expect(true, c4c is{ForNonNullableByDefault} self::B<core::num>);
+ self::expect(false, c4c is{ForNonNullableByDefault} self::B<core::int>);
+ dynamic c4d = f4b{dynamic}.call<core::int>();
+ self::expect(true, c4d is{ForNonNullableByDefault} self::B<core::int>);
+ self::expect(false, c4d is{ForNonNullableByDefault} self::B<core::double>);
+ self::throws(() → dynamic => f4b{dynamic}.call(0));
+ self::throws(() → dynamic => f4b{dynamic}.call<core::String>());
+ <X extends core::num, unrelated Y extends core::String>() → self::B<X> f5a = #C10;
+ self::B<core::num> c5a = f5a<core::num, core::String>(){() → self::B<core::num>};
+ self::expect(true, c5a is{ForNonNullableByDefault} self::B<core::num>);
+ self::expect(false, c5a is{ForNonNullableByDefault} self::B<core::int>);
+ self::B<core::int> c5b = f5a<core::int, core::String>(){() → self::B<core::int>};
+ self::expect(true, c5b is{ForNonNullableByDefault} self::B<core::int>);
+ self::expect(false, c5b is{ForNonNullableByDefault} self::B<core::double>);
+ () → Null {
+ let final Never #t12 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:152:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+ f5a(0); // error
+ ^" in f5a{<inapplicable>}.<core::num, core::String>(0);
+ let final Never #t13 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:153:8: Error: Expected 2 type arguments.
+ f5a<String>(); // error
+ ^" in f5a{<inapplicable>}.<core::String>();
+ f5a<core::String, core::String>(){() → self::B<core::String>};
+ f5a<core::num, core::num>(){() → self::B<core::num>};
+ };
+ dynamic f5b = #C10;
+ dynamic c5c = f5b{dynamic}.call();
+ self::expect(true, c5c is{ForNonNullableByDefault} self::B<core::num>);
+ self::expect(false, c5c is{ForNonNullableByDefault} self::B<core::int>);
+ dynamic c5d = f5b{dynamic}.call<core::int, core::String>();
+ self::expect(true, c5d is{ForNonNullableByDefault} self::B<core::int>);
+ self::expect(false, c5d is{ForNonNullableByDefault} self::B<core::double>);
+ self::throws(() → dynamic => f5b{dynamic}.call(0));
+ self::throws(() → dynamic => f5b{dynamic}.call<core::String>());
+ self::throws(() → dynamic => f5b{dynamic}.call<core::String, core::String>());
+ self::throws(() → dynamic => f5b{dynamic}.call<core::num, core::num>());
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C11}) → dynamic {
+ try {
+ f(){() → dynamic};
+ }
+ on core::Object catch(final core::Object e) {
+ core::print("Thrown: ${e}");
+ return;
+ }
+ if(!self::inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw "Expected exception";
+}
+static method _#DA2#new#tearOff<unrelated X extends core::num>() → self::A
+ return new self::A::•();
+static method _#DB2#_#tearOff<X extends core::num>(core::int field1, core::String field2) → self::B<self::_#DB2#_#tearOff::X>
+ return new self::B::_<self::_#DB2#_#tearOff::X>(field1, field2);
+static method _#DB2#new#tearOff<X extends core::num>() → self::B<self::_#DB2#new#tearOff::X>
+ return new self::B::•<self::_#DB2#new#tearOff::X>();
+static method _#DB2#foo#tearOff<X extends core::num>(core::int field1) → self::B<self::_#DB2#foo#tearOff::X>
+ return new self::B::foo<self::_#DB2#foo#tearOff::X>(field1);
+static method _#DB2#bar#tearOff<X extends core::num>(core::int i, core::String j) → self::B<self::_#DB2#bar#tearOff::X>
+ return self::B::bar<self::_#DB2#bar#tearOff::X>(i, j);
+static method _#DB3#_#tearOff<X extends core::num, unrelated Y extends core::String>(core::int field1, core::String field2) → self::B<self::_#DB3#_#tearOff::X>
+ return new self::B::_<self::_#DB3#_#tearOff::X>(field1, field2);
+static method _#DB3#new#tearOff<X extends core::num, unrelated Y extends core::String>() → self::B<self::_#DB3#new#tearOff::X>
+ return new self::B::•<self::_#DB3#new#tearOff::X>();
+static method _#DB3#foo#tearOff<X extends core::num, unrelated Y extends core::String>(core::int field1) → self::B<self::_#DB3#foo#tearOff::X>
+ return new self::B::foo<self::_#DB3#foo#tearOff::X>(field1);
+static method _#DB3#bar#tearOff<X extends core::num, unrelated Y extends core::String>(core::int i, core::String j) → self::B<self::_#DB3#bar#tearOff::X>
+ return self::B::bar<self::_#DB3#bar#tearOff::X>(i, j);
+
+constants {
+ #C1 = static-tearoff self::A::_#new#tearOff
+ #C2 = static-tearoff self::_#DA2#new#tearOff
+ #C3 = static-tearoff self::B::_#new#tearOff
+ #C4 = instantiation self::B::_#new#tearOff <core::String>
+ #C5 = static-tearoff self::B::_#foo#tearOff
+ #C6 = instantiation self::B::_#foo#tearOff <core::String>
+ #C7 = static-tearoff self::B::_#bar#tearOff
+ #C8 = instantiation self::B::_#bar#tearOff <core::String>
+ #C9 = static-tearoff self::_#DB2#new#tearOff
+ #C10 = static-tearoff self::_#DB3#new#tearOff
+ #C11 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.strong.transformed.expect
new file mode 100644
index 0000000..7c8571b
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.strong.transformed.expect
@@ -0,0 +1,330 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:34:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+// f1a(0); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:46:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+// f2a(0); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:47:8: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+// f2a<String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:65:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+// f3a(0); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:66:8: Error: Expected 0 type arguments.
+// f3a<String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:85:8: Error: Too few positional arguments: 1 required, 0 given.
+// f3c(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:86:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f3c(0, 0); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:87:8: Error: Expected 0 type arguments.
+// f3c<String>(0); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:107:8: Error: Too few positional arguments: 2 required, 0 given.
+// f3e(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:108:8: Error: Too few positional arguments: 2 required, 1 given.
+// f3e(0); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:109:8: Error: Expected 0 type arguments.
+// f3e<String>(0, ''); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:130:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+// f4a(0); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:131:8: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+// f4a<String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:152:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+// f5a(0); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:153:8: Error: Expected 2 type arguments.
+// f5a<String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:154:8: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+// f5a<String, String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:155:8: Error: Type argument 'num' doesn't conform to the bound 'String' of the type variable 'Y' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+// f5a<num, num>(); // error
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef DA1 = self::A;
+typedef DA2<unrelated X extends core::num> = self::A;
+typedef DB1 = self::B<core::String>;
+typedef DB2<X extends core::num> = self::B<X>;
+typedef DB3<X extends core::num, unrelated Y extends core::String> = self::B<X>;
+class A extends core::Object {
+ synthetic constructor •() → self::A
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff() → self::A
+ return new self::A::•();
+}
+class B<X extends core::Object? = dynamic> extends core::Object {
+ field core::int field1;
+ field core::String field2;
+ constructor _(core::int field1, core::String field2) → self::B<self::B::X%>
+ : self::B::field1 = field1, self::B::field2 = field2, super core::Object::•()
+ ;
+ constructor •() → self::B<self::B::X%>
+ : this self::B::_(0, "")
+ ;
+ constructor foo(core::int field1) → self::B<self::B::X%>
+ : self::B::field1 = field1, self::B::field2 = "", super core::Object::•()
+ ;
+ static method _#_#tearOff<X extends core::Object? = dynamic>(core::int field1, core::String field2) → self::B<self::B::_#_#tearOff::X%>
+ return new self::B::_<self::B::_#_#tearOff::X%>(field1, field2);
+ static method _#new#tearOff<X extends core::Object? = dynamic>() → self::B<self::B::_#new#tearOff::X%>
+ return new self::B::•<self::B::_#new#tearOff::X%>();
+ static method _#foo#tearOff<X extends core::Object? = dynamic>(core::int field1) → self::B<self::B::_#foo#tearOff::X%>
+ return new self::B::foo<self::B::_#foo#tearOff::X%>(field1);
+ static factory bar<X extends core::Object? = dynamic>(core::int i, core::String j) → self::B<self::B::bar::X%>
+ return new self::B::_<self::B::bar::X%>(i, j);
+ static method _#bar#tearOff<X extends core::Object? = dynamic>(core::int i, core::String j) → self::B<self::B::_#bar#tearOff::X%>
+ return self::B::bar<self::B::_#bar#tearOff::X%>(i, j);
+}
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+ () → self::A f1a = #C1;
+ self::A c1a = f1a(){() → self::A};
+ self::expect(true, c1a is{ForNonNullableByDefault} self::A);
+ () → Null {
+ let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:34:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+ f1a(0); // error
+ ^" in f1a{<inapplicable>}.(0);
+ };
+ dynamic f1b = #C1;
+ dynamic c1b = f1b{dynamic}.call();
+ self::expect(true, c1b is{ForNonNullableByDefault} self::A);
+ self::throws(() → dynamic => f1b{dynamic}.call(0));
+ <unrelated X extends core::num>() → self::A f2a = #C2;
+ self::A c2a = f2a<core::num>(){() → self::A};
+ self::expect(true, c2a is{ForNonNullableByDefault} self::A);
+ () → Null {
+ let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:46:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+ f2a(0); // error
+ ^" in f2a{<inapplicable>}.<core::num>(0);
+ f2a<core::String>(){() → self::A};
+ };
+ dynamic f2b = #C2;
+ dynamic c2b = f2b{dynamic}.call();
+ self::expect(true, c2b is{ForNonNullableByDefault} self::A);
+ dynamic c2c = f2b{dynamic}.call<core::int>();
+ self::expect(true, c2c is{ForNonNullableByDefault} self::A);
+ self::throws(() → dynamic => f2b{dynamic}.call(0));
+ self::throws(() → dynamic => f2b{dynamic}.call<core::String>());
+ () → self::B<core::String> f3a = #C4;
+ self::B<core::String> c3a = f3a(){() → self::B<core::String>};
+ self::expect(true, c3a is{ForNonNullableByDefault} self::B<core::String>);
+ self::expect(false, c3a is{ForNonNullableByDefault} self::B<core::int>);
+ self::expect(0, c3a.{self::B::field1}{core::int});
+ self::expect("", c3a.{self::B::field2}{core::String});
+ () → Null {
+ let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:65:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+ f3a(0); // error
+ ^" in f3a{<inapplicable>}.(0);
+ let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:66:8: Error: Expected 0 type arguments.
+ f3a<String>(); // error
+ ^" in f3a{<inapplicable>}.<core::String>();
+ };
+ dynamic f3b = #C4;
+ dynamic c3b = f3b{dynamic}.call();
+ self::expect(true, c3b is{ForNonNullableByDefault} self::B<core::String>);
+ self::expect(false, c3b is{ForNonNullableByDefault} self::B<core::int>);
+ self::expect(0, c3a.{self::B::field1}{core::int});
+ self::expect("", c3a.{self::B::field2}{core::String});
+ self::throws(() → dynamic => f3b{dynamic}.call(0));
+ self::throws(() → dynamic => f3b{dynamic}.call<core::String>());
+ (core::int) → self::B<core::String> f3c = #C6;
+ self::B<core::String> c3c = f3c(42){(core::int) → self::B<core::String>};
+ self::expect(true, c3c is{ForNonNullableByDefault} self::B<core::String>);
+ self::expect(false, c3c is{ForNonNullableByDefault} self::B<core::int>);
+ self::expect(42, c3c.{self::B::field1}{core::int});
+ self::expect("", c3c.{self::B::field2}{core::String});
+ () → Null {
+ let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:85:8: Error: Too few positional arguments: 1 required, 0 given.
+ f3c(); // error
+ ^" in f3c{<inapplicable>}.();
+ let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:86:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f3c(0, 0); // error
+ ^" in f3c{<inapplicable>}.(0, 0);
+ let final Never #t7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:87:8: Error: Expected 0 type arguments.
+ f3c<String>(0); // error
+ ^" in f3c{<inapplicable>}.<core::String>(0);
+ };
+ dynamic f3d = #C6;
+ dynamic c3d = f3d{dynamic}.call(42);
+ self::expect(true, c3d is{ForNonNullableByDefault} self::B<core::String>);
+ self::expect(false, c3d is{ForNonNullableByDefault} self::B<core::int>);
+ self::expect(42, c3d{dynamic}.field1);
+ self::expect("", c3d{dynamic}.field2);
+ self::throws(() → dynamic => f3d{dynamic}.call());
+ self::throws(() → dynamic => f3d{dynamic}.call(0, 0));
+ self::throws(() → dynamic => f3d{dynamic}.call<core::String>(0));
+ (core::int, core::String) → self::B<core::String> f3e = #C8;
+ self::B<core::String> c3e = f3e(42, "foo"){(core::int, core::String) → self::B<core::String>};
+ self::expect(true, c3e is{ForNonNullableByDefault} self::B<core::String>);
+ self::expect(false, c3e is{ForNonNullableByDefault} self::B<core::int>);
+ self::expect(42, c3e.{self::B::field1}{core::int});
+ self::expect("foo", c3e.{self::B::field2}{core::String});
+ () → Null {
+ let final Never #t8 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:107:8: Error: Too few positional arguments: 2 required, 0 given.
+ f3e(); // error
+ ^" in f3e{<inapplicable>}.();
+ let final Never #t9 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:108:8: Error: Too few positional arguments: 2 required, 1 given.
+ f3e(0); // error
+ ^" in f3e{<inapplicable>}.(0);
+ let final Never #t10 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:109:8: Error: Expected 0 type arguments.
+ f3e<String>(0, ''); // error
+ ^" in f3e{<inapplicable>}.<core::String>(0, "");
+ };
+ dynamic f3f = #C8;
+ dynamic c3f = f3f{dynamic}.call(42, "foo");
+ self::expect(true, c3f is{ForNonNullableByDefault} self::B<core::String>);
+ self::expect(false, c3f is{ForNonNullableByDefault} self::B<core::int>);
+ self::expect(42, c3f{dynamic}.field1);
+ self::expect("foo", c3f{dynamic}.field2);
+ self::throws(() → dynamic => c3f{dynamic}.call());
+ self::throws(() → dynamic => c3f{dynamic}.call(0));
+ self::throws(() → dynamic => c3f{dynamic}.call<core::String>(0));
+ <X extends core::num>() → self::B<X> f4a = #C9;
+ self::B<core::num> c4a = f4a<core::num>(){() → self::B<core::num>};
+ self::expect(true, c4a is{ForNonNullableByDefault} self::B<core::num>);
+ self::expect(false, c4a is{ForNonNullableByDefault} self::B<core::int>);
+ self::B<core::int> c4b = f4a<core::int>(){() → self::B<core::int>};
+ self::expect(true, c4b is{ForNonNullableByDefault} self::B<core::int>);
+ self::expect(false, c4b is{ForNonNullableByDefault} self::B<core::double>);
+ () → Null {
+ let final Never #t11 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:130:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+ f4a(0); // error
+ ^" in f4a{<inapplicable>}.<core::num>(0);
+ f4a<core::String>(){() → self::B<core::String>};
+ };
+ dynamic f4b = #C9;
+ dynamic c4c = f4b{dynamic}.call();
+ self::expect(true, c4c is{ForNonNullableByDefault} self::B<core::num>);
+ self::expect(false, c4c is{ForNonNullableByDefault} self::B<core::int>);
+ dynamic c4d = f4b{dynamic}.call<core::int>();
+ self::expect(true, c4d is{ForNonNullableByDefault} self::B<core::int>);
+ self::expect(false, c4d is{ForNonNullableByDefault} self::B<core::double>);
+ self::throws(() → dynamic => f4b{dynamic}.call(0));
+ self::throws(() → dynamic => f4b{dynamic}.call<core::String>());
+ <X extends core::num, unrelated Y extends core::String>() → self::B<X> f5a = #C10;
+ self::B<core::num> c5a = f5a<core::num, core::String>(){() → self::B<core::num>};
+ self::expect(true, c5a is{ForNonNullableByDefault} self::B<core::num>);
+ self::expect(false, c5a is{ForNonNullableByDefault} self::B<core::int>);
+ self::B<core::int> c5b = f5a<core::int, core::String>(){() → self::B<core::int>};
+ self::expect(true, c5b is{ForNonNullableByDefault} self::B<core::int>);
+ self::expect(false, c5b is{ForNonNullableByDefault} self::B<core::double>);
+ () → Null {
+ let final Never #t12 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:152:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+ f5a(0); // error
+ ^" in f5a{<inapplicable>}.<core::num, core::String>(0);
+ let final Never #t13 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:153:8: Error: Expected 2 type arguments.
+ f5a<String>(); // error
+ ^" in f5a{<inapplicable>}.<core::String>();
+ f5a<core::String, core::String>(){() → self::B<core::String>};
+ f5a<core::num, core::num>(){() → self::B<core::num>};
+ };
+ dynamic f5b = #C10;
+ dynamic c5c = f5b{dynamic}.call();
+ self::expect(true, c5c is{ForNonNullableByDefault} self::B<core::num>);
+ self::expect(false, c5c is{ForNonNullableByDefault} self::B<core::int>);
+ dynamic c5d = f5b{dynamic}.call<core::int, core::String>();
+ self::expect(true, c5d is{ForNonNullableByDefault} self::B<core::int>);
+ self::expect(false, c5d is{ForNonNullableByDefault} self::B<core::double>);
+ self::throws(() → dynamic => f5b{dynamic}.call(0));
+ self::throws(() → dynamic => f5b{dynamic}.call<core::String>());
+ self::throws(() → dynamic => f5b{dynamic}.call<core::String, core::String>());
+ self::throws(() → dynamic => f5b{dynamic}.call<core::num, core::num>());
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C11}) → dynamic {
+ try {
+ f(){() → dynamic};
+ }
+ on core::Object catch(final core::Object e) {
+ core::print("Thrown: ${e}");
+ return;
+ }
+ if(!self::inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw "Expected exception";
+}
+static method _#DA2#new#tearOff<unrelated X extends core::num>() → self::A
+ return new self::A::•();
+static method _#DB2#_#tearOff<X extends core::num>(core::int field1, core::String field2) → self::B<self::_#DB2#_#tearOff::X>
+ return new self::B::_<self::_#DB2#_#tearOff::X>(field1, field2);
+static method _#DB2#new#tearOff<X extends core::num>() → self::B<self::_#DB2#new#tearOff::X>
+ return new self::B::•<self::_#DB2#new#tearOff::X>();
+static method _#DB2#foo#tearOff<X extends core::num>(core::int field1) → self::B<self::_#DB2#foo#tearOff::X>
+ return new self::B::foo<self::_#DB2#foo#tearOff::X>(field1);
+static method _#DB2#bar#tearOff<X extends core::num>(core::int i, core::String j) → self::B<self::_#DB2#bar#tearOff::X>
+ return self::B::bar<self::_#DB2#bar#tearOff::X>(i, j);
+static method _#DB3#_#tearOff<X extends core::num, unrelated Y extends core::String>(core::int field1, core::String field2) → self::B<self::_#DB3#_#tearOff::X>
+ return new self::B::_<self::_#DB3#_#tearOff::X>(field1, field2);
+static method _#DB3#new#tearOff<X extends core::num, unrelated Y extends core::String>() → self::B<self::_#DB3#new#tearOff::X>
+ return new self::B::•<self::_#DB3#new#tearOff::X>();
+static method _#DB3#foo#tearOff<X extends core::num, unrelated Y extends core::String>(core::int field1) → self::B<self::_#DB3#foo#tearOff::X>
+ return new self::B::foo<self::_#DB3#foo#tearOff::X>(field1);
+static method _#DB3#bar#tearOff<X extends core::num, unrelated Y extends core::String>(core::int i, core::String j) → self::B<self::_#DB3#bar#tearOff::X>
+ return self::B::bar<self::_#DB3#bar#tearOff::X>(i, j);
+
+constants {
+ #C1 = static-tearoff self::A::_#new#tearOff
+ #C2 = static-tearoff self::_#DA2#new#tearOff
+ #C3 = static-tearoff self::B::_#new#tearOff
+ #C4 = instantiation self::B::_#new#tearOff <core::String>
+ #C5 = static-tearoff self::B::_#foo#tearOff
+ #C6 = instantiation self::B::_#foo#tearOff <core::String>
+ #C7 = static-tearoff self::B::_#bar#tearOff
+ #C8 = instantiation self::B::_#bar#tearOff <core::String>
+ #C9 = static-tearoff self::_#DB2#new#tearOff
+ #C10 = static-tearoff self::_#DB3#new#tearOff
+ #C11 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.textual_outline.expect
new file mode 100644
index 0000000..fa1b6a2
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.textual_outline.expect
@@ -0,0 +1,21 @@
+final bool inSoundMode = <int?>[] is! List<int>;
+
+class A {}
+
+class B<X> {
+ int field1;
+ String field2;
+ B._(this.field1, this.field2);
+ B() : this._(0, '');
+ B.foo(this.field1) : field2 = '';
+ factory B.bar(int i, String j) => new B<X>._(i, j);
+}
+
+typedef DA1 = A;
+typedef DA2<X extends num> = A;
+typedef DB1 = B<String>;
+typedef DB2<X extends num> = B<X>;
+typedef DB3<X extends num, Y extends String> = B<X>;
+main() {}
+expect(expected, actual) {}
+throws(Function() f, {bool inSoundModeOnly: false}) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..f65e858
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.textual_outline_modelled.expect
@@ -0,0 +1,20 @@
+class A {}
+
+class B<X> {
+ B() : this._(0, '');
+ B._(this.field1, this.field2);
+ B.foo(this.field1) : field2 = '';
+ String field2;
+ factory B.bar(int i, String j) => new B<X>._(i, j);
+ int field1;
+}
+
+expect(expected, actual) {}
+final bool inSoundMode = <int?>[] is! List<int>;
+main() {}
+throws(Function() f, {bool inSoundModeOnly: false}) {}
+typedef DA1 = A;
+typedef DA2<X extends num> = A;
+typedef DB1 = B<String>;
+typedef DB2<X extends num> = B<X>;
+typedef DB3<X extends num, Y extends String> = B<X>;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.weak.expect
new file mode 100644
index 0000000..f4e5e89
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.weak.expect
@@ -0,0 +1,330 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:34:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+// f1a(0); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:46:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+// f2a(0); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:47:8: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+// f2a<String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:65:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+// f3a(0); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:66:8: Error: Expected 0 type arguments.
+// f3a<String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:85:8: Error: Too few positional arguments: 1 required, 0 given.
+// f3c(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:86:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f3c(0, 0); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:87:8: Error: Expected 0 type arguments.
+// f3c<String>(0); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:107:8: Error: Too few positional arguments: 2 required, 0 given.
+// f3e(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:108:8: Error: Too few positional arguments: 2 required, 1 given.
+// f3e(0); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:109:8: Error: Expected 0 type arguments.
+// f3e<String>(0, ''); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:130:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+// f4a(0); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:131:8: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+// f4a<String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:152:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+// f5a(0); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:153:8: Error: Expected 2 type arguments.
+// f5a<String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:154:8: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+// f5a<String, String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:155:8: Error: Type argument 'num' doesn't conform to the bound 'String' of the type variable 'Y' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+// f5a<num, num>(); // error
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef DA1 = self::A;
+typedef DA2<unrelated X extends core::num> = self::A;
+typedef DB1 = self::B<core::String>;
+typedef DB2<X extends core::num> = self::B<X>;
+typedef DB3<X extends core::num, unrelated Y extends core::String> = self::B<X>;
+class A extends core::Object {
+ synthetic constructor •() → self::A
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff() → self::A
+ return new self::A::•();
+}
+class B<X extends core::Object? = dynamic> extends core::Object {
+ field core::int field1;
+ field core::String field2;
+ constructor _(core::int field1, core::String field2) → self::B<self::B::X%>
+ : self::B::field1 = field1, self::B::field2 = field2, super core::Object::•()
+ ;
+ constructor •() → self::B<self::B::X%>
+ : this self::B::_(0, "")
+ ;
+ constructor foo(core::int field1) → self::B<self::B::X%>
+ : self::B::field1 = field1, self::B::field2 = "", super core::Object::•()
+ ;
+ static method _#_#tearOff<X extends core::Object? = dynamic>(core::int field1, core::String field2) → self::B<self::B::_#_#tearOff::X%>
+ return new self::B::_<self::B::_#_#tearOff::X%>(field1, field2);
+ static method _#new#tearOff<X extends core::Object? = dynamic>() → self::B<self::B::_#new#tearOff::X%>
+ return new self::B::•<self::B::_#new#tearOff::X%>();
+ static method _#foo#tearOff<X extends core::Object? = dynamic>(core::int field1) → self::B<self::B::_#foo#tearOff::X%>
+ return new self::B::foo<self::B::_#foo#tearOff::X%>(field1);
+ static factory bar<X extends core::Object? = dynamic>(core::int i, core::String j) → self::B<self::B::bar::X%>
+ return new self::B::_<self::B::bar::X%>(i, j);
+ static method _#bar#tearOff<X extends core::Object? = dynamic>(core::int i, core::String j) → self::B<self::B::_#bar#tearOff::X%>
+ return self::B::bar<self::B::_#bar#tearOff::X%>(i, j);
+}
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+ () → self::A f1a = #C1;
+ self::A c1a = f1a(){() → self::A};
+ self::expect(true, c1a is{ForNonNullableByDefault} self::A);
+ () → Null {
+ let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:34:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+ f1a(0); // error
+ ^" in f1a{<inapplicable>}.(0);
+ };
+ dynamic f1b = #C1;
+ dynamic c1b = f1b{dynamic}.call();
+ self::expect(true, c1b is{ForNonNullableByDefault} self::A);
+ self::throws(() → dynamic => f1b{dynamic}.call(0));
+ <unrelated X extends core::num>() → self::A f2a = #C2;
+ self::A c2a = f2a<core::num>(){() → self::A};
+ self::expect(true, c2a is{ForNonNullableByDefault} self::A);
+ () → Null {
+ let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:46:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+ f2a(0); // error
+ ^" in f2a{<inapplicable>}.<core::num>(0);
+ f2a<core::String>(){() → self::A};
+ };
+ dynamic f2b = #C2;
+ dynamic c2b = f2b{dynamic}.call();
+ self::expect(true, c2b is{ForNonNullableByDefault} self::A);
+ dynamic c2c = f2b{dynamic}.call<core::int>();
+ self::expect(true, c2c is{ForNonNullableByDefault} self::A);
+ self::throws(() → dynamic => f2b{dynamic}.call(0));
+ self::throws(() → dynamic => f2b{dynamic}.call<core::String>());
+ () → self::B<core::String> f3a = #C4;
+ self::B<core::String> c3a = f3a(){() → self::B<core::String>};
+ self::expect(true, c3a is{ForNonNullableByDefault} self::B<core::String>);
+ self::expect(false, c3a is{ForNonNullableByDefault} self::B<core::int>);
+ self::expect(0, c3a.{self::B::field1}{core::int});
+ self::expect("", c3a.{self::B::field2}{core::String});
+ () → Null {
+ let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:65:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+ f3a(0); // error
+ ^" in f3a{<inapplicable>}.(0);
+ let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:66:8: Error: Expected 0 type arguments.
+ f3a<String>(); // error
+ ^" in f3a{<inapplicable>}.<core::String>();
+ };
+ dynamic f3b = #C4;
+ dynamic c3b = f3b{dynamic}.call();
+ self::expect(true, c3b is{ForNonNullableByDefault} self::B<core::String>);
+ self::expect(false, c3b is{ForNonNullableByDefault} self::B<core::int>);
+ self::expect(0, c3a.{self::B::field1}{core::int});
+ self::expect("", c3a.{self::B::field2}{core::String});
+ self::throws(() → dynamic => f3b{dynamic}.call(0));
+ self::throws(() → dynamic => f3b{dynamic}.call<core::String>());
+ (core::int) → self::B<core::String> f3c = #C6;
+ self::B<core::String> c3c = f3c(42){(core::int) → self::B<core::String>};
+ self::expect(true, c3c is{ForNonNullableByDefault} self::B<core::String>);
+ self::expect(false, c3c is{ForNonNullableByDefault} self::B<core::int>);
+ self::expect(42, c3c.{self::B::field1}{core::int});
+ self::expect("", c3c.{self::B::field2}{core::String});
+ () → Null {
+ let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:85:8: Error: Too few positional arguments: 1 required, 0 given.
+ f3c(); // error
+ ^" in f3c{<inapplicable>}.();
+ let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:86:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f3c(0, 0); // error
+ ^" in f3c{<inapplicable>}.(0, 0);
+ let final Never #t7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:87:8: Error: Expected 0 type arguments.
+ f3c<String>(0); // error
+ ^" in f3c{<inapplicable>}.<core::String>(0);
+ };
+ dynamic f3d = #C6;
+ dynamic c3d = f3d{dynamic}.call(42);
+ self::expect(true, c3d is{ForNonNullableByDefault} self::B<core::String>);
+ self::expect(false, c3d is{ForNonNullableByDefault} self::B<core::int>);
+ self::expect(42, c3d{dynamic}.field1);
+ self::expect("", c3d{dynamic}.field2);
+ self::throws(() → dynamic => f3d{dynamic}.call());
+ self::throws(() → dynamic => f3d{dynamic}.call(0, 0));
+ self::throws(() → dynamic => f3d{dynamic}.call<core::String>(0));
+ (core::int, core::String) → self::B<core::String> f3e = #C8;
+ self::B<core::String> c3e = f3e(42, "foo"){(core::int, core::String) → self::B<core::String>};
+ self::expect(true, c3e is{ForNonNullableByDefault} self::B<core::String>);
+ self::expect(false, c3e is{ForNonNullableByDefault} self::B<core::int>);
+ self::expect(42, c3e.{self::B::field1}{core::int});
+ self::expect("foo", c3e.{self::B::field2}{core::String});
+ () → Null {
+ let final Never #t8 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:107:8: Error: Too few positional arguments: 2 required, 0 given.
+ f3e(); // error
+ ^" in f3e{<inapplicable>}.();
+ let final Never #t9 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:108:8: Error: Too few positional arguments: 2 required, 1 given.
+ f3e(0); // error
+ ^" in f3e{<inapplicable>}.(0);
+ let final Never #t10 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:109:8: Error: Expected 0 type arguments.
+ f3e<String>(0, ''); // error
+ ^" in f3e{<inapplicable>}.<core::String>(0, "");
+ };
+ dynamic f3f = #C8;
+ dynamic c3f = f3f{dynamic}.call(42, "foo");
+ self::expect(true, c3f is{ForNonNullableByDefault} self::B<core::String>);
+ self::expect(false, c3f is{ForNonNullableByDefault} self::B<core::int>);
+ self::expect(42, c3f{dynamic}.field1);
+ self::expect("foo", c3f{dynamic}.field2);
+ self::throws(() → dynamic => c3f{dynamic}.call());
+ self::throws(() → dynamic => c3f{dynamic}.call(0));
+ self::throws(() → dynamic => c3f{dynamic}.call<core::String>(0));
+ <X extends core::num>() → self::B<X> f4a = #C9;
+ self::B<core::num> c4a = f4a<core::num>(){() → self::B<core::num>};
+ self::expect(true, c4a is{ForNonNullableByDefault} self::B<core::num>);
+ self::expect(false, c4a is{ForNonNullableByDefault} self::B<core::int>);
+ self::B<core::int> c4b = f4a<core::int>(){() → self::B<core::int>};
+ self::expect(true, c4b is{ForNonNullableByDefault} self::B<core::int>);
+ self::expect(false, c4b is{ForNonNullableByDefault} self::B<core::double>);
+ () → Null {
+ let final Never #t11 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:130:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+ f4a(0); // error
+ ^" in f4a{<inapplicable>}.<core::num>(0);
+ f4a<core::String>(){() → self::B<core::String>};
+ };
+ dynamic f4b = #C9;
+ dynamic c4c = f4b{dynamic}.call();
+ self::expect(true, c4c is{ForNonNullableByDefault} self::B<core::num>);
+ self::expect(false, c4c is{ForNonNullableByDefault} self::B<core::int>);
+ dynamic c4d = f4b{dynamic}.call<core::int>();
+ self::expect(true, c4d is{ForNonNullableByDefault} self::B<core::int>);
+ self::expect(false, c4d is{ForNonNullableByDefault} self::B<core::double>);
+ self::throws(() → dynamic => f4b{dynamic}.call(0));
+ self::throws(() → dynamic => f4b{dynamic}.call<core::String>());
+ <X extends core::num, unrelated Y extends core::String>() → self::B<X> f5a = #C10;
+ self::B<core::num> c5a = f5a<core::num, core::String>(){() → self::B<core::num>};
+ self::expect(true, c5a is{ForNonNullableByDefault} self::B<core::num>);
+ self::expect(false, c5a is{ForNonNullableByDefault} self::B<core::int>);
+ self::B<core::int> c5b = f5a<core::int, core::String>(){() → self::B<core::int>};
+ self::expect(true, c5b is{ForNonNullableByDefault} self::B<core::int>);
+ self::expect(false, c5b is{ForNonNullableByDefault} self::B<core::double>);
+ () → Null {
+ let final Never #t12 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:152:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+ f5a(0); // error
+ ^" in f5a{<inapplicable>}.<core::num, core::String>(0);
+ let final Never #t13 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:153:8: Error: Expected 2 type arguments.
+ f5a<String>(); // error
+ ^" in f5a{<inapplicable>}.<core::String>();
+ f5a<core::String, core::String>(){() → self::B<core::String>};
+ f5a<core::num, core::num>(){() → self::B<core::num>};
+ };
+ dynamic f5b = #C10;
+ dynamic c5c = f5b{dynamic}.call();
+ self::expect(true, c5c is{ForNonNullableByDefault} self::B<core::num>);
+ self::expect(false, c5c is{ForNonNullableByDefault} self::B<core::int>);
+ dynamic c5d = f5b{dynamic}.call<core::int, core::String>();
+ self::expect(true, c5d is{ForNonNullableByDefault} self::B<core::int>);
+ self::expect(false, c5d is{ForNonNullableByDefault} self::B<core::double>);
+ self::throws(() → dynamic => f5b{dynamic}.call(0));
+ self::throws(() → dynamic => f5b{dynamic}.call<core::String>());
+ self::throws(() → dynamic => f5b{dynamic}.call<core::String, core::String>());
+ self::throws(() → dynamic => f5b{dynamic}.call<core::num, core::num>());
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C11}) → dynamic {
+ try {
+ f(){() → dynamic};
+ }
+ on core::Object catch(final core::Object e) {
+ core::print("Thrown: ${e}");
+ return;
+ }
+ if(!self::inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw "Expected exception";
+}
+static method _#DA2#new#tearOff<unrelated X extends core::num>() → self::A
+ return new self::A::•();
+static method _#DB2#_#tearOff<X extends core::num>(core::int field1, core::String field2) → self::B<self::_#DB2#_#tearOff::X>
+ return new self::B::_<self::_#DB2#_#tearOff::X>(field1, field2);
+static method _#DB2#new#tearOff<X extends core::num>() → self::B<self::_#DB2#new#tearOff::X>
+ return new self::B::•<self::_#DB2#new#tearOff::X>();
+static method _#DB2#foo#tearOff<X extends core::num>(core::int field1) → self::B<self::_#DB2#foo#tearOff::X>
+ return new self::B::foo<self::_#DB2#foo#tearOff::X>(field1);
+static method _#DB2#bar#tearOff<X extends core::num>(core::int i, core::String j) → self::B<self::_#DB2#bar#tearOff::X>
+ return self::B::bar<self::_#DB2#bar#tearOff::X>(i, j);
+static method _#DB3#_#tearOff<X extends core::num, unrelated Y extends core::String>(core::int field1, core::String field2) → self::B<self::_#DB3#_#tearOff::X>
+ return new self::B::_<self::_#DB3#_#tearOff::X>(field1, field2);
+static method _#DB3#new#tearOff<X extends core::num, unrelated Y extends core::String>() → self::B<self::_#DB3#new#tearOff::X>
+ return new self::B::•<self::_#DB3#new#tearOff::X>();
+static method _#DB3#foo#tearOff<X extends core::num, unrelated Y extends core::String>(core::int field1) → self::B<self::_#DB3#foo#tearOff::X>
+ return new self::B::foo<self::_#DB3#foo#tearOff::X>(field1);
+static method _#DB3#bar#tearOff<X extends core::num, unrelated Y extends core::String>(core::int i, core::String j) → self::B<self::_#DB3#bar#tearOff::X>
+ return self::B::bar<self::_#DB3#bar#tearOff::X>(i, j);
+
+constants {
+ #C1 = static-tearoff self::A::_#new#tearOff
+ #C2 = static-tearoff self::_#DA2#new#tearOff
+ #C3 = static-tearoff self::B::_#new#tearOff
+ #C4 = instantiation self::B::_#new#tearOff <core::String*>
+ #C5 = static-tearoff self::B::_#foo#tearOff
+ #C6 = instantiation self::B::_#foo#tearOff <core::String*>
+ #C7 = static-tearoff self::B::_#bar#tearOff
+ #C8 = instantiation self::B::_#bar#tearOff <core::String*>
+ #C9 = static-tearoff self::_#DB2#new#tearOff
+ #C10 = static-tearoff self::_#DB3#new#tearOff
+ #C11 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.weak.outline.expect
new file mode 100644
index 0000000..10537bf
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.weak.outline.expect
@@ -0,0 +1,60 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef DA1 = self::A;
+typedef DA2<unrelated X extends core::num> = self::A;
+typedef DB1 = self::B<core::String>;
+typedef DB2<X extends core::num> = self::B<X>;
+typedef DB3<X extends core::num, unrelated Y extends core::String> = self::B<X>;
+class A extends core::Object {
+ synthetic constructor •() → self::A
+ ;
+ static method _#new#tearOff() → self::A
+ return new self::A::•();
+}
+class B<X extends core::Object? = dynamic> extends core::Object {
+ field core::int field1;
+ field core::String field2;
+ constructor _(core::int field1, core::String field2) → self::B<self::B::X%>
+ ;
+ constructor •() → self::B<self::B::X%>
+ ;
+ constructor foo(core::int field1) → self::B<self::B::X%>
+ ;
+ static method _#_#tearOff<X extends core::Object? = dynamic>(core::int field1, core::String field2) → self::B<self::B::_#_#tearOff::X%>
+ return new self::B::_<self::B::_#_#tearOff::X%>(field1, field2);
+ static method _#new#tearOff<X extends core::Object? = dynamic>() → self::B<self::B::_#new#tearOff::X%>
+ return new self::B::•<self::B::_#new#tearOff::X%>();
+ static method _#foo#tearOff<X extends core::Object? = dynamic>(core::int field1) → self::B<self::B::_#foo#tearOff::X%>
+ return new self::B::foo<self::B::_#foo#tearOff::X%>(field1);
+ static factory bar<X extends core::Object? = dynamic>(core::int i, core::String j) → self::B<self::B::bar::X%>
+ ;
+ static method _#bar#tearOff<X extends core::Object? = dynamic>(core::int i, core::String j) → self::B<self::B::_#bar#tearOff::X%>
+ return self::B::bar<self::B::_#bar#tearOff::X%>(i, j);
+}
+static final field core::bool inSoundMode;
+static method main() → dynamic
+ ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+ ;
+static method throws(() → dynamic f, {core::bool inSoundModeOnly}) → dynamic
+ ;
+static method _#DA2#new#tearOff<unrelated X extends core::num>() → self::A
+ return new self::A::•();
+static method _#DB2#_#tearOff<X extends core::num>(core::int field1, core::String field2) → self::B<self::_#DB2#_#tearOff::X>
+ return new self::B::_<self::_#DB2#_#tearOff::X>(field1, field2);
+static method _#DB2#new#tearOff<X extends core::num>() → self::B<self::_#DB2#new#tearOff::X>
+ return new self::B::•<self::_#DB2#new#tearOff::X>();
+static method _#DB2#foo#tearOff<X extends core::num>(core::int field1) → self::B<self::_#DB2#foo#tearOff::X>
+ return new self::B::foo<self::_#DB2#foo#tearOff::X>(field1);
+static method _#DB2#bar#tearOff<X extends core::num>(core::int i, core::String j) → self::B<self::_#DB2#bar#tearOff::X>
+ return self::B::bar<self::_#DB2#bar#tearOff::X>(i, j);
+static method _#DB3#_#tearOff<X extends core::num, unrelated Y extends core::String>(core::int field1, core::String field2) → self::B<self::_#DB3#_#tearOff::X>
+ return new self::B::_<self::_#DB3#_#tearOff::X>(field1, field2);
+static method _#DB3#new#tearOff<X extends core::num, unrelated Y extends core::String>() → self::B<self::_#DB3#new#tearOff::X>
+ return new self::B::•<self::_#DB3#new#tearOff::X>();
+static method _#DB3#foo#tearOff<X extends core::num, unrelated Y extends core::String>(core::int field1) → self::B<self::_#DB3#foo#tearOff::X>
+ return new self::B::foo<self::_#DB3#foo#tearOff::X>(field1);
+static method _#DB3#bar#tearOff<X extends core::num, unrelated Y extends core::String>(core::int i, core::String j) → self::B<self::_#DB3#bar#tearOff::X>
+ return self::B::bar<self::_#DB3#bar#tearOff::X>(i, j);
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.weak.transformed.expect
new file mode 100644
index 0000000..12bd083
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart.weak.transformed.expect
@@ -0,0 +1,330 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:34:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+// f1a(0); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:46:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+// f2a(0); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:47:8: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+// f2a<String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:65:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+// f3a(0); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:66:8: Error: Expected 0 type arguments.
+// f3a<String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:85:8: Error: Too few positional arguments: 1 required, 0 given.
+// f3c(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:86:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f3c(0, 0); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:87:8: Error: Expected 0 type arguments.
+// f3c<String>(0); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:107:8: Error: Too few positional arguments: 2 required, 0 given.
+// f3e(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:108:8: Error: Too few positional arguments: 2 required, 1 given.
+// f3e(0); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:109:8: Error: Expected 0 type arguments.
+// f3e<String>(0, ''); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:130:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+// f4a(0); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:131:8: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+// f4a<String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:152:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+// f5a(0); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:153:8: Error: Expected 2 type arguments.
+// f5a<String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:154:8: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+// f5a<String, String>(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:155:8: Error: Type argument 'num' doesn't conform to the bound 'String' of the type variable 'Y' on 'call'.
+// Try changing type arguments so that they conform to the bounds.
+// f5a<num, num>(); // error
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef DA1 = self::A;
+typedef DA2<unrelated X extends core::num> = self::A;
+typedef DB1 = self::B<core::String>;
+typedef DB2<X extends core::num> = self::B<X>;
+typedef DB3<X extends core::num, unrelated Y extends core::String> = self::B<X>;
+class A extends core::Object {
+ synthetic constructor •() → self::A
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff() → self::A
+ return new self::A::•();
+}
+class B<X extends core::Object? = dynamic> extends core::Object {
+ field core::int field1;
+ field core::String field2;
+ constructor _(core::int field1, core::String field2) → self::B<self::B::X%>
+ : self::B::field1 = field1, self::B::field2 = field2, super core::Object::•()
+ ;
+ constructor •() → self::B<self::B::X%>
+ : this self::B::_(0, "")
+ ;
+ constructor foo(core::int field1) → self::B<self::B::X%>
+ : self::B::field1 = field1, self::B::field2 = "", super core::Object::•()
+ ;
+ static method _#_#tearOff<X extends core::Object? = dynamic>(core::int field1, core::String field2) → self::B<self::B::_#_#tearOff::X%>
+ return new self::B::_<self::B::_#_#tearOff::X%>(field1, field2);
+ static method _#new#tearOff<X extends core::Object? = dynamic>() → self::B<self::B::_#new#tearOff::X%>
+ return new self::B::•<self::B::_#new#tearOff::X%>();
+ static method _#foo#tearOff<X extends core::Object? = dynamic>(core::int field1) → self::B<self::B::_#foo#tearOff::X%>
+ return new self::B::foo<self::B::_#foo#tearOff::X%>(field1);
+ static factory bar<X extends core::Object? = dynamic>(core::int i, core::String j) → self::B<self::B::bar::X%>
+ return new self::B::_<self::B::bar::X%>(i, j);
+ static method _#bar#tearOff<X extends core::Object? = dynamic>(core::int i, core::String j) → self::B<self::B::_#bar#tearOff::X%>
+ return self::B::bar<self::B::_#bar#tearOff::X%>(i, j);
+}
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+ () → self::A f1a = #C1;
+ self::A c1a = f1a(){() → self::A};
+ self::expect(true, c1a is{ForNonNullableByDefault} self::A);
+ () → Null {
+ let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:34:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+ f1a(0); // error
+ ^" in f1a{<inapplicable>}.(0);
+ };
+ dynamic f1b = #C1;
+ dynamic c1b = f1b{dynamic}.call();
+ self::expect(true, c1b is{ForNonNullableByDefault} self::A);
+ self::throws(() → dynamic => f1b{dynamic}.call(0));
+ <unrelated X extends core::num>() → self::A f2a = #C2;
+ self::A c2a = f2a<core::num>(){() → self::A};
+ self::expect(true, c2a is{ForNonNullableByDefault} self::A);
+ () → Null {
+ let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:46:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+ f2a(0); // error
+ ^" in f2a{<inapplicable>}.<core::num>(0);
+ f2a<core::String>(){() → self::A};
+ };
+ dynamic f2b = #C2;
+ dynamic c2b = f2b{dynamic}.call();
+ self::expect(true, c2b is{ForNonNullableByDefault} self::A);
+ dynamic c2c = f2b{dynamic}.call<core::int>();
+ self::expect(true, c2c is{ForNonNullableByDefault} self::A);
+ self::throws(() → dynamic => f2b{dynamic}.call(0));
+ self::throws(() → dynamic => f2b{dynamic}.call<core::String>());
+ () → self::B<core::String> f3a = #C4;
+ self::B<core::String> c3a = f3a(){() → self::B<core::String>};
+ self::expect(true, c3a is{ForNonNullableByDefault} self::B<core::String>);
+ self::expect(false, c3a is{ForNonNullableByDefault} self::B<core::int>);
+ self::expect(0, c3a.{self::B::field1}{core::int});
+ self::expect("", c3a.{self::B::field2}{core::String});
+ () → Null {
+ let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:65:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+ f3a(0); // error
+ ^" in f3a{<inapplicable>}.(0);
+ let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:66:8: Error: Expected 0 type arguments.
+ f3a<String>(); // error
+ ^" in f3a{<inapplicable>}.<core::String>();
+ };
+ dynamic f3b = #C4;
+ dynamic c3b = f3b{dynamic}.call();
+ self::expect(true, c3b is{ForNonNullableByDefault} self::B<core::String>);
+ self::expect(false, c3b is{ForNonNullableByDefault} self::B<core::int>);
+ self::expect(0, c3a.{self::B::field1}{core::int});
+ self::expect("", c3a.{self::B::field2}{core::String});
+ self::throws(() → dynamic => f3b{dynamic}.call(0));
+ self::throws(() → dynamic => f3b{dynamic}.call<core::String>());
+ (core::int) → self::B<core::String> f3c = #C6;
+ self::B<core::String> c3c = f3c(42){(core::int) → self::B<core::String>};
+ self::expect(true, c3c is{ForNonNullableByDefault} self::B<core::String>);
+ self::expect(false, c3c is{ForNonNullableByDefault} self::B<core::int>);
+ self::expect(42, c3c.{self::B::field1}{core::int});
+ self::expect("", c3c.{self::B::field2}{core::String});
+ () → Null {
+ let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:85:8: Error: Too few positional arguments: 1 required, 0 given.
+ f3c(); // error
+ ^" in f3c{<inapplicable>}.();
+ let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:86:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f3c(0, 0); // error
+ ^" in f3c{<inapplicable>}.(0, 0);
+ let final Never #t7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:87:8: Error: Expected 0 type arguments.
+ f3c<String>(0); // error
+ ^" in f3c{<inapplicable>}.<core::String>(0);
+ };
+ dynamic f3d = #C6;
+ dynamic c3d = f3d{dynamic}.call(42);
+ self::expect(true, c3d is{ForNonNullableByDefault} self::B<core::String>);
+ self::expect(false, c3d is{ForNonNullableByDefault} self::B<core::int>);
+ self::expect(42, c3d{dynamic}.field1);
+ self::expect("", c3d{dynamic}.field2);
+ self::throws(() → dynamic => f3d{dynamic}.call());
+ self::throws(() → dynamic => f3d{dynamic}.call(0, 0));
+ self::throws(() → dynamic => f3d{dynamic}.call<core::String>(0));
+ (core::int, core::String) → self::B<core::String> f3e = #C8;
+ self::B<core::String> c3e = f3e(42, "foo"){(core::int, core::String) → self::B<core::String>};
+ self::expect(true, c3e is{ForNonNullableByDefault} self::B<core::String>);
+ self::expect(false, c3e is{ForNonNullableByDefault} self::B<core::int>);
+ self::expect(42, c3e.{self::B::field1}{core::int});
+ self::expect("foo", c3e.{self::B::field2}{core::String});
+ () → Null {
+ let final Never #t8 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:107:8: Error: Too few positional arguments: 2 required, 0 given.
+ f3e(); // error
+ ^" in f3e{<inapplicable>}.();
+ let final Never #t9 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:108:8: Error: Too few positional arguments: 2 required, 1 given.
+ f3e(0); // error
+ ^" in f3e{<inapplicable>}.(0);
+ let final Never #t10 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:109:8: Error: Expected 0 type arguments.
+ f3e<String>(0, ''); // error
+ ^" in f3e{<inapplicable>}.<core::String>(0, "");
+ };
+ dynamic f3f = #C8;
+ dynamic c3f = f3f{dynamic}.call(42, "foo");
+ self::expect(true, c3f is{ForNonNullableByDefault} self::B<core::String>);
+ self::expect(false, c3f is{ForNonNullableByDefault} self::B<core::int>);
+ self::expect(42, c3f{dynamic}.field1);
+ self::expect("foo", c3f{dynamic}.field2);
+ self::throws(() → dynamic => c3f{dynamic}.call());
+ self::throws(() → dynamic => c3f{dynamic}.call(0));
+ self::throws(() → dynamic => c3f{dynamic}.call<core::String>(0));
+ <X extends core::num>() → self::B<X> f4a = #C9;
+ self::B<core::num> c4a = f4a<core::num>(){() → self::B<core::num>};
+ self::expect(true, c4a is{ForNonNullableByDefault} self::B<core::num>);
+ self::expect(false, c4a is{ForNonNullableByDefault} self::B<core::int>);
+ self::B<core::int> c4b = f4a<core::int>(){() → self::B<core::int>};
+ self::expect(true, c4b is{ForNonNullableByDefault} self::B<core::int>);
+ self::expect(false, c4b is{ForNonNullableByDefault} self::B<core::double>);
+ () → Null {
+ let final Never #t11 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:130:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+ f4a(0); // error
+ ^" in f4a{<inapplicable>}.<core::num>(0);
+ f4a<core::String>(){() → self::B<core::String>};
+ };
+ dynamic f4b = #C9;
+ dynamic c4c = f4b{dynamic}.call();
+ self::expect(true, c4c is{ForNonNullableByDefault} self::B<core::num>);
+ self::expect(false, c4c is{ForNonNullableByDefault} self::B<core::int>);
+ dynamic c4d = f4b{dynamic}.call<core::int>();
+ self::expect(true, c4d is{ForNonNullableByDefault} self::B<core::int>);
+ self::expect(false, c4d is{ForNonNullableByDefault} self::B<core::double>);
+ self::throws(() → dynamic => f4b{dynamic}.call(0));
+ self::throws(() → dynamic => f4b{dynamic}.call<core::String>());
+ <X extends core::num, unrelated Y extends core::String>() → self::B<X> f5a = #C10;
+ self::B<core::num> c5a = f5a<core::num, core::String>(){() → self::B<core::num>};
+ self::expect(true, c5a is{ForNonNullableByDefault} self::B<core::num>);
+ self::expect(false, c5a is{ForNonNullableByDefault} self::B<core::int>);
+ self::B<core::int> c5b = f5a<core::int, core::String>(){() → self::B<core::int>};
+ self::expect(true, c5b is{ForNonNullableByDefault} self::B<core::int>);
+ self::expect(false, c5b is{ForNonNullableByDefault} self::B<core::double>);
+ () → Null {
+ let final Never #t12 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:152:8: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+ f5a(0); // error
+ ^" in f5a{<inapplicable>}.<core::num, core::String>(0);
+ let final Never #t13 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/typedef_tear_off.dart:153:8: Error: Expected 2 type arguments.
+ f5a<String>(); // error
+ ^" in f5a{<inapplicable>}.<core::String>();
+ f5a<core::String, core::String>(){() → self::B<core::String>};
+ f5a<core::num, core::num>(){() → self::B<core::num>};
+ };
+ dynamic f5b = #C10;
+ dynamic c5c = f5b{dynamic}.call();
+ self::expect(true, c5c is{ForNonNullableByDefault} self::B<core::num>);
+ self::expect(false, c5c is{ForNonNullableByDefault} self::B<core::int>);
+ dynamic c5d = f5b{dynamic}.call<core::int, core::String>();
+ self::expect(true, c5d is{ForNonNullableByDefault} self::B<core::int>);
+ self::expect(false, c5d is{ForNonNullableByDefault} self::B<core::double>);
+ self::throws(() → dynamic => f5b{dynamic}.call(0));
+ self::throws(() → dynamic => f5b{dynamic}.call<core::String>());
+ self::throws(() → dynamic => f5b{dynamic}.call<core::String, core::String>());
+ self::throws(() → dynamic => f5b{dynamic}.call<core::num, core::num>());
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C11}) → dynamic {
+ try {
+ f(){() → dynamic};
+ }
+ on core::Object catch(final core::Object e) {
+ core::print("Thrown: ${e}");
+ return;
+ }
+ if(!self::inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw "Expected exception";
+}
+static method _#DA2#new#tearOff<unrelated X extends core::num>() → self::A
+ return new self::A::•();
+static method _#DB2#_#tearOff<X extends core::num>(core::int field1, core::String field2) → self::B<self::_#DB2#_#tearOff::X>
+ return new self::B::_<self::_#DB2#_#tearOff::X>(field1, field2);
+static method _#DB2#new#tearOff<X extends core::num>() → self::B<self::_#DB2#new#tearOff::X>
+ return new self::B::•<self::_#DB2#new#tearOff::X>();
+static method _#DB2#foo#tearOff<X extends core::num>(core::int field1) → self::B<self::_#DB2#foo#tearOff::X>
+ return new self::B::foo<self::_#DB2#foo#tearOff::X>(field1);
+static method _#DB2#bar#tearOff<X extends core::num>(core::int i, core::String j) → self::B<self::_#DB2#bar#tearOff::X>
+ return self::B::bar<self::_#DB2#bar#tearOff::X>(i, j);
+static method _#DB3#_#tearOff<X extends core::num, unrelated Y extends core::String>(core::int field1, core::String field2) → self::B<self::_#DB3#_#tearOff::X>
+ return new self::B::_<self::_#DB3#_#tearOff::X>(field1, field2);
+static method _#DB3#new#tearOff<X extends core::num, unrelated Y extends core::String>() → self::B<self::_#DB3#new#tearOff::X>
+ return new self::B::•<self::_#DB3#new#tearOff::X>();
+static method _#DB3#foo#tearOff<X extends core::num, unrelated Y extends core::String>(core::int field1) → self::B<self::_#DB3#foo#tearOff::X>
+ return new self::B::foo<self::_#DB3#foo#tearOff::X>(field1);
+static method _#DB3#bar#tearOff<X extends core::num, unrelated Y extends core::String>(core::int i, core::String j) → self::B<self::_#DB3#bar#tearOff::X>
+ return self::B::bar<self::_#DB3#bar#tearOff::X>(i, j);
+
+constants {
+ #C1 = static-tearoff self::A::_#new#tearOff
+ #C2 = static-tearoff self::_#DA2#new#tearOff
+ #C3 = static-tearoff self::B::_#new#tearOff
+ #C4 = instantiation self::B::_#new#tearOff <core::String*>
+ #C5 = static-tearoff self::B::_#foo#tearOff
+ #C6 = instantiation self::B::_#foo#tearOff <core::String*>
+ #C7 = static-tearoff self::B::_#bar#tearOff
+ #C8 = instantiation self::B::_#bar#tearOff <core::String*>
+ #C9 = static-tearoff self::_#DB2#new#tearOff
+ #C10 = static-tearoff self::_#DB3#new#tearOff
+ #C11 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart.strong.expect
index f6026a2..7292491 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart.strong.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart.strong.expect
@@ -31,24 +31,31 @@
return new self::A::•();
}
static method test1() → () → self::A
- return self::A::foo1;
+ return #C1;
static method test2() → () → self::A
return let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart:13:25: Error: A value of type 'A Function(int)' can't be returned from a function with return type 'A Function()'.
- 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart'.
A Function() test2() => A.foo2; // Error.
- ^" in self::A::foo2 as{TypeError,ForNonNullableByDefault} () → self::A;
+ ^" in (#C2) as{TypeError,ForNonNullableByDefault} () → self::A;
static method test3() → () → self::A
- return self::A::•;
+ return #C3;
static method test4() → (core::int) → self::A
return let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart:15:28: Error: A value of type 'A Function()' can't be returned from a function with return type 'A Function(int)'.
- 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart'.
A Function(int) test4() => A.new; // Error.
- ^" in self::A::• as{TypeError,ForNonNullableByDefault} (core::int) → self::A;
+ ^" in (#C3) as{TypeError,ForNonNullableByDefault} (core::int) → self::A;
static method test5() → () → self::A
- return self::A::bar1;
+ return #C4;
static method test6() → (core::int) → self::A
return let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart:17:28: Error: A value of type 'A Function()' can't be returned from a function with return type 'A Function(int)'.
- 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart'.
A Function(int) test6() => A.bar1; // Error.
- ^" in self::A::bar1 as{TypeError,ForNonNullableByDefault} (core::int) → self::A;
+ ^" in (#C4) as{TypeError,ForNonNullableByDefault} (core::int) → self::A;
static method main() → dynamic {}
+
+constants {
+ #C1 = constructor-tearoff self::A::foo1
+ #C2 = constructor-tearoff self::A::foo2
+ #C3 = constructor-tearoff self::A::•
+ #C4 = static-tearoff self::A::bar1
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart.strong.transformed.expect
index f6026a2..7292491 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart.strong.transformed.expect
@@ -31,24 +31,31 @@
return new self::A::•();
}
static method test1() → () → self::A
- return self::A::foo1;
+ return #C1;
static method test2() → () → self::A
return let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart:13:25: Error: A value of type 'A Function(int)' can't be returned from a function with return type 'A Function()'.
- 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart'.
A Function() test2() => A.foo2; // Error.
- ^" in self::A::foo2 as{TypeError,ForNonNullableByDefault} () → self::A;
+ ^" in (#C2) as{TypeError,ForNonNullableByDefault} () → self::A;
static method test3() → () → self::A
- return self::A::•;
+ return #C3;
static method test4() → (core::int) → self::A
return let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart:15:28: Error: A value of type 'A Function()' can't be returned from a function with return type 'A Function(int)'.
- 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart'.
A Function(int) test4() => A.new; // Error.
- ^" in self::A::• as{TypeError,ForNonNullableByDefault} (core::int) → self::A;
+ ^" in (#C3) as{TypeError,ForNonNullableByDefault} (core::int) → self::A;
static method test5() → () → self::A
- return self::A::bar1;
+ return #C4;
static method test6() → (core::int) → self::A
return let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart:17:28: Error: A value of type 'A Function()' can't be returned from a function with return type 'A Function(int)'.
- 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart'.
A Function(int) test6() => A.bar1; // Error.
- ^" in self::A::bar1 as{TypeError,ForNonNullableByDefault} (core::int) → self::A;
+ ^" in (#C4) as{TypeError,ForNonNullableByDefault} (core::int) → self::A;
static method main() → dynamic {}
+
+constants {
+ #C1 = constructor-tearoff self::A::foo1
+ #C2 = constructor-tearoff self::A::foo2
+ #C3 = constructor-tearoff self::A::•
+ #C4 = static-tearoff self::A::bar1
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart.weak.expect
index f6026a2..7292491 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart.weak.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart.weak.expect
@@ -31,24 +31,31 @@
return new self::A::•();
}
static method test1() → () → self::A
- return self::A::foo1;
+ return #C1;
static method test2() → () → self::A
return let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart:13:25: Error: A value of type 'A Function(int)' can't be returned from a function with return type 'A Function()'.
- 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart'.
A Function() test2() => A.foo2; // Error.
- ^" in self::A::foo2 as{TypeError,ForNonNullableByDefault} () → self::A;
+ ^" in (#C2) as{TypeError,ForNonNullableByDefault} () → self::A;
static method test3() → () → self::A
- return self::A::•;
+ return #C3;
static method test4() → (core::int) → self::A
return let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart:15:28: Error: A value of type 'A Function()' can't be returned from a function with return type 'A Function(int)'.
- 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart'.
A Function(int) test4() => A.new; // Error.
- ^" in self::A::• as{TypeError,ForNonNullableByDefault} (core::int) → self::A;
+ ^" in (#C3) as{TypeError,ForNonNullableByDefault} (core::int) → self::A;
static method test5() → () → self::A
- return self::A::bar1;
+ return #C4;
static method test6() → (core::int) → self::A
return let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart:17:28: Error: A value of type 'A Function()' can't be returned from a function with return type 'A Function(int)'.
- 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart'.
A Function(int) test6() => A.bar1; // Error.
- ^" in self::A::bar1 as{TypeError,ForNonNullableByDefault} (core::int) → self::A;
+ ^" in (#C4) as{TypeError,ForNonNullableByDefault} (core::int) → self::A;
static method main() → dynamic {}
+
+constants {
+ #C1 = constructor-tearoff self::A::foo1
+ #C2 = constructor-tearoff self::A::foo2
+ #C3 = constructor-tearoff self::A::•
+ #C4 = static-tearoff self::A::bar1
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart.weak.transformed.expect
index f6026a2..7292491 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart.weak.transformed.expect
@@ -31,24 +31,31 @@
return new self::A::•();
}
static method test1() → () → self::A
- return self::A::foo1;
+ return #C1;
static method test2() → () → self::A
return let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart:13:25: Error: A value of type 'A Function(int)' can't be returned from a function with return type 'A Function()'.
- 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart'.
A Function() test2() => A.foo2; // Error.
- ^" in self::A::foo2 as{TypeError,ForNonNullableByDefault} () → self::A;
+ ^" in (#C2) as{TypeError,ForNonNullableByDefault} () → self::A;
static method test3() → () → self::A
- return self::A::•;
+ return #C3;
static method test4() → (core::int) → self::A
return let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart:15:28: Error: A value of type 'A Function()' can't be returned from a function with return type 'A Function(int)'.
- 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart'.
A Function(int) test4() => A.new; // Error.
- ^" in self::A::• as{TypeError,ForNonNullableByDefault} (core::int) → self::A;
+ ^" in (#C3) as{TypeError,ForNonNullableByDefault} (core::int) → self::A;
static method test5() → () → self::A
- return self::A::bar1;
+ return #C4;
static method test6() → (core::int) → self::A
return let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart:17:28: Error: A value of type 'A Function()' can't be returned from a function with return type 'A Function(int)'.
- 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_with_context.dart'.
A Function(int) test6() => A.bar1; // Error.
- ^" in self::A::bar1 as{TypeError,ForNonNullableByDefault} (core::int) → self::A;
+ ^" in (#C4) as{TypeError,ForNonNullableByDefault} (core::int) → self::A;
static method main() → dynamic {}
+
+constants {
+ #C1 = constructor-tearoff self::A::foo1
+ #C2 = constructor-tearoff self::A::foo2
+ #C3 = constructor-tearoff self::A::•
+ #C4 = static-tearoff self::A::bar1
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_without_context.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_without_context.dart.strong.expect
index f6db3b2..5d000f0 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_without_context.dart.strong.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_without_context.dart.strong.expect
@@ -32,11 +32,11 @@
return new self::A::•();
}
static method testFoo() → dynamic
- return self::A::foo;
+ return #C1;
static method testNew() → dynamic
- return self::A::•;
+ return #C2;
static method testBar() → dynamic
- return self::A::bar;
+ return #C3;
static method testFooExtraArgs() → dynamic
return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_without_context.dart:15:23: Error: The static type of the explicit instantiation operand must be a generic function type but is 'A Function()'.
- 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_without_context.dart'.
@@ -56,3 +56,9 @@
testBarExtraArgs() => A<int>.bar; // Error.
^";
static method main() → dynamic {}
+
+constants {
+ #C1 = constructor-tearoff self::A::foo
+ #C2 = constructor-tearoff self::A::•
+ #C3 = static-tearoff self::A::bar
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_without_context.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_without_context.dart.strong.transformed.expect
index f6db3b2..5d000f0 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_without_context.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_without_context.dart.strong.transformed.expect
@@ -32,11 +32,11 @@
return new self::A::•();
}
static method testFoo() → dynamic
- return self::A::foo;
+ return #C1;
static method testNew() → dynamic
- return self::A::•;
+ return #C2;
static method testBar() → dynamic
- return self::A::bar;
+ return #C3;
static method testFooExtraArgs() → dynamic
return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_without_context.dart:15:23: Error: The static type of the explicit instantiation operand must be a generic function type but is 'A Function()'.
- 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_without_context.dart'.
@@ -56,3 +56,9 @@
testBarExtraArgs() => A<int>.bar; // Error.
^";
static method main() → dynamic {}
+
+constants {
+ #C1 = constructor-tearoff self::A::foo
+ #C2 = constructor-tearoff self::A::•
+ #C3 = static-tearoff self::A::bar
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_without_context.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_without_context.dart.weak.expect
index f6db3b2..5d000f0 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_without_context.dart.weak.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_without_context.dart.weak.expect
@@ -32,11 +32,11 @@
return new self::A::•();
}
static method testFoo() → dynamic
- return self::A::foo;
+ return #C1;
static method testNew() → dynamic
- return self::A::•;
+ return #C2;
static method testBar() → dynamic
- return self::A::bar;
+ return #C3;
static method testFooExtraArgs() → dynamic
return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_without_context.dart:15:23: Error: The static type of the explicit instantiation operand must be a generic function type but is 'A Function()'.
- 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_without_context.dart'.
@@ -56,3 +56,9 @@
testBarExtraArgs() => A<int>.bar; // Error.
^";
static method main() → dynamic {}
+
+constants {
+ #C1 = constructor-tearoff self::A::foo
+ #C2 = constructor-tearoff self::A::•
+ #C3 = static-tearoff self::A::bar
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_without_context.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_without_context.dart.weak.transformed.expect
index f6db3b2..5d000f0 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_without_context.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_without_context.dart.weak.transformed.expect
@@ -32,11 +32,11 @@
return new self::A::•();
}
static method testFoo() → dynamic
- return self::A::foo;
+ return #C1;
static method testNew() → dynamic
- return self::A::•;
+ return #C2;
static method testBar() → dynamic
- return self::A::bar;
+ return #C3;
static method testFooExtraArgs() → dynamic
return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_without_context.dart:15:23: Error: The static type of the explicit instantiation operand must be a generic function type but is 'A Function()'.
- 'A' is from 'pkg/front_end/testcases/constructor_tearoffs/nongeneric_tearoff_without_context.dart'.
@@ -56,3 +56,9 @@
testBarExtraArgs() => A<int>.bar; // Error.
^";
static method main() → dynamic {}
+
+constants {
+ #C1 = constructor-tearoff self::A::foo
+ #C2 = constructor-tearoff self::A::•
+ #C3 = static-tearoff self::A::bar
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.strong.expect
index 145140e..b589af6 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.strong.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.strong.expect
@@ -2,55 +2,20 @@
//
// Problems in library:
//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:6:5: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-// A.new();
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:7:38: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-// factory A.redirectingFactory() = A.new;
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:8:43: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-// factory A.redirectingFactoryChild() = B.new;
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:7:36: Error: Redirection constructor target not found: 'A.new'
-// factory A.redirectingFactory() = A.new;
-// ^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:15:23: Error: Getter not found: 'redirectingFactory'.
-// A Function() f1 = A.redirectingFactory;
-// ^^^^^^^^^^^^^^^^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:16:23: Error: Getter not found: 'redirectingFactoryChild'.
-// A Function() f2 = A.redirectingFactoryChild;
-// ^^^^^^^^^^^^^^^^^^^^^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:17:23: Error: Getter not found: 'redirectingTwice'.
-// A Function() f3 = A.redirectingTwice;
-// ^^^^^^^^^^^^^^^^
-//
// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:20:5: Error: Expected ';' after this.
// A x3 f3();
// ^^
//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:12:7: Error: The superclass, 'A', has no unnamed constructor that takes no arguments.
-// class B extends A {}
-// ^
-//
import self as self;
import "dart:core" as core;
class A extends core::Object {
static final field dynamic _redirecting# = <dynamic>[self::A::redirectingFactory, self::A::redirectingFactoryChild, self::A::redirectingTwice]/*isLegacy*/;
- constructor new() → self::A
+ constructor •() → self::A
: super core::Object::•()
;
static factory redirectingFactory() → self::A
- let dynamic #redirecting_factory = "A.new" in invalid-expression;
+ let dynamic #redirecting_factory = self::A::• in invalid-expression;
static factory redirectingFactoryChild() → self::A
let dynamic #redirecting_factory = self::B::• in invalid-expression;
static factory redirectingTwice() → self::A
@@ -58,19 +23,13 @@
}
class B extends self::A {
synthetic constructor •() → self::B
- : invalid-initializer
+ : super self::A::•()
;
}
static method test() → dynamic {
- () → self::A f1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:15:23: Error: Getter not found: 'redirectingFactory'.
- A Function() f1 = A.redirectingFactory;
- ^^^^^^^^^^^^^^^^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} () → self::A;
- () → self::A f2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:16:23: Error: Getter not found: 'redirectingFactoryChild'.
- A Function() f2 = A.redirectingFactoryChild;
- ^^^^^^^^^^^^^^^^^^^^^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} () → self::A;
- () → self::A f3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:17:23: Error: Getter not found: 'redirectingTwice'.
- A Function() f3 = A.redirectingTwice;
- ^^^^^^^^^^^^^^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} () → self::A;
+ () → self::A f1 = #C1;
+ () → self::A f2 = #C2;
+ () → self::A f3 = #C3;
self::A x1 = f1(){() → self::A};
self::B x2 = f2(){() → self::A} as{ForNonNullableByDefault} self::B;
self::A x3;
@@ -78,3 +37,9 @@
}
static method main() → dynamic
return self::test();
+
+constants {
+ #C1 = redirecting-factory-tearoff self::A::redirectingFactory
+ #C2 = redirecting-factory-tearoff self::A::redirectingFactoryChild
+ #C3 = redirecting-factory-tearoff self::A::redirectingTwice
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.strong.transformed.expect
index 943d69c..a3c5d1d 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.strong.transformed.expect
@@ -2,55 +2,20 @@
//
// Problems in library:
//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:6:5: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-// A.new();
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:7:38: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-// factory A.redirectingFactory() = A.new;
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:8:43: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-// factory A.redirectingFactoryChild() = B.new;
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:7:36: Error: Redirection constructor target not found: 'A.new'
-// factory A.redirectingFactory() = A.new;
-// ^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:15:23: Error: Getter not found: 'redirectingFactory'.
-// A Function() f1 = A.redirectingFactory;
-// ^^^^^^^^^^^^^^^^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:16:23: Error: Getter not found: 'redirectingFactoryChild'.
-// A Function() f2 = A.redirectingFactoryChild;
-// ^^^^^^^^^^^^^^^^^^^^^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:17:23: Error: Getter not found: 'redirectingTwice'.
-// A Function() f3 = A.redirectingTwice;
-// ^^^^^^^^^^^^^^^^
-//
// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:20:5: Error: Expected ';' after this.
// A x3 f3();
// ^^
//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:12:7: Error: The superclass, 'A', has no unnamed constructor that takes no arguments.
-// class B extends A {}
-// ^
-//
import self as self;
import "dart:core" as core;
class A extends core::Object {
static final field dynamic _redirecting# = <dynamic>[self::A::redirectingFactory, self::A::redirectingFactoryChild, self::A::redirectingTwice]/*isLegacy*/;
- constructor new() → self::A
+ constructor •() → self::A
: super core::Object::•()
;
static factory redirectingFactory() → self::A
- let core::String* #redirecting_factory = "A.new" in invalid-expression;
+ let Never #redirecting_factory = self::A::• in invalid-expression;
static factory redirectingFactoryChild() → self::A
let Never #redirecting_factory = self::B::• in invalid-expression;
static factory redirectingTwice() → self::A
@@ -58,19 +23,13 @@
}
class B extends self::A {
synthetic constructor •() → self::B
- : invalid-initializer
+ : super self::A::•()
;
}
static method test() → dynamic {
- () → self::A f1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:15:23: Error: Getter not found: 'redirectingFactory'.
- A Function() f1 = A.redirectingFactory;
- ^^^^^^^^^^^^^^^^^^";
- () → self::A f2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:16:23: Error: Getter not found: 'redirectingFactoryChild'.
- A Function() f2 = A.redirectingFactoryChild;
- ^^^^^^^^^^^^^^^^^^^^^^^";
- () → self::A f3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:17:23: Error: Getter not found: 'redirectingTwice'.
- A Function() f3 = A.redirectingTwice;
- ^^^^^^^^^^^^^^^^";
+ () → self::A f1 = #C1;
+ () → self::A f2 = #C2;
+ () → self::A f3 = #C3;
self::A x1 = f1(){() → self::A};
self::B x2 = f2(){() → self::A} as{ForNonNullableByDefault} self::B;
self::A x3;
@@ -78,3 +37,9 @@
}
static method main() → dynamic
return self::test();
+
+constants {
+ #C1 = redirecting-factory-tearoff self::A::redirectingFactory
+ #C2 = redirecting-factory-tearoff self::A::redirectingFactoryChild
+ #C3 = redirecting-factory-tearoff self::A::redirectingTwice
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.weak.expect
index 145140e..b589af6 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.weak.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.weak.expect
@@ -2,55 +2,20 @@
//
// Problems in library:
//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:6:5: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-// A.new();
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:7:38: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-// factory A.redirectingFactory() = A.new;
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:8:43: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-// factory A.redirectingFactoryChild() = B.new;
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:7:36: Error: Redirection constructor target not found: 'A.new'
-// factory A.redirectingFactory() = A.new;
-// ^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:15:23: Error: Getter not found: 'redirectingFactory'.
-// A Function() f1 = A.redirectingFactory;
-// ^^^^^^^^^^^^^^^^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:16:23: Error: Getter not found: 'redirectingFactoryChild'.
-// A Function() f2 = A.redirectingFactoryChild;
-// ^^^^^^^^^^^^^^^^^^^^^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:17:23: Error: Getter not found: 'redirectingTwice'.
-// A Function() f3 = A.redirectingTwice;
-// ^^^^^^^^^^^^^^^^
-//
// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:20:5: Error: Expected ';' after this.
// A x3 f3();
// ^^
//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:12:7: Error: The superclass, 'A', has no unnamed constructor that takes no arguments.
-// class B extends A {}
-// ^
-//
import self as self;
import "dart:core" as core;
class A extends core::Object {
static final field dynamic _redirecting# = <dynamic>[self::A::redirectingFactory, self::A::redirectingFactoryChild, self::A::redirectingTwice]/*isLegacy*/;
- constructor new() → self::A
+ constructor •() → self::A
: super core::Object::•()
;
static factory redirectingFactory() → self::A
- let dynamic #redirecting_factory = "A.new" in invalid-expression;
+ let dynamic #redirecting_factory = self::A::• in invalid-expression;
static factory redirectingFactoryChild() → self::A
let dynamic #redirecting_factory = self::B::• in invalid-expression;
static factory redirectingTwice() → self::A
@@ -58,19 +23,13 @@
}
class B extends self::A {
synthetic constructor •() → self::B
- : invalid-initializer
+ : super self::A::•()
;
}
static method test() → dynamic {
- () → self::A f1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:15:23: Error: Getter not found: 'redirectingFactory'.
- A Function() f1 = A.redirectingFactory;
- ^^^^^^^^^^^^^^^^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} () → self::A;
- () → self::A f2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:16:23: Error: Getter not found: 'redirectingFactoryChild'.
- A Function() f2 = A.redirectingFactoryChild;
- ^^^^^^^^^^^^^^^^^^^^^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} () → self::A;
- () → self::A f3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:17:23: Error: Getter not found: 'redirectingTwice'.
- A Function() f3 = A.redirectingTwice;
- ^^^^^^^^^^^^^^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} () → self::A;
+ () → self::A f1 = #C1;
+ () → self::A f2 = #C2;
+ () → self::A f3 = #C3;
self::A x1 = f1(){() → self::A};
self::B x2 = f2(){() → self::A} as{ForNonNullableByDefault} self::B;
self::A x3;
@@ -78,3 +37,9 @@
}
static method main() → dynamic
return self::test();
+
+constants {
+ #C1 = redirecting-factory-tearoff self::A::redirectingFactory
+ #C2 = redirecting-factory-tearoff self::A::redirectingFactoryChild
+ #C3 = redirecting-factory-tearoff self::A::redirectingTwice
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.weak.outline.expect
index b9415d3..e80d672 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.weak.outline.expect
@@ -1,35 +1,13 @@
library /*isNonNullableByDefault*/;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:6:5: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-// A.new();
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:7:38: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-// factory A.redirectingFactory() = A.new;
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:8:43: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-// factory A.redirectingFactoryChild() = B.new;
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:7:36: Error: Redirection constructor target not found: 'A.new'
-// factory A.redirectingFactory() = A.new;
-// ^
-//
import self as self;
import "dart:core" as core;
class A extends core::Object {
static final field dynamic _redirecting# = <dynamic>[self::A::redirectingFactory, self::A::redirectingFactoryChild, self::A::redirectingTwice]/*isLegacy*/;
- constructor new() → self::A
+ constructor •() → self::A
;
static factory redirectingFactory() → self::A
- let dynamic #redirecting_factory = "A.new" in invalid-expression;
+ let dynamic #redirecting_factory = self::A::• in invalid-expression;
static factory redirectingFactoryChild() → self::A
let dynamic #redirecting_factory = self::B::• in invalid-expression;
static factory redirectingTwice() → self::A
diff --git a/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.weak.transformed.expect
index 943d69c..a3c5d1d 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart.weak.transformed.expect
@@ -2,55 +2,20 @@
//
// Problems in library:
//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:6:5: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-// A.new();
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:7:38: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-// factory A.redirectingFactory() = A.new;
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:8:43: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-// factory A.redirectingFactoryChild() = B.new;
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:7:36: Error: Redirection constructor target not found: 'A.new'
-// factory A.redirectingFactory() = A.new;
-// ^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:15:23: Error: Getter not found: 'redirectingFactory'.
-// A Function() f1 = A.redirectingFactory;
-// ^^^^^^^^^^^^^^^^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:16:23: Error: Getter not found: 'redirectingFactoryChild'.
-// A Function() f2 = A.redirectingFactoryChild;
-// ^^^^^^^^^^^^^^^^^^^^^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:17:23: Error: Getter not found: 'redirectingTwice'.
-// A Function() f3 = A.redirectingTwice;
-// ^^^^^^^^^^^^^^^^
-//
// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:20:5: Error: Expected ';' after this.
// A x3 f3();
// ^^
//
-// pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:12:7: Error: The superclass, 'A', has no unnamed constructor that takes no arguments.
-// class B extends A {}
-// ^
-//
import self as self;
import "dart:core" as core;
class A extends core::Object {
static final field dynamic _redirecting# = <dynamic>[self::A::redirectingFactory, self::A::redirectingFactoryChild, self::A::redirectingTwice]/*isLegacy*/;
- constructor new() → self::A
+ constructor •() → self::A
: super core::Object::•()
;
static factory redirectingFactory() → self::A
- let core::String* #redirecting_factory = "A.new" in invalid-expression;
+ let Never #redirecting_factory = self::A::• in invalid-expression;
static factory redirectingFactoryChild() → self::A
let Never #redirecting_factory = self::B::• in invalid-expression;
static factory redirectingTwice() → self::A
@@ -58,19 +23,13 @@
}
class B extends self::A {
synthetic constructor •() → self::B
- : invalid-initializer
+ : super self::A::•()
;
}
static method test() → dynamic {
- () → self::A f1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:15:23: Error: Getter not found: 'redirectingFactory'.
- A Function() f1 = A.redirectingFactory;
- ^^^^^^^^^^^^^^^^^^";
- () → self::A f2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:16:23: Error: Getter not found: 'redirectingFactoryChild'.
- A Function() f2 = A.redirectingFactoryChild;
- ^^^^^^^^^^^^^^^^^^^^^^^";
- () → self::A f3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_constructors.dart:17:23: Error: Getter not found: 'redirectingTwice'.
- A Function() f3 = A.redirectingTwice;
- ^^^^^^^^^^^^^^^^";
+ () → self::A f1 = #C1;
+ () → self::A f2 = #C2;
+ () → self::A f3 = #C3;
self::A x1 = f1(){() → self::A};
self::B x2 = f2(){() → self::A} as{ForNonNullableByDefault} self::B;
self::A x3;
@@ -78,3 +37,9 @@
}
static method main() → dynamic
return self::test();
+
+constants {
+ #C1 = redirecting-factory-tearoff self::A::redirectingFactory
+ #C2 = redirecting-factory-tearoff self::A::redirectingFactoryChild
+ #C3 = redirecting-factory-tearoff self::A::redirectingTwice
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart b/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart
new file mode 100644
index 0000000..4ac8aea
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart
@@ -0,0 +1,194 @@
+// 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.
+
+final bool inSoundMode = <int?>[] is! List<int>;
+
+main() {
+ print('inSoundMode: $inSoundMode');
+ testNoArgs();
+ testArgs();
+}
+
+class Class1 {
+ Class1._();
+ factory Class1() = Class1._;
+}
+
+class Class2 {
+ Class2.__();
+ factory Class2._() => Class2.__();
+ factory Class2.named() = Class2._;
+}
+
+testNoArgs() {
+ var f1a = Class1.new;
+ var c1a = f1a();
+ expect(true, c1a is Class1);
+
+ dynamic f1b = Class1.new;
+ var c1b = f1b();
+ expect(true, c1b is Class1);
+
+ expect(true, identical(f1a, f1b));
+
+ var f2a = Class2.named;
+ var c2a = f2a();
+ expect(true, c2a is Class2);
+
+ dynamic f2b = Class2.named;
+ var c2b = f2b();
+ expect(true, c2b is Class2);
+
+ expect(true, identical(f2a, f2b));
+}
+
+class Class3 {
+ final int field;
+
+ Class3._(this.field);
+ factory Class3(int field) = Class3._;
+}
+
+class Class4 {
+ final int? field;
+
+ Class4._([this.field]);
+ factory Class4([int? field]) = Class4._;
+}
+
+class Class5 {
+ final int field1;
+ final int? field2;
+
+ Class5._(this.field1, [this.field2]);
+ factory Class5(int field1, [int? field2]) = Class5._;
+}
+
+class Class6 {
+ final int field1;
+ final int? field2;
+ final int field3;
+
+ Class6._(this.field1, {this.field2, required this.field3});
+ factory Class6(int field1, {int? field2, required int field3}) =
+ Class6._;
+}
+
+class Class7a implements Class7b {
+ Class7a();
+}
+
+class Class7b {
+ factory Class7b() = Class7a;
+}
+
+class Class8a<T> implements Class8b<T> {
+ Class8a();
+}
+
+class Class8b<T> {
+ factory Class8b() = Class8a<T>;
+}
+
+testArgs() {
+ var f3a = Class3.new;
+ var c3a = f3a(42);
+ expect(42, c3a.field);
+ () {
+ f3a(); // error
+ f3a(42, 87); // error
+ };
+
+ dynamic f3b = Class3.new;
+ var c3b = f3b(87);
+ expect(87, c3b.field);
+ throws(() => f3b());
+ throws(() => f3b(42, 87));
+
+ var f4a = Class4.new;
+ var c4a = f4a();
+ expect(null, c4a.field);
+ var c4b = f4a(42);
+ expect(42, c4b.field);
+ () {
+ f4a(42, 87); // error
+ };
+ dynamic f4b = Class4.new;
+ throws(() => f4b(42, 87));
+
+
+ var f5a = Class5.new;
+ var c5a = f5a(42);
+ expect(42, c5a.field1);
+ expect(null, c5a.field2);
+ var c5b = f5a(87, 42);
+ expect(87, c5b.field1);
+ expect(42, c5b.field2);
+ () {
+ f5a(); // error
+ f5a(42, 87, 123); // error
+ };
+ dynamic f5b = Class5.new;
+ throws(() => f5b());
+ throws(() => f5b(42, 87, 123));
+
+ var f6a = Class6.new;
+ var c6a = f6a(42, field3: 87);
+ expect(42, c6a.field1);
+ expect(null, c6a.field2);
+ expect(87, c6a.field3);
+ () {
+ f6a(); // error
+ f6a(42); // error
+ f6a(42, 87); // error
+ f6a(field1: 87, field2: 87); // error
+ };
+
+ var c6b = f6a(42, field2: 123, field3: 87);
+ expect(42, c6b.field1);
+ expect(123, c6b.field2);
+ expect(87, c6b.field3);
+
+ var c6c = f6a(87, field3: 42, field2: 123);
+ expect(87, c6c.field1);
+ expect(123, c6c.field2);
+ expect(42, c6c.field3);
+
+ dynamic f6b = Class6.new;
+ throws(() => f6b());
+ throws(() => f6b(42), inSoundModeOnly: true);
+ throws(() => f6b(42, 87), inSoundModeOnly: true);
+ throws(() => f6b(field1: 87, field2: 87));
+
+ var f7a = Class7b.new;
+ var c7a = f7a();
+ expect(true, c7a is Class7a);
+ expect(true, c7a is Class7b);
+
+ var f8a = Class8b.new;
+ var c8a = f8a();
+ expect(true, c8a is Class8a);
+ expect(true, c8a is Class8b);
+ var c8b = f8a<int>();
+ expect(true, c8b is Class8a<int>);
+ expect(true, c8b is Class8b<int>);
+ expect(false, c8b is Class8b<String>);
+}
+
+expect(expected, actual) {
+ if (expected != actual) throw 'Expected $expected, actual $actual';
+}
+
+throws(Function() f, {bool inSoundModeOnly: false}) {
+ try {
+ f();
+ } catch (e) {
+ print('Thrown: $e');
+ return;
+ }
+ if (!inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw 'Expected exception';
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.strong.expect
new file mode 100644
index 0000000..ce07a22
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.strong.expect
@@ -0,0 +1,272 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:99:8: Error: Too few positional arguments: 1 required, 0 given.
+// f3a(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:100:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f3a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:115:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f4a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:129:8: Error: Too few positional arguments: 1 required, 0 given.
+// f5a(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:130:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+// Try removing the extra positional arguments.
+// f5a(42, 87, 123); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:142:8: Error: Too few positional arguments: 1 required, 0 given.
+// f6a(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:143:8: Error: Required named parameter 'field3' must be provided.
+// f6a(42); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:144:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f6a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:145:8: Error: Too few positional arguments: 1 required, 0 given.
+// f6a(field1: 87, field2: 87); // error
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class1::•]/*isLegacy*/;
+ constructor _() → self::Class1
+ : super core::Object::•()
+ ;
+ static factory •() → self::Class1
+ let dynamic #redirecting_factory = self::Class1::_ in invalid-expression;
+}
+class Class2 extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class2::named]/*isLegacy*/;
+ constructor __() → self::Class2
+ : super core::Object::•()
+ ;
+ static factory _() → self::Class2
+ return new self::Class2::__();
+ static factory named() → self::Class2
+ let dynamic #redirecting_factory = self::Class2::_ in invalid-expression;
+}
+class Class3 extends core::Object {
+ final field core::int field;
+ static final field dynamic _redirecting# = <dynamic>[self::Class3::•]/*isLegacy*/;
+ constructor _(core::int field) → self::Class3
+ : self::Class3::field = field, super core::Object::•()
+ ;
+ static factory •(core::int field) → self::Class3
+ let dynamic #redirecting_factory = self::Class3::_ in invalid-expression;
+}
+class Class4 extends core::Object {
+ final field core::int? field;
+ static final field dynamic _redirecting# = <dynamic>[self::Class4::•]/*isLegacy*/;
+ constructor _([core::int? field = #C1]) → self::Class4
+ : self::Class4::field = field, super core::Object::•()
+ ;
+ static factory •([core::int? field = #C1]) → self::Class4
+ let dynamic #redirecting_factory = self::Class4::_ in invalid-expression;
+}
+class Class5 extends core::Object {
+ final field core::int field1;
+ final field core::int? field2;
+ static final field dynamic _redirecting# = <dynamic>[self::Class5::•]/*isLegacy*/;
+ constructor _(core::int field1, [core::int? field2 = #C1]) → self::Class5
+ : self::Class5::field1 = field1, self::Class5::field2 = field2, super core::Object::•()
+ ;
+ static factory •(core::int field1, [core::int? field2 = #C1]) → self::Class5
+ let dynamic #redirecting_factory = self::Class5::_ in invalid-expression;
+}
+class Class6 extends core::Object {
+ final field core::int field1;
+ final field core::int? field2;
+ final field core::int field3;
+ static final field dynamic _redirecting# = <dynamic>[self::Class6::•]/*isLegacy*/;
+ constructor _(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+ : self::Class6::field1 = field1, self::Class6::field2 = field2, self::Class6::field3 = field3, super core::Object::•()
+ ;
+ static factory •(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+ let dynamic #redirecting_factory = self::Class6::_ in invalid-expression;
+}
+class Class7a extends core::Object implements self::Class7b {
+ constructor •() → self::Class7a
+ : super core::Object::•()
+ ;
+}
+class Class7b extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class7b::•]/*isLegacy*/;
+ static factory •() → self::Class7b
+ let dynamic #redirecting_factory = self::Class7a::• in invalid-expression;
+}
+class Class8a<T extends core::Object? = dynamic> extends core::Object implements self::Class8b<self::Class8a::T%> {
+ constructor •() → self::Class8a<self::Class8a::T%>
+ : super core::Object::•()
+ ;
+}
+class Class8b<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class8b::•]/*isLegacy*/;
+ static factory •<T extends core::Object? = dynamic>() → self::Class8b<self::Class8b::•::T%>
+ let dynamic #redirecting_factory = self::Class8a::• in let self::Class8b::•::T% #typeArg0 = null in invalid-expression;
+}
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+ core::print("inSoundMode: ${self::inSoundMode}");
+ self::testNoArgs();
+ self::testArgs();
+}
+static method testNoArgs() → dynamic {
+ () → self::Class1 f1a = #C2;
+ self::Class1 c1a = f1a(){() → self::Class1};
+ self::expect(true, c1a is{ForNonNullableByDefault} self::Class1);
+ dynamic f1b = #C2;
+ dynamic c1b = f1b{dynamic}.call();
+ self::expect(true, c1b is{ForNonNullableByDefault} self::Class1);
+ self::expect(true, core::identical(f1a, f1b));
+ () → self::Class2 f2a = #C3;
+ self::Class2 c2a = f2a(){() → self::Class2};
+ self::expect(true, c2a is{ForNonNullableByDefault} self::Class2);
+ dynamic f2b = #C3;
+ dynamic c2b = f2b{dynamic}.call();
+ self::expect(true, c2b is{ForNonNullableByDefault} self::Class2);
+ self::expect(true, core::identical(f2a, f2b));
+}
+static method testArgs() → dynamic {
+ (core::int) → self::Class3 f3a = #C4;
+ self::Class3 c3a = f3a(42){(core::int) → self::Class3};
+ self::expect(42, c3a.{self::Class3::field}{core::int});
+ () → Null {
+ let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:99:8: Error: Too few positional arguments: 1 required, 0 given.
+ f3a(); // error
+ ^" in f3a{<inapplicable>}.();
+ let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:100:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f3a(42, 87); // error
+ ^" in f3a{<inapplicable>}.(42, 87);
+ };
+ dynamic f3b = #C4;
+ dynamic c3b = f3b{dynamic}.call(87);
+ self::expect(87, c3b{dynamic}.field);
+ self::throws(() → dynamic => f3b{dynamic}.call());
+ self::throws(() → dynamic => f3b{dynamic}.call(42, 87));
+ ([core::int?]) → self::Class4 f4a = #C5;
+ self::Class4 c4a = f4a(){([core::int?]) → self::Class4};
+ self::expect(null, c4a.{self::Class4::field}{core::int?});
+ self::Class4 c4b = f4a(42){([core::int?]) → self::Class4};
+ self::expect(42, c4b.{self::Class4::field}{core::int?});
+ () → Null {
+ let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:115:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f4a(42, 87); // error
+ ^" in f4a{<inapplicable>}.(42, 87);
+ };
+ dynamic f4b = #C5;
+ self::throws(() → dynamic => f4b{dynamic}.call(42, 87));
+ (core::int, [core::int?]) → self::Class5 f5a = #C6;
+ self::Class5 c5a = f5a(42){(core::int, [core::int?]) → self::Class5};
+ self::expect(42, c5a.{self::Class5::field1}{core::int});
+ self::expect(null, c5a.{self::Class5::field2}{core::int?});
+ self::Class5 c5b = f5a(87, 42){(core::int, [core::int?]) → self::Class5};
+ self::expect(87, c5b.{self::Class5::field1}{core::int});
+ self::expect(42, c5b.{self::Class5::field2}{core::int?});
+ () → Null {
+ let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:129:8: Error: Too few positional arguments: 1 required, 0 given.
+ f5a(); // error
+ ^" in f5a{<inapplicable>}.();
+ let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:130:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+Try removing the extra positional arguments.
+ f5a(42, 87, 123); // error
+ ^" in f5a{<inapplicable>}.(42, 87, 123);
+ };
+ dynamic f5b = #C6;
+ self::throws(() → dynamic => f5b{dynamic}.call());
+ self::throws(() → dynamic => f5b{dynamic}.call(42, 87, 123));
+ (core::int, {field2: core::int?, required field3: core::int}) → self::Class6 f6a = #C7;
+ self::Class6 c6a = f6a(42, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+ self::expect(42, c6a.{self::Class6::field1}{core::int});
+ self::expect(null, c6a.{self::Class6::field2}{core::int?});
+ self::expect(87, c6a.{self::Class6::field3}{core::int});
+ () → Null {
+ let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:142:8: Error: Too few positional arguments: 1 required, 0 given.
+ f6a(); // error
+ ^" in f6a{<inapplicable>}.();
+ let final Never #t7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:143:8: Error: Required named parameter 'field3' must be provided.
+ f6a(42); // error
+ ^" in f6a{<inapplicable>}.(42);
+ let final Never #t8 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:144:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f6a(42, 87); // error
+ ^" in f6a{<inapplicable>}.(42, 87);
+ let final Never #t9 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:145:8: Error: Too few positional arguments: 1 required, 0 given.
+ f6a(field1: 87, field2: 87); // error
+ ^" in f6a{<inapplicable>}.(field1: 87, field2: 87);
+ };
+ self::Class6 c6b = f6a(42, field2: 123, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+ self::expect(42, c6b.{self::Class6::field1}{core::int});
+ self::expect(123, c6b.{self::Class6::field2}{core::int?});
+ self::expect(87, c6b.{self::Class6::field3}{core::int});
+ self::Class6 c6c = f6a(87, field3: 42, field2: 123){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+ self::expect(87, c6c.{self::Class6::field1}{core::int});
+ self::expect(123, c6c.{self::Class6::field2}{core::int?});
+ self::expect(42, c6c.{self::Class6::field3}{core::int});
+ dynamic f6b = #C7;
+ self::throws(() → dynamic => f6b{dynamic}.call());
+ self::throws(() → dynamic => f6b{dynamic}.call(42), inSoundModeOnly: true);
+ self::throws(() → dynamic => f6b{dynamic}.call(42, 87), inSoundModeOnly: true);
+ self::throws(() → dynamic => f6b{dynamic}.call(field1: 87, field2: 87));
+ () → self::Class7b f7a = #C8;
+ self::Class7b c7a = f7a(){() → self::Class7b};
+ self::expect(true, c7a is{ForNonNullableByDefault} self::Class7a);
+ self::expect(true, c7a is{ForNonNullableByDefault} self::Class7b);
+ <T extends core::Object? = dynamic>() → self::Class8b<T%> f8a = #C9;
+ self::Class8b<dynamic> c8a = f8a<dynamic>(){() → self::Class8b<dynamic>};
+ self::expect(true, c8a is{ForNonNullableByDefault} self::Class8a<dynamic>);
+ self::expect(true, c8a is{ForNonNullableByDefault} self::Class8b<dynamic>);
+ self::Class8b<core::int> c8b = f8a<core::int>(){() → self::Class8b<core::int>};
+ self::expect(true, c8b is{ForNonNullableByDefault} self::Class8a<core::int>);
+ self::expect(true, c8b is{ForNonNullableByDefault} self::Class8b<core::int>);
+ self::expect(false, c8b is{ForNonNullableByDefault} self::Class8b<core::String>);
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C10}) → dynamic {
+ try {
+ f(){() → dynamic};
+ }
+ on core::Object catch(final core::Object e) {
+ core::print("Thrown: ${e}");
+ return;
+ }
+ if(!self::inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw "Expected exception";
+}
+
+constants {
+ #C1 = null
+ #C2 = redirecting-factory-tearoff self::Class1::•
+ #C3 = redirecting-factory-tearoff self::Class2::named
+ #C4 = redirecting-factory-tearoff self::Class3::•
+ #C5 = redirecting-factory-tearoff self::Class4::•
+ #C6 = redirecting-factory-tearoff self::Class5::•
+ #C7 = redirecting-factory-tearoff self::Class6::•
+ #C8 = redirecting-factory-tearoff self::Class7b::•
+ #C9 = redirecting-factory-tearoff self::Class8b::•
+ #C10 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.strong.transformed.expect
new file mode 100644
index 0000000..872ae36
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.strong.transformed.expect
@@ -0,0 +1,272 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:99:8: Error: Too few positional arguments: 1 required, 0 given.
+// f3a(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:100:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f3a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:115:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f4a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:129:8: Error: Too few positional arguments: 1 required, 0 given.
+// f5a(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:130:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+// Try removing the extra positional arguments.
+// f5a(42, 87, 123); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:142:8: Error: Too few positional arguments: 1 required, 0 given.
+// f6a(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:143:8: Error: Required named parameter 'field3' must be provided.
+// f6a(42); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:144:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f6a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:145:8: Error: Too few positional arguments: 1 required, 0 given.
+// f6a(field1: 87, field2: 87); // error
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class1::•]/*isLegacy*/;
+ constructor _() → self::Class1
+ : super core::Object::•()
+ ;
+ static factory •() → self::Class1
+ let Never #redirecting_factory = self::Class1::_ in invalid-expression;
+}
+class Class2 extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class2::named]/*isLegacy*/;
+ constructor __() → self::Class2
+ : super core::Object::•()
+ ;
+ static factory _() → self::Class2
+ return new self::Class2::__();
+ static factory named() → self::Class2
+ let () → self::Class2 #redirecting_factory = self::Class2::_ in invalid-expression;
+}
+class Class3 extends core::Object {
+ final field core::int field;
+ static final field dynamic _redirecting# = <dynamic>[self::Class3::•]/*isLegacy*/;
+ constructor _(core::int field) → self::Class3
+ : self::Class3::field = field, super core::Object::•()
+ ;
+ static factory •(core::int field) → self::Class3
+ let Never #redirecting_factory = self::Class3::_ in invalid-expression;
+}
+class Class4 extends core::Object {
+ final field core::int? field;
+ static final field dynamic _redirecting# = <dynamic>[self::Class4::•]/*isLegacy*/;
+ constructor _([core::int? field = #C1]) → self::Class4
+ : self::Class4::field = field, super core::Object::•()
+ ;
+ static factory •([core::int? field = #C1]) → self::Class4
+ let Never #redirecting_factory = self::Class4::_ in invalid-expression;
+}
+class Class5 extends core::Object {
+ final field core::int field1;
+ final field core::int? field2;
+ static final field dynamic _redirecting# = <dynamic>[self::Class5::•]/*isLegacy*/;
+ constructor _(core::int field1, [core::int? field2 = #C1]) → self::Class5
+ : self::Class5::field1 = field1, self::Class5::field2 = field2, super core::Object::•()
+ ;
+ static factory •(core::int field1, [core::int? field2 = #C1]) → self::Class5
+ let Never #redirecting_factory = self::Class5::_ in invalid-expression;
+}
+class Class6 extends core::Object {
+ final field core::int field1;
+ final field core::int? field2;
+ final field core::int field3;
+ static final field dynamic _redirecting# = <dynamic>[self::Class6::•]/*isLegacy*/;
+ constructor _(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+ : self::Class6::field1 = field1, self::Class6::field2 = field2, self::Class6::field3 = field3, super core::Object::•()
+ ;
+ static factory •(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+ let Never #redirecting_factory = self::Class6::_ in invalid-expression;
+}
+class Class7a extends core::Object implements self::Class7b {
+ constructor •() → self::Class7a
+ : super core::Object::•()
+ ;
+}
+class Class7b extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class7b::•]/*isLegacy*/;
+ static factory •() → self::Class7b
+ let Never #redirecting_factory = self::Class7a::• in invalid-expression;
+}
+class Class8a<T extends core::Object? = dynamic> extends core::Object implements self::Class8b<self::Class8a::T%> {
+ constructor •() → self::Class8a<self::Class8a::T%>
+ : super core::Object::•()
+ ;
+}
+class Class8b<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class8b::•]/*isLegacy*/;
+ static factory •<T extends core::Object? = dynamic>() → self::Class8b<self::Class8b::•::T%>
+ let Never #redirecting_factory = self::Class8a::• in let self::Class8b::•::T% #typeArg0 = null in invalid-expression;
+}
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+ core::print("inSoundMode: ${self::inSoundMode}");
+ self::testNoArgs();
+ self::testArgs();
+}
+static method testNoArgs() → dynamic {
+ () → self::Class1 f1a = #C2;
+ self::Class1 c1a = f1a(){() → self::Class1};
+ self::expect(true, c1a is{ForNonNullableByDefault} self::Class1);
+ dynamic f1b = #C2;
+ dynamic c1b = f1b{dynamic}.call();
+ self::expect(true, c1b is{ForNonNullableByDefault} self::Class1);
+ self::expect(true, core::identical(f1a, f1b));
+ () → self::Class2 f2a = #C3;
+ self::Class2 c2a = f2a(){() → self::Class2};
+ self::expect(true, c2a is{ForNonNullableByDefault} self::Class2);
+ dynamic f2b = #C3;
+ dynamic c2b = f2b{dynamic}.call();
+ self::expect(true, c2b is{ForNonNullableByDefault} self::Class2);
+ self::expect(true, core::identical(f2a, f2b));
+}
+static method testArgs() → dynamic {
+ (core::int) → self::Class3 f3a = #C4;
+ self::Class3 c3a = f3a(42){(core::int) → self::Class3};
+ self::expect(42, c3a.{self::Class3::field}{core::int});
+ () → Null {
+ let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:99:8: Error: Too few positional arguments: 1 required, 0 given.
+ f3a(); // error
+ ^" in f3a{<inapplicable>}.();
+ let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:100:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f3a(42, 87); // error
+ ^" in f3a{<inapplicable>}.(42, 87);
+ };
+ dynamic f3b = #C4;
+ dynamic c3b = f3b{dynamic}.call(87);
+ self::expect(87, c3b{dynamic}.field);
+ self::throws(() → dynamic => f3b{dynamic}.call());
+ self::throws(() → dynamic => f3b{dynamic}.call(42, 87));
+ ([core::int?]) → self::Class4 f4a = #C5;
+ self::Class4 c4a = f4a(){([core::int?]) → self::Class4};
+ self::expect(null, c4a.{self::Class4::field}{core::int?});
+ self::Class4 c4b = f4a(42){([core::int?]) → self::Class4};
+ self::expect(42, c4b.{self::Class4::field}{core::int?});
+ () → Null {
+ let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:115:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f4a(42, 87); // error
+ ^" in f4a{<inapplicable>}.(42, 87);
+ };
+ dynamic f4b = #C5;
+ self::throws(() → dynamic => f4b{dynamic}.call(42, 87));
+ (core::int, [core::int?]) → self::Class5 f5a = #C6;
+ self::Class5 c5a = f5a(42){(core::int, [core::int?]) → self::Class5};
+ self::expect(42, c5a.{self::Class5::field1}{core::int});
+ self::expect(null, c5a.{self::Class5::field2}{core::int?});
+ self::Class5 c5b = f5a(87, 42){(core::int, [core::int?]) → self::Class5};
+ self::expect(87, c5b.{self::Class5::field1}{core::int});
+ self::expect(42, c5b.{self::Class5::field2}{core::int?});
+ () → Null {
+ let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:129:8: Error: Too few positional arguments: 1 required, 0 given.
+ f5a(); // error
+ ^" in f5a{<inapplicable>}.();
+ let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:130:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+Try removing the extra positional arguments.
+ f5a(42, 87, 123); // error
+ ^" in f5a{<inapplicable>}.(42, 87, 123);
+ };
+ dynamic f5b = #C6;
+ self::throws(() → dynamic => f5b{dynamic}.call());
+ self::throws(() → dynamic => f5b{dynamic}.call(42, 87, 123));
+ (core::int, {field2: core::int?, required field3: core::int}) → self::Class6 f6a = #C7;
+ self::Class6 c6a = f6a(42, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+ self::expect(42, c6a.{self::Class6::field1}{core::int});
+ self::expect(null, c6a.{self::Class6::field2}{core::int?});
+ self::expect(87, c6a.{self::Class6::field3}{core::int});
+ () → Null {
+ let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:142:8: Error: Too few positional arguments: 1 required, 0 given.
+ f6a(); // error
+ ^" in f6a{<inapplicable>}.();
+ let final Never #t7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:143:8: Error: Required named parameter 'field3' must be provided.
+ f6a(42); // error
+ ^" in f6a{<inapplicable>}.(42);
+ let final Never #t8 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:144:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f6a(42, 87); // error
+ ^" in f6a{<inapplicable>}.(42, 87);
+ let final Never #t9 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:145:8: Error: Too few positional arguments: 1 required, 0 given.
+ f6a(field1: 87, field2: 87); // error
+ ^" in f6a{<inapplicable>}.(field1: 87, field2: 87);
+ };
+ self::Class6 c6b = f6a(42, field2: 123, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+ self::expect(42, c6b.{self::Class6::field1}{core::int});
+ self::expect(123, c6b.{self::Class6::field2}{core::int?});
+ self::expect(87, c6b.{self::Class6::field3}{core::int});
+ self::Class6 c6c = f6a(87, field3: 42, field2: 123){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+ self::expect(87, c6c.{self::Class6::field1}{core::int});
+ self::expect(123, c6c.{self::Class6::field2}{core::int?});
+ self::expect(42, c6c.{self::Class6::field3}{core::int});
+ dynamic f6b = #C7;
+ self::throws(() → dynamic => f6b{dynamic}.call());
+ self::throws(() → dynamic => f6b{dynamic}.call(42), inSoundModeOnly: true);
+ self::throws(() → dynamic => f6b{dynamic}.call(42, 87), inSoundModeOnly: true);
+ self::throws(() → dynamic => f6b{dynamic}.call(field1: 87, field2: 87));
+ () → self::Class7b f7a = #C8;
+ self::Class7b c7a = f7a(){() → self::Class7b};
+ self::expect(true, c7a is{ForNonNullableByDefault} self::Class7a);
+ self::expect(true, c7a is{ForNonNullableByDefault} self::Class7b);
+ <T extends core::Object? = dynamic>() → self::Class8b<T%> f8a = #C9;
+ self::Class8b<dynamic> c8a = f8a<dynamic>(){() → self::Class8b<dynamic>};
+ self::expect(true, c8a is{ForNonNullableByDefault} self::Class8a<dynamic>);
+ self::expect(true, c8a is{ForNonNullableByDefault} self::Class8b<dynamic>);
+ self::Class8b<core::int> c8b = f8a<core::int>(){() → self::Class8b<core::int>};
+ self::expect(true, c8b is{ForNonNullableByDefault} self::Class8a<core::int>);
+ self::expect(true, c8b is{ForNonNullableByDefault} self::Class8b<core::int>);
+ self::expect(false, c8b is{ForNonNullableByDefault} self::Class8b<core::String>);
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C10}) → dynamic {
+ try {
+ f(){() → dynamic};
+ }
+ on core::Object catch(final core::Object e) {
+ core::print("Thrown: ${e}");
+ return;
+ }
+ if(!self::inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw "Expected exception";
+}
+
+constants {
+ #C1 = null
+ #C2 = redirecting-factory-tearoff self::Class1::•
+ #C3 = redirecting-factory-tearoff self::Class2::named
+ #C4 = redirecting-factory-tearoff self::Class3::•
+ #C5 = redirecting-factory-tearoff self::Class4::•
+ #C6 = redirecting-factory-tearoff self::Class5::•
+ #C7 = redirecting-factory-tearoff self::Class6::•
+ #C8 = redirecting-factory-tearoff self::Class7b::•
+ #C9 = redirecting-factory-tearoff self::Class8b::•
+ #C10 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.textual_outline.expect
new file mode 100644
index 0000000..2fa25d6
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.textual_outline.expect
@@ -0,0 +1,62 @@
+final bool inSoundMode = <int?>[] is! List<int>;
+main() {}
+
+class Class1 {
+ Class1._();
+ factory Class1() = Class1._;
+}
+
+class Class2 {
+ Class2.__();
+ factory Class2._() => Class2.__();
+ factory Class2.named() = Class2._;
+}
+
+testNoArgs() {}
+
+class Class3 {
+ final int field;
+ Class3._(this.field);
+ factory Class3(int field) = Class3._;
+}
+
+class Class4 {
+ final int? field;
+ Class4._([this.field]);
+ factory Class4([int? field]) = Class4._;
+}
+
+class Class5 {
+ final int field1;
+ final int? field2;
+ Class5._(this.field1, [this.field2]);
+ factory Class5(int field1, [int? field2]) = Class5._;
+}
+
+class Class6 {
+ final int field1;
+ final int? field2;
+ final int field3;
+ Class6._(this.field1, {this.field2, required this.field3});
+ factory Class6(int field1, {int? field2, required int field3}) = Class6._;
+}
+
+class Class7a implements Class7b {
+ Class7a();
+}
+
+class Class7b {
+ factory Class7b() = Class7a;
+}
+
+class Class8a<T> implements Class8b<T> {
+ Class8a();
+}
+
+class Class8b<T> {
+ factory Class8b() = Class8a<T>;
+}
+
+testArgs() {}
+expect(expected, actual) {}
+throws(Function() f, {bool inSoundModeOnly: false}) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..0500e74
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.textual_outline_modelled.expect
@@ -0,0 +1,60 @@
+class Class1 {
+ Class1._();
+ factory Class1() = Class1._;
+}
+
+class Class2 {
+ Class2.__();
+ factory Class2._() => Class2.__();
+ factory Class2.named() = Class2._;
+}
+
+class Class3 {
+ Class3._(this.field);
+ factory Class3(int field) = Class3._;
+ final int field;
+}
+
+class Class4 {
+ Class4._([this.field]);
+ factory Class4([int? field]) = Class4._;
+ final int? field;
+}
+
+class Class5 {
+ Class5._(this.field1, [this.field2]);
+ factory Class5(int field1, [int? field2]) = Class5._;
+ final int? field2;
+ final int field1;
+}
+
+class Class6 {
+ Class6._(this.field1, {this.field2, required this.field3});
+ factory Class6(int field1, {int? field2, required int field3}) = Class6._;
+ final int? field2;
+ final int field1;
+ final int field3;
+}
+
+class Class7a implements Class7b {
+ Class7a();
+}
+
+class Class7b {
+ factory Class7b() = Class7a;
+}
+
+class Class8a<T> implements Class8b<T> {
+ Class8a();
+}
+
+class Class8b<T> {
+ factory Class8b() = Class8a<T>;
+}
+
+expect(expected, actual) {}
+final bool inSoundMode = <int?>[] is! List<int>;
+main() {}
+testArgs() {}
+testNoArgs() {}
+throws(Function() f, {bool inSoundModeOnly: false}) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.weak.expect
new file mode 100644
index 0000000..ce07a22
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.weak.expect
@@ -0,0 +1,272 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:99:8: Error: Too few positional arguments: 1 required, 0 given.
+// f3a(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:100:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f3a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:115:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f4a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:129:8: Error: Too few positional arguments: 1 required, 0 given.
+// f5a(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:130:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+// Try removing the extra positional arguments.
+// f5a(42, 87, 123); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:142:8: Error: Too few positional arguments: 1 required, 0 given.
+// f6a(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:143:8: Error: Required named parameter 'field3' must be provided.
+// f6a(42); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:144:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f6a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:145:8: Error: Too few positional arguments: 1 required, 0 given.
+// f6a(field1: 87, field2: 87); // error
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class1::•]/*isLegacy*/;
+ constructor _() → self::Class1
+ : super core::Object::•()
+ ;
+ static factory •() → self::Class1
+ let dynamic #redirecting_factory = self::Class1::_ in invalid-expression;
+}
+class Class2 extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class2::named]/*isLegacy*/;
+ constructor __() → self::Class2
+ : super core::Object::•()
+ ;
+ static factory _() → self::Class2
+ return new self::Class2::__();
+ static factory named() → self::Class2
+ let dynamic #redirecting_factory = self::Class2::_ in invalid-expression;
+}
+class Class3 extends core::Object {
+ final field core::int field;
+ static final field dynamic _redirecting# = <dynamic>[self::Class3::•]/*isLegacy*/;
+ constructor _(core::int field) → self::Class3
+ : self::Class3::field = field, super core::Object::•()
+ ;
+ static factory •(core::int field) → self::Class3
+ let dynamic #redirecting_factory = self::Class3::_ in invalid-expression;
+}
+class Class4 extends core::Object {
+ final field core::int? field;
+ static final field dynamic _redirecting# = <dynamic>[self::Class4::•]/*isLegacy*/;
+ constructor _([core::int? field = #C1]) → self::Class4
+ : self::Class4::field = field, super core::Object::•()
+ ;
+ static factory •([core::int? field = #C1]) → self::Class4
+ let dynamic #redirecting_factory = self::Class4::_ in invalid-expression;
+}
+class Class5 extends core::Object {
+ final field core::int field1;
+ final field core::int? field2;
+ static final field dynamic _redirecting# = <dynamic>[self::Class5::•]/*isLegacy*/;
+ constructor _(core::int field1, [core::int? field2 = #C1]) → self::Class5
+ : self::Class5::field1 = field1, self::Class5::field2 = field2, super core::Object::•()
+ ;
+ static factory •(core::int field1, [core::int? field2 = #C1]) → self::Class5
+ let dynamic #redirecting_factory = self::Class5::_ in invalid-expression;
+}
+class Class6 extends core::Object {
+ final field core::int field1;
+ final field core::int? field2;
+ final field core::int field3;
+ static final field dynamic _redirecting# = <dynamic>[self::Class6::•]/*isLegacy*/;
+ constructor _(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+ : self::Class6::field1 = field1, self::Class6::field2 = field2, self::Class6::field3 = field3, super core::Object::•()
+ ;
+ static factory •(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+ let dynamic #redirecting_factory = self::Class6::_ in invalid-expression;
+}
+class Class7a extends core::Object implements self::Class7b {
+ constructor •() → self::Class7a
+ : super core::Object::•()
+ ;
+}
+class Class7b extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class7b::•]/*isLegacy*/;
+ static factory •() → self::Class7b
+ let dynamic #redirecting_factory = self::Class7a::• in invalid-expression;
+}
+class Class8a<T extends core::Object? = dynamic> extends core::Object implements self::Class8b<self::Class8a::T%> {
+ constructor •() → self::Class8a<self::Class8a::T%>
+ : super core::Object::•()
+ ;
+}
+class Class8b<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class8b::•]/*isLegacy*/;
+ static factory •<T extends core::Object? = dynamic>() → self::Class8b<self::Class8b::•::T%>
+ let dynamic #redirecting_factory = self::Class8a::• in let self::Class8b::•::T% #typeArg0 = null in invalid-expression;
+}
+static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+ core::print("inSoundMode: ${self::inSoundMode}");
+ self::testNoArgs();
+ self::testArgs();
+}
+static method testNoArgs() → dynamic {
+ () → self::Class1 f1a = #C2;
+ self::Class1 c1a = f1a(){() → self::Class1};
+ self::expect(true, c1a is{ForNonNullableByDefault} self::Class1);
+ dynamic f1b = #C2;
+ dynamic c1b = f1b{dynamic}.call();
+ self::expect(true, c1b is{ForNonNullableByDefault} self::Class1);
+ self::expect(true, core::identical(f1a, f1b));
+ () → self::Class2 f2a = #C3;
+ self::Class2 c2a = f2a(){() → self::Class2};
+ self::expect(true, c2a is{ForNonNullableByDefault} self::Class2);
+ dynamic f2b = #C3;
+ dynamic c2b = f2b{dynamic}.call();
+ self::expect(true, c2b is{ForNonNullableByDefault} self::Class2);
+ self::expect(true, core::identical(f2a, f2b));
+}
+static method testArgs() → dynamic {
+ (core::int) → self::Class3 f3a = #C4;
+ self::Class3 c3a = f3a(42){(core::int) → self::Class3};
+ self::expect(42, c3a.{self::Class3::field}{core::int});
+ () → Null {
+ let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:99:8: Error: Too few positional arguments: 1 required, 0 given.
+ f3a(); // error
+ ^" in f3a{<inapplicable>}.();
+ let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:100:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f3a(42, 87); // error
+ ^" in f3a{<inapplicable>}.(42, 87);
+ };
+ dynamic f3b = #C4;
+ dynamic c3b = f3b{dynamic}.call(87);
+ self::expect(87, c3b{dynamic}.field);
+ self::throws(() → dynamic => f3b{dynamic}.call());
+ self::throws(() → dynamic => f3b{dynamic}.call(42, 87));
+ ([core::int?]) → self::Class4 f4a = #C5;
+ self::Class4 c4a = f4a(){([core::int?]) → self::Class4};
+ self::expect(null, c4a.{self::Class4::field}{core::int?});
+ self::Class4 c4b = f4a(42){([core::int?]) → self::Class4};
+ self::expect(42, c4b.{self::Class4::field}{core::int?});
+ () → Null {
+ let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:115:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f4a(42, 87); // error
+ ^" in f4a{<inapplicable>}.(42, 87);
+ };
+ dynamic f4b = #C5;
+ self::throws(() → dynamic => f4b{dynamic}.call(42, 87));
+ (core::int, [core::int?]) → self::Class5 f5a = #C6;
+ self::Class5 c5a = f5a(42){(core::int, [core::int?]) → self::Class5};
+ self::expect(42, c5a.{self::Class5::field1}{core::int});
+ self::expect(null, c5a.{self::Class5::field2}{core::int?});
+ self::Class5 c5b = f5a(87, 42){(core::int, [core::int?]) → self::Class5};
+ self::expect(87, c5b.{self::Class5::field1}{core::int});
+ self::expect(42, c5b.{self::Class5::field2}{core::int?});
+ () → Null {
+ let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:129:8: Error: Too few positional arguments: 1 required, 0 given.
+ f5a(); // error
+ ^" in f5a{<inapplicable>}.();
+ let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:130:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+Try removing the extra positional arguments.
+ f5a(42, 87, 123); // error
+ ^" in f5a{<inapplicable>}.(42, 87, 123);
+ };
+ dynamic f5b = #C6;
+ self::throws(() → dynamic => f5b{dynamic}.call());
+ self::throws(() → dynamic => f5b{dynamic}.call(42, 87, 123));
+ (core::int, {field2: core::int?, required field3: core::int}) → self::Class6 f6a = #C7;
+ self::Class6 c6a = f6a(42, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+ self::expect(42, c6a.{self::Class6::field1}{core::int});
+ self::expect(null, c6a.{self::Class6::field2}{core::int?});
+ self::expect(87, c6a.{self::Class6::field3}{core::int});
+ () → Null {
+ let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:142:8: Error: Too few positional arguments: 1 required, 0 given.
+ f6a(); // error
+ ^" in f6a{<inapplicable>}.();
+ let final Never #t7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:143:8: Error: Required named parameter 'field3' must be provided.
+ f6a(42); // error
+ ^" in f6a{<inapplicable>}.(42);
+ let final Never #t8 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:144:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f6a(42, 87); // error
+ ^" in f6a{<inapplicable>}.(42, 87);
+ let final Never #t9 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:145:8: Error: Too few positional arguments: 1 required, 0 given.
+ f6a(field1: 87, field2: 87); // error
+ ^" in f6a{<inapplicable>}.(field1: 87, field2: 87);
+ };
+ self::Class6 c6b = f6a(42, field2: 123, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+ self::expect(42, c6b.{self::Class6::field1}{core::int});
+ self::expect(123, c6b.{self::Class6::field2}{core::int?});
+ self::expect(87, c6b.{self::Class6::field3}{core::int});
+ self::Class6 c6c = f6a(87, field3: 42, field2: 123){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+ self::expect(87, c6c.{self::Class6::field1}{core::int});
+ self::expect(123, c6c.{self::Class6::field2}{core::int?});
+ self::expect(42, c6c.{self::Class6::field3}{core::int});
+ dynamic f6b = #C7;
+ self::throws(() → dynamic => f6b{dynamic}.call());
+ self::throws(() → dynamic => f6b{dynamic}.call(42), inSoundModeOnly: true);
+ self::throws(() → dynamic => f6b{dynamic}.call(42, 87), inSoundModeOnly: true);
+ self::throws(() → dynamic => f6b{dynamic}.call(field1: 87, field2: 87));
+ () → self::Class7b f7a = #C8;
+ self::Class7b c7a = f7a(){() → self::Class7b};
+ self::expect(true, c7a is{ForNonNullableByDefault} self::Class7a);
+ self::expect(true, c7a is{ForNonNullableByDefault} self::Class7b);
+ <T extends core::Object? = dynamic>() → self::Class8b<T%> f8a = #C9;
+ self::Class8b<dynamic> c8a = f8a<dynamic>(){() → self::Class8b<dynamic>};
+ self::expect(true, c8a is{ForNonNullableByDefault} self::Class8a<dynamic>);
+ self::expect(true, c8a is{ForNonNullableByDefault} self::Class8b<dynamic>);
+ self::Class8b<core::int> c8b = f8a<core::int>(){() → self::Class8b<core::int>};
+ self::expect(true, c8b is{ForNonNullableByDefault} self::Class8a<core::int>);
+ self::expect(true, c8b is{ForNonNullableByDefault} self::Class8b<core::int>);
+ self::expect(false, c8b is{ForNonNullableByDefault} self::Class8b<core::String>);
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C10}) → dynamic {
+ try {
+ f(){() → dynamic};
+ }
+ on core::Object catch(final core::Object e) {
+ core::print("Thrown: ${e}");
+ return;
+ }
+ if(!self::inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw "Expected exception";
+}
+
+constants {
+ #C1 = null
+ #C2 = redirecting-factory-tearoff self::Class1::•
+ #C3 = redirecting-factory-tearoff self::Class2::named
+ #C4 = redirecting-factory-tearoff self::Class3::•
+ #C5 = redirecting-factory-tearoff self::Class4::•
+ #C6 = redirecting-factory-tearoff self::Class5::•
+ #C7 = redirecting-factory-tearoff self::Class6::•
+ #C8 = redirecting-factory-tearoff self::Class7b::•
+ #C9 = redirecting-factory-tearoff self::Class8b::•
+ #C10 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.weak.outline.expect
new file mode 100644
index 0000000..d972b38
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.weak.outline.expect
@@ -0,0 +1,84 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class1::•]/*isLegacy*/;
+ constructor _() → self::Class1
+ ;
+ static factory •() → self::Class1
+ let dynamic #redirecting_factory = self::Class1::_ in invalid-expression;
+}
+class Class2 extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class2::named]/*isLegacy*/;
+ constructor __() → self::Class2
+ ;
+ static factory _() → self::Class2
+ ;
+ static factory named() → self::Class2
+ let dynamic #redirecting_factory = self::Class2::_ in invalid-expression;
+}
+class Class3 extends core::Object {
+ final field core::int field;
+ static final field dynamic _redirecting# = <dynamic>[self::Class3::•]/*isLegacy*/;
+ constructor _(core::int field) → self::Class3
+ ;
+ static factory •(core::int field) → self::Class3
+ let dynamic #redirecting_factory = self::Class3::_ in invalid-expression;
+}
+class Class4 extends core::Object {
+ final field core::int? field;
+ static final field dynamic _redirecting# = <dynamic>[self::Class4::•]/*isLegacy*/;
+ constructor _([core::int? field]) → self::Class4
+ ;
+ static factory •([core::int? field]) → self::Class4
+ let dynamic #redirecting_factory = self::Class4::_ in invalid-expression;
+}
+class Class5 extends core::Object {
+ final field core::int field1;
+ final field core::int? field2;
+ static final field dynamic _redirecting# = <dynamic>[self::Class5::•]/*isLegacy*/;
+ constructor _(core::int field1, [core::int? field2]) → self::Class5
+ ;
+ static factory •(core::int field1, [core::int? field2]) → self::Class5
+ let dynamic #redirecting_factory = self::Class5::_ in invalid-expression;
+}
+class Class6 extends core::Object {
+ final field core::int field1;
+ final field core::int? field2;
+ final field core::int field3;
+ static final field dynamic _redirecting# = <dynamic>[self::Class6::•]/*isLegacy*/;
+ constructor _(core::int field1, {core::int? field2, required core::int field3}) → self::Class6
+ ;
+ static factory •(core::int field1, {core::int? field2, required core::int field3}) → self::Class6
+ let dynamic #redirecting_factory = self::Class6::_ in invalid-expression;
+}
+class Class7a extends core::Object implements self::Class7b {
+ constructor •() → self::Class7a
+ ;
+}
+class Class7b extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class7b::•]/*isLegacy*/;
+ static factory •() → self::Class7b
+ let dynamic #redirecting_factory = self::Class7a::• in invalid-expression;
+}
+class Class8a<T extends core::Object? = dynamic> extends core::Object implements self::Class8b<self::Class8a::T%> {
+ constructor •() → self::Class8a<self::Class8a::T%>
+ ;
+}
+class Class8b<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class8b::•]/*isLegacy*/;
+ static factory •<T extends core::Object? = dynamic>() → self::Class8b<self::Class8b::•::T%>
+ let dynamic #redirecting_factory = self::Class8a::• in let self::Class8b::•::T% #typeArg0 = null in invalid-expression;
+}
+static final field core::bool inSoundMode;
+static method main() → dynamic
+ ;
+static method testNoArgs() → dynamic
+ ;
+static method testArgs() → dynamic
+ ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+ ;
+static method throws(() → dynamic f, {core::bool inSoundModeOnly}) → dynamic
+ ;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.weak.transformed.expect
new file mode 100644
index 0000000..872ae36
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart.weak.transformed.expect
@@ -0,0 +1,272 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:99:8: Error: Too few positional arguments: 1 required, 0 given.
+// f3a(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:100:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f3a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:115:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f4a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:129:8: Error: Too few positional arguments: 1 required, 0 given.
+// f5a(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:130:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+// Try removing the extra positional arguments.
+// f5a(42, 87, 123); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:142:8: Error: Too few positional arguments: 1 required, 0 given.
+// f6a(); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:143:8: Error: Required named parameter 'field3' must be provided.
+// f6a(42); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:144:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// Try removing the extra positional arguments.
+// f6a(42, 87); // error
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:145:8: Error: Too few positional arguments: 1 required, 0 given.
+// f6a(field1: 87, field2: 87); // error
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class1::•]/*isLegacy*/;
+ constructor _() → self::Class1
+ : super core::Object::•()
+ ;
+ static factory •() → self::Class1
+ let Never #redirecting_factory = self::Class1::_ in invalid-expression;
+}
+class Class2 extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class2::named]/*isLegacy*/;
+ constructor __() → self::Class2
+ : super core::Object::•()
+ ;
+ static factory _() → self::Class2
+ return new self::Class2::__();
+ static factory named() → self::Class2
+ let () → self::Class2 #redirecting_factory = self::Class2::_ in invalid-expression;
+}
+class Class3 extends core::Object {
+ final field core::int field;
+ static final field dynamic _redirecting# = <dynamic>[self::Class3::•]/*isLegacy*/;
+ constructor _(core::int field) → self::Class3
+ : self::Class3::field = field, super core::Object::•()
+ ;
+ static factory •(core::int field) → self::Class3
+ let Never #redirecting_factory = self::Class3::_ in invalid-expression;
+}
+class Class4 extends core::Object {
+ final field core::int? field;
+ static final field dynamic _redirecting# = <dynamic>[self::Class4::•]/*isLegacy*/;
+ constructor _([core::int? field = #C1]) → self::Class4
+ : self::Class4::field = field, super core::Object::•()
+ ;
+ static factory •([core::int? field = #C1]) → self::Class4
+ let Never #redirecting_factory = self::Class4::_ in invalid-expression;
+}
+class Class5 extends core::Object {
+ final field core::int field1;
+ final field core::int? field2;
+ static final field dynamic _redirecting# = <dynamic>[self::Class5::•]/*isLegacy*/;
+ constructor _(core::int field1, [core::int? field2 = #C1]) → self::Class5
+ : self::Class5::field1 = field1, self::Class5::field2 = field2, super core::Object::•()
+ ;
+ static factory •(core::int field1, [core::int? field2 = #C1]) → self::Class5
+ let Never #redirecting_factory = self::Class5::_ in invalid-expression;
+}
+class Class6 extends core::Object {
+ final field core::int field1;
+ final field core::int? field2;
+ final field core::int field3;
+ static final field dynamic _redirecting# = <dynamic>[self::Class6::•]/*isLegacy*/;
+ constructor _(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+ : self::Class6::field1 = field1, self::Class6::field2 = field2, self::Class6::field3 = field3, super core::Object::•()
+ ;
+ static factory •(core::int field1, {core::int? field2 = #C1, required core::int field3 = #C1}) → self::Class6
+ let Never #redirecting_factory = self::Class6::_ in invalid-expression;
+}
+class Class7a extends core::Object implements self::Class7b {
+ constructor •() → self::Class7a
+ : super core::Object::•()
+ ;
+}
+class Class7b extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class7b::•]/*isLegacy*/;
+ static factory •() → self::Class7b
+ let Never #redirecting_factory = self::Class7a::• in invalid-expression;
+}
+class Class8a<T extends core::Object? = dynamic> extends core::Object implements self::Class8b<self::Class8a::T%> {
+ constructor •() → self::Class8a<self::Class8a::T%>
+ : super core::Object::•()
+ ;
+}
+class Class8b<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Class8b::•]/*isLegacy*/;
+ static factory •<T extends core::Object? = dynamic>() → self::Class8b<self::Class8b::•::T%>
+ let Never #redirecting_factory = self::Class8a::• in let self::Class8b::•::T% #typeArg0 = null in invalid-expression;
+}
+static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
+static method main() → dynamic {
+ core::print("inSoundMode: ${self::inSoundMode}");
+ self::testNoArgs();
+ self::testArgs();
+}
+static method testNoArgs() → dynamic {
+ () → self::Class1 f1a = #C2;
+ self::Class1 c1a = f1a(){() → self::Class1};
+ self::expect(true, c1a is{ForNonNullableByDefault} self::Class1);
+ dynamic f1b = #C2;
+ dynamic c1b = f1b{dynamic}.call();
+ self::expect(true, c1b is{ForNonNullableByDefault} self::Class1);
+ self::expect(true, core::identical(f1a, f1b));
+ () → self::Class2 f2a = #C3;
+ self::Class2 c2a = f2a(){() → self::Class2};
+ self::expect(true, c2a is{ForNonNullableByDefault} self::Class2);
+ dynamic f2b = #C3;
+ dynamic c2b = f2b{dynamic}.call();
+ self::expect(true, c2b is{ForNonNullableByDefault} self::Class2);
+ self::expect(true, core::identical(f2a, f2b));
+}
+static method testArgs() → dynamic {
+ (core::int) → self::Class3 f3a = #C4;
+ self::Class3 c3a = f3a(42){(core::int) → self::Class3};
+ self::expect(42, c3a.{self::Class3::field}{core::int});
+ () → Null {
+ let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:99:8: Error: Too few positional arguments: 1 required, 0 given.
+ f3a(); // error
+ ^" in f3a{<inapplicable>}.();
+ let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:100:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f3a(42, 87); // error
+ ^" in f3a{<inapplicable>}.(42, 87);
+ };
+ dynamic f3b = #C4;
+ dynamic c3b = f3b{dynamic}.call(87);
+ self::expect(87, c3b{dynamic}.field);
+ self::throws(() → dynamic => f3b{dynamic}.call());
+ self::throws(() → dynamic => f3b{dynamic}.call(42, 87));
+ ([core::int?]) → self::Class4 f4a = #C5;
+ self::Class4 c4a = f4a(){([core::int?]) → self::Class4};
+ self::expect(null, c4a.{self::Class4::field}{core::int?});
+ self::Class4 c4b = f4a(42){([core::int?]) → self::Class4};
+ self::expect(42, c4b.{self::Class4::field}{core::int?});
+ () → Null {
+ let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:115:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f4a(42, 87); // error
+ ^" in f4a{<inapplicable>}.(42, 87);
+ };
+ dynamic f4b = #C5;
+ self::throws(() → dynamic => f4b{dynamic}.call(42, 87));
+ (core::int, [core::int?]) → self::Class5 f5a = #C6;
+ self::Class5 c5a = f5a(42){(core::int, [core::int?]) → self::Class5};
+ self::expect(42, c5a.{self::Class5::field1}{core::int});
+ self::expect(null, c5a.{self::Class5::field2}{core::int?});
+ self::Class5 c5b = f5a(87, 42){(core::int, [core::int?]) → self::Class5};
+ self::expect(87, c5b.{self::Class5::field1}{core::int});
+ self::expect(42, c5b.{self::Class5::field2}{core::int?});
+ () → Null {
+ let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:129:8: Error: Too few positional arguments: 1 required, 0 given.
+ f5a(); // error
+ ^" in f5a{<inapplicable>}.();
+ let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:130:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+Try removing the extra positional arguments.
+ f5a(42, 87, 123); // error
+ ^" in f5a{<inapplicable>}.(42, 87, 123);
+ };
+ dynamic f5b = #C6;
+ self::throws(() → dynamic => f5b{dynamic}.call());
+ self::throws(() → dynamic => f5b{dynamic}.call(42, 87, 123));
+ (core::int, {field2: core::int?, required field3: core::int}) → self::Class6 f6a = #C7;
+ self::Class6 c6a = f6a(42, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+ self::expect(42, c6a.{self::Class6::field1}{core::int});
+ self::expect(null, c6a.{self::Class6::field2}{core::int?});
+ self::expect(87, c6a.{self::Class6::field3}{core::int});
+ () → Null {
+ let final Never #t6 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:142:8: Error: Too few positional arguments: 1 required, 0 given.
+ f6a(); // error
+ ^" in f6a{<inapplicable>}.();
+ let final Never #t7 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:143:8: Error: Required named parameter 'field3' must be provided.
+ f6a(42); // error
+ ^" in f6a{<inapplicable>}.(42);
+ let final Never #t8 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:144:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+Try removing the extra positional arguments.
+ f6a(42, 87); // error
+ ^" in f6a{<inapplicable>}.(42, 87);
+ let final Never #t9 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/redirecting_factory_tear_off.dart:145:8: Error: Too few positional arguments: 1 required, 0 given.
+ f6a(field1: 87, field2: 87); // error
+ ^" in f6a{<inapplicable>}.(field1: 87, field2: 87);
+ };
+ self::Class6 c6b = f6a(42, field2: 123, field3: 87){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+ self::expect(42, c6b.{self::Class6::field1}{core::int});
+ self::expect(123, c6b.{self::Class6::field2}{core::int?});
+ self::expect(87, c6b.{self::Class6::field3}{core::int});
+ self::Class6 c6c = f6a(87, field3: 42, field2: 123){(core::int, {field2: core::int?, required field3: core::int}) → self::Class6};
+ self::expect(87, c6c.{self::Class6::field1}{core::int});
+ self::expect(123, c6c.{self::Class6::field2}{core::int?});
+ self::expect(42, c6c.{self::Class6::field3}{core::int});
+ dynamic f6b = #C7;
+ self::throws(() → dynamic => f6b{dynamic}.call());
+ self::throws(() → dynamic => f6b{dynamic}.call(42), inSoundModeOnly: true);
+ self::throws(() → dynamic => f6b{dynamic}.call(42, 87), inSoundModeOnly: true);
+ self::throws(() → dynamic => f6b{dynamic}.call(field1: 87, field2: 87));
+ () → self::Class7b f7a = #C8;
+ self::Class7b c7a = f7a(){() → self::Class7b};
+ self::expect(true, c7a is{ForNonNullableByDefault} self::Class7a);
+ self::expect(true, c7a is{ForNonNullableByDefault} self::Class7b);
+ <T extends core::Object? = dynamic>() → self::Class8b<T%> f8a = #C9;
+ self::Class8b<dynamic> c8a = f8a<dynamic>(){() → self::Class8b<dynamic>};
+ self::expect(true, c8a is{ForNonNullableByDefault} self::Class8a<dynamic>);
+ self::expect(true, c8a is{ForNonNullableByDefault} self::Class8b<dynamic>);
+ self::Class8b<core::int> c8b = f8a<core::int>(){() → self::Class8b<core::int>};
+ self::expect(true, c8b is{ForNonNullableByDefault} self::Class8a<core::int>);
+ self::expect(true, c8b is{ForNonNullableByDefault} self::Class8b<core::int>);
+ self::expect(false, c8b is{ForNonNullableByDefault} self::Class8b<core::String>);
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C10}) → dynamic {
+ try {
+ f(){() → dynamic};
+ }
+ on core::Object catch(final core::Object e) {
+ core::print("Thrown: ${e}");
+ return;
+ }
+ if(!self::inSoundMode && inSoundModeOnly) {
+ return;
+ }
+ throw "Expected exception";
+}
+
+constants {
+ #C1 = null
+ #C2 = redirecting-factory-tearoff self::Class1::•
+ #C3 = redirecting-factory-tearoff self::Class2::named
+ #C4 = redirecting-factory-tearoff self::Class3::•
+ #C5 = redirecting-factory-tearoff self::Class4::•
+ #C6 = redirecting-factory-tearoff self::Class5::•
+ #C7 = redirecting-factory-tearoff self::Class6::•
+ #C8 = redirecting-factory-tearoff self::Class7b::•
+ #C9 = redirecting-factory-tearoff self::Class8b::•
+ #C10 = false
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart b/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart
new file mode 100644
index 0000000..969cca4
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart
@@ -0,0 +1,36 @@
+// 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 A1<T> {}
+
+typedef B1<T> = A1<T>;
+
+class A2<T extends num> {}
+
+typedef B2<T extends num> = A2<T>;
+
+class A3<T extends List<dynamic>, S extends Never?> {}
+
+typedef B3<T extends List<Object?>, S extends Null> = A3<T, S>;
+
+class A4<T extends num> {}
+
+typedef B4<T extends int> = A4<T>;
+
+class A5<T extends List<dynamic>, S extends Never?> {}
+
+typedef B5<T extends List<Object?>, S extends Null> = A5;
+
+class StaticIdentityTest {
+ const StaticIdentityTest(a, b) : assert(identical(a, b));
+}
+
+test1() => const StaticIdentityTest(A1.new, B1.new); // Ok.
+test2() => const StaticIdentityTest(A2.new, B2.new); // Ok.
+test3() => const StaticIdentityTest(A3.new, B3.new); // Ok.
+test4() => const StaticIdentityTest(A4.new, B4.new); // Error.
+test5() => const StaticIdentityTest(A5.new, B5.new); // Error.
+
+
+main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart.strong.expect
new file mode 100644
index 0000000..2949323
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart.strong.expect
@@ -0,0 +1,77 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart:32:18: Error: Constant evaluation error:
+// test4() => const StaticIdentityTest(A4.new, B4.new); // Error.
+// ^
+// pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart:26:43: Context: This assertion failed.
+// const StaticIdentityTest(a, b) : assert(identical(a, b));
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart:33:18: Error: Constant evaluation error:
+// test5() => const StaticIdentityTest(A5.new, B5.new); // Error.
+// ^
+// pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart:26:43: Context: This assertion failed.
+// const StaticIdentityTest(a, b) : assert(identical(a, b));
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef B1<T extends core::Object? = dynamic> = self::A1<T%>;
+typedef B2<T extends core::num> = self::A2<T>;
+typedef B3<T extends core::List<core::Object?>, S extends Null> = self::A3<T, S%>;
+typedef B4<T extends core::int> = self::A4<T>;
+typedef B5<unrelated T extends core::List<core::Object?>, unrelated S extends Null> = self::A5<core::List<dynamic>, Never?>;
+class A1<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::A1<self::A1::T%>
+ : super core::Object::•()
+ ;
+}
+class A2<T extends core::num> extends core::Object {
+ synthetic constructor •() → self::A2<self::A2::T>
+ : super core::Object::•()
+ ;
+}
+class A3<T extends core::List<dynamic>, S extends Never?> extends core::Object {
+ synthetic constructor •() → self::A3<self::A3::T, self::A3::S%>
+ : super core::Object::•()
+ ;
+}
+class A4<T extends core::num> extends core::Object {
+ synthetic constructor •() → self::A4<self::A4::T>
+ : super core::Object::•()
+ ;
+}
+class A5<T extends core::List<dynamic>, S extends Never?> extends core::Object {
+ synthetic constructor •() → self::A5<self::A5::T, self::A5::S%>
+ : super core::Object::•()
+ ;
+}
+class StaticIdentityTest extends core::Object /*hasConstConstructor*/ {
+ const constructor •(dynamic a, dynamic b) → self::StaticIdentityTest
+ : assert(core::identical(a, b)), super core::Object::•()
+ ;
+}
+static method test1() → dynamic
+ return #C1;
+static method test2() → dynamic
+ return #C1;
+static method test3() → dynamic
+ return #C1;
+static method test4() → dynamic
+ return invalid-expression "This assertion failed.";
+static method test5() → dynamic
+ return invalid-expression "This assertion failed.";
+static method main() → dynamic {}
+
+constants {
+ #C1 = self::StaticIdentityTest {}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///simple_proper_rename_identity.dart:
+- StaticIdentityTest. (from org-dartlang-testcase:///simple_proper_rename_identity.dart:26:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart.strong.transformed.expect
new file mode 100644
index 0000000..2949323
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart.strong.transformed.expect
@@ -0,0 +1,77 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart:32:18: Error: Constant evaluation error:
+// test4() => const StaticIdentityTest(A4.new, B4.new); // Error.
+// ^
+// pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart:26:43: Context: This assertion failed.
+// const StaticIdentityTest(a, b) : assert(identical(a, b));
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart:33:18: Error: Constant evaluation error:
+// test5() => const StaticIdentityTest(A5.new, B5.new); // Error.
+// ^
+// pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart:26:43: Context: This assertion failed.
+// const StaticIdentityTest(a, b) : assert(identical(a, b));
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef B1<T extends core::Object? = dynamic> = self::A1<T%>;
+typedef B2<T extends core::num> = self::A2<T>;
+typedef B3<T extends core::List<core::Object?>, S extends Null> = self::A3<T, S%>;
+typedef B4<T extends core::int> = self::A4<T>;
+typedef B5<unrelated T extends core::List<core::Object?>, unrelated S extends Null> = self::A5<core::List<dynamic>, Never?>;
+class A1<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::A1<self::A1::T%>
+ : super core::Object::•()
+ ;
+}
+class A2<T extends core::num> extends core::Object {
+ synthetic constructor •() → self::A2<self::A2::T>
+ : super core::Object::•()
+ ;
+}
+class A3<T extends core::List<dynamic>, S extends Never?> extends core::Object {
+ synthetic constructor •() → self::A3<self::A3::T, self::A3::S%>
+ : super core::Object::•()
+ ;
+}
+class A4<T extends core::num> extends core::Object {
+ synthetic constructor •() → self::A4<self::A4::T>
+ : super core::Object::•()
+ ;
+}
+class A5<T extends core::List<dynamic>, S extends Never?> extends core::Object {
+ synthetic constructor •() → self::A5<self::A5::T, self::A5::S%>
+ : super core::Object::•()
+ ;
+}
+class StaticIdentityTest extends core::Object /*hasConstConstructor*/ {
+ const constructor •(dynamic a, dynamic b) → self::StaticIdentityTest
+ : assert(core::identical(a, b)), super core::Object::•()
+ ;
+}
+static method test1() → dynamic
+ return #C1;
+static method test2() → dynamic
+ return #C1;
+static method test3() → dynamic
+ return #C1;
+static method test4() → dynamic
+ return invalid-expression "This assertion failed.";
+static method test5() → dynamic
+ return invalid-expression "This assertion failed.";
+static method main() → dynamic {}
+
+constants {
+ #C1 = self::StaticIdentityTest {}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///simple_proper_rename_identity.dart:
+- StaticIdentityTest. (from org-dartlang-testcase:///simple_proper_rename_identity.dart:26:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart.textual_outline.expect
new file mode 100644
index 0000000..77787a1
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart.textual_outline.expect
@@ -0,0 +1,19 @@
+class A1<T> {}
+typedef B1<T> = A1<T>;
+class A2<T extends num> {}
+typedef B2<T extends num> = A2<T>;
+class A3<T extends List<dynamic>, S extends Never?> {}
+typedef B3<T extends List<Object?>, S extends Null> = A3<T, S>;
+class A4<T extends num> {}
+typedef B4<T extends int> = A4<T>;
+class A5<T extends List<dynamic>, S extends Never?> {}
+typedef B5<T extends List<Object?>, S extends Null> = A5;
+class StaticIdentityTest {
+ const StaticIdentityTest(a, b) : assert(identical(a, b));
+}
+test1() => const StaticIdentityTest(A1.new, B1.new);
+test2() => const StaticIdentityTest(A2.new, B2.new);
+test3() => const StaticIdentityTest(A3.new, B3.new);
+test4() => const StaticIdentityTest(A4.new, B4.new);
+test5() => const StaticIdentityTest(A5.new, B5.new);
+main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart.weak.expect
new file mode 100644
index 0000000..2949323
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart.weak.expect
@@ -0,0 +1,77 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart:32:18: Error: Constant evaluation error:
+// test4() => const StaticIdentityTest(A4.new, B4.new); // Error.
+// ^
+// pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart:26:43: Context: This assertion failed.
+// const StaticIdentityTest(a, b) : assert(identical(a, b));
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart:33:18: Error: Constant evaluation error:
+// test5() => const StaticIdentityTest(A5.new, B5.new); // Error.
+// ^
+// pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart:26:43: Context: This assertion failed.
+// const StaticIdentityTest(a, b) : assert(identical(a, b));
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef B1<T extends core::Object? = dynamic> = self::A1<T%>;
+typedef B2<T extends core::num> = self::A2<T>;
+typedef B3<T extends core::List<core::Object?>, S extends Null> = self::A3<T, S%>;
+typedef B4<T extends core::int> = self::A4<T>;
+typedef B5<unrelated T extends core::List<core::Object?>, unrelated S extends Null> = self::A5<core::List<dynamic>, Never?>;
+class A1<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::A1<self::A1::T%>
+ : super core::Object::•()
+ ;
+}
+class A2<T extends core::num> extends core::Object {
+ synthetic constructor •() → self::A2<self::A2::T>
+ : super core::Object::•()
+ ;
+}
+class A3<T extends core::List<dynamic>, S extends Never?> extends core::Object {
+ synthetic constructor •() → self::A3<self::A3::T, self::A3::S%>
+ : super core::Object::•()
+ ;
+}
+class A4<T extends core::num> extends core::Object {
+ synthetic constructor •() → self::A4<self::A4::T>
+ : super core::Object::•()
+ ;
+}
+class A5<T extends core::List<dynamic>, S extends Never?> extends core::Object {
+ synthetic constructor •() → self::A5<self::A5::T, self::A5::S%>
+ : super core::Object::•()
+ ;
+}
+class StaticIdentityTest extends core::Object /*hasConstConstructor*/ {
+ const constructor •(dynamic a, dynamic b) → self::StaticIdentityTest
+ : assert(core::identical(a, b)), super core::Object::•()
+ ;
+}
+static method test1() → dynamic
+ return #C1;
+static method test2() → dynamic
+ return #C1;
+static method test3() → dynamic
+ return #C1;
+static method test4() → dynamic
+ return invalid-expression "This assertion failed.";
+static method test5() → dynamic
+ return invalid-expression "This assertion failed.";
+static method main() → dynamic {}
+
+constants {
+ #C1 = self::StaticIdentityTest {}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///simple_proper_rename_identity.dart:
+- StaticIdentityTest. (from org-dartlang-testcase:///simple_proper_rename_identity.dart:26:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart.weak.outline.expect
new file mode 100644
index 0000000..fd75da2
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart.weak.outline.expect
@@ -0,0 +1,46 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef B1<T extends core::Object? = dynamic> = self::A1<T%>;
+typedef B2<T extends core::num> = self::A2<T>;
+typedef B3<T extends core::List<core::Object?>, S extends Null> = self::A3<T, S%>;
+typedef B4<T extends core::int> = self::A4<T>;
+typedef B5<unrelated T extends core::List<core::Object?>, unrelated S extends Null> = self::A5<core::List<dynamic>, Never?>;
+class A1<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::A1<self::A1::T%>
+ ;
+}
+class A2<T extends core::num> extends core::Object {
+ synthetic constructor •() → self::A2<self::A2::T>
+ ;
+}
+class A3<T extends core::List<dynamic>, S extends Never?> extends core::Object {
+ synthetic constructor •() → self::A3<self::A3::T, self::A3::S%>
+ ;
+}
+class A4<T extends core::num> extends core::Object {
+ synthetic constructor •() → self::A4<self::A4::T>
+ ;
+}
+class A5<T extends core::List<dynamic>, S extends Never?> extends core::Object {
+ synthetic constructor •() → self::A5<self::A5::T, self::A5::S%>
+ ;
+}
+class StaticIdentityTest extends core::Object /*hasConstConstructor*/ {
+ const constructor •(dynamic a, dynamic b) → self::StaticIdentityTest
+ : assert(core::identical(a, b)), super core::Object::•()
+ ;
+}
+static method test1() → dynamic
+ ;
+static method test2() → dynamic
+ ;
+static method test3() → dynamic
+ ;
+static method test4() → dynamic
+ ;
+static method test5() → dynamic
+ ;
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart.weak.transformed.expect
new file mode 100644
index 0000000..2949323
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart.weak.transformed.expect
@@ -0,0 +1,77 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart:32:18: Error: Constant evaluation error:
+// test4() => const StaticIdentityTest(A4.new, B4.new); // Error.
+// ^
+// pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart:26:43: Context: This assertion failed.
+// const StaticIdentityTest(a, b) : assert(identical(a, b));
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart:33:18: Error: Constant evaluation error:
+// test5() => const StaticIdentityTest(A5.new, B5.new); // Error.
+// ^
+// pkg/front_end/testcases/constructor_tearoffs/simple_proper_rename_identity.dart:26:43: Context: This assertion failed.
+// const StaticIdentityTest(a, b) : assert(identical(a, b));
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef B1<T extends core::Object? = dynamic> = self::A1<T%>;
+typedef B2<T extends core::num> = self::A2<T>;
+typedef B3<T extends core::List<core::Object?>, S extends Null> = self::A3<T, S%>;
+typedef B4<T extends core::int> = self::A4<T>;
+typedef B5<unrelated T extends core::List<core::Object?>, unrelated S extends Null> = self::A5<core::List<dynamic>, Never?>;
+class A1<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::A1<self::A1::T%>
+ : super core::Object::•()
+ ;
+}
+class A2<T extends core::num> extends core::Object {
+ synthetic constructor •() → self::A2<self::A2::T>
+ : super core::Object::•()
+ ;
+}
+class A3<T extends core::List<dynamic>, S extends Never?> extends core::Object {
+ synthetic constructor •() → self::A3<self::A3::T, self::A3::S%>
+ : super core::Object::•()
+ ;
+}
+class A4<T extends core::num> extends core::Object {
+ synthetic constructor •() → self::A4<self::A4::T>
+ : super core::Object::•()
+ ;
+}
+class A5<T extends core::List<dynamic>, S extends Never?> extends core::Object {
+ synthetic constructor •() → self::A5<self::A5::T, self::A5::S%>
+ : super core::Object::•()
+ ;
+}
+class StaticIdentityTest extends core::Object /*hasConstConstructor*/ {
+ const constructor •(dynamic a, dynamic b) → self::StaticIdentityTest
+ : assert(core::identical(a, b)), super core::Object::•()
+ ;
+}
+static method test1() → dynamic
+ return #C1;
+static method test2() → dynamic
+ return #C1;
+static method test3() → dynamic
+ return #C1;
+static method test4() → dynamic
+ return invalid-expression "This assertion failed.";
+static method test5() → dynamic
+ return invalid-expression "This assertion failed.";
+static method main() → dynamic {}
+
+constants {
+ #C1 = self::StaticIdentityTest {}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///simple_proper_rename_identity.dart:
+- StaticIdentityTest. (from org-dartlang-testcase:///simple_proper_rename_identity.dart:26:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart b/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart
index 0abf8e6..1ee6b80 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart
+++ b/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart
@@ -45,7 +45,9 @@
B<num> Function() test19() => DB3<num, String>.foo; // Ok.
B<num> Function() test20() => DB3<num, String>.bar; // Ok.
B<num> Function() test21() => DB3.new; // Ok.
-B<Y> Function<Y extends num, Z extends String>() test22() => DB2.new; // Ok.
-B<Y> Function<Y, Z>() test23() => DB2.new; // Error.
+B<Y> Function<Y extends num, Z extends String>() test22() => DB3.new; // Ok.
+B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
+
+B<String> Function() test24() => DB2.new; // Ok.
main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.strong.expect
index 0a4373e..b69871d 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.strong.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.strong.expect
@@ -15,24 +15,24 @@
// B<num> Function() test9() => DB1.new; // Error.
// ^
//
-// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:41:44: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y extends num>()'.
-// - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-// B<Y> Function<Y extends num>() test16() => DB2.new; // Ok.
-// ^
-//
-// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y>()'.
+// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<X> Function<X extends num>()' can't be assigned to a variable of type 'B<Y> Function<Y>()'.
// - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
// B<Y> Function<Y>() test17() => DB2.new; // Error.
// ^
//
-// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:48:62: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y extends num, Z extends String>()'.
+// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<X> Function<X extends num>()' can't be returned from a function with return type 'B<Y> Function<Y>()'.
// - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-// B<Y> Function<Y extends num, Z extends String>() test22() => DB2.new; // Ok.
-// ^
+// B<Y> Function<Y>() test17() => DB2.new; // Error.
+// ^
//
-// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y, Z>()'.
+// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<X> Function<X extends num, Y extends String>()' can't be assigned to a variable of type 'B<Y> Function<Y, Z>()'.
// - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-// B<Y> Function<Y, Z>() test23() => DB2.new; // Error.
+// B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<X> Function<X extends num, Y extends String>()' can't be returned from a function with return type 'B<Y> Function<Y, Z>()'.
+// - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
+// B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
// ^
//
import self as self;
@@ -59,64 +59,83 @@
return new self::B::•<self::B::bar::X%>();
}
static method test1() → () → self::A
- return self::A::•;
+ return #C1;
static method test2() → () → self::A
- return self::A::•;
+ return #C1;
static method test3() → () → self::A
- return self::A::•;
+ return #C2;
static method test4() → () → self::A
- return self::A::•;
+ return #C2;
static method test5() → () → self::A
- return self::A::•;
+ return #C1;
static method test6() → () → self::A
- return self::A::•;
+ return #C1;
static method test7() → () → self::B<core::String>
- return self::B::•<core::String>;
+ return #C4;
static method test8() → () → self::B<core::String>
- return self::B::•<core::String>;
+ return #C4;
static method test9() → () → self::B<core::num>
return let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:33:30: Error: A value of type 'B<String> Function()' can't be returned from a function with return type 'B<num> Function()'.
- 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
B<num> Function() test9() => DB1.new; // Error.
- ^" in (self::B::•<core::String>) as{TypeError,ForNonNullableByDefault} () → self::B<core::num>;
+ ^" in (#C4) as{TypeError,ForNonNullableByDefault} () → self::B<core::num>;
static method test10() → () → self::B<core::String>
- return self::B::foo<core::String>;
+ return #C6;
static method test11() → () → self::B<core::String>
- return self::B::bar<core::String>;
+ return #C8;
static method test12() → () → self::B<core::num>
- return self::B::•<core::num>;
+ return #C9;
static method test13() → () → self::B<core::num>
- return self::B::foo<core::num>;
+ return #C10;
static method test14() → () → self::B<core::num>
- return self::B::bar<core::num>;
+ return #C11;
static method test15() → () → self::B<core::num>
- return self::B::•<core::num>;
+ return #C9;
static method test16() → <Y extends core::num = dynamic>() → self::B<Y>
- return let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:41:44: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y extends num>()'.
- - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-B<Y> Function<Y extends num>() test16() => DB2.new; // Ok.
- ^" in (self::B::•<core::num>) as{TypeError,ForNonNullableByDefault} <Y extends core::num = dynamic>() → self::B<Y>;
+ return #C12;
static method test17() → <Y extends core::Object? = dynamic>() → self::B<Y%>
- return let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y>()'.
+ return let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<X> Function<X extends num>()' can't be returned from a function with return type 'B<Y> Function<Y>()'.
- 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
B<Y> Function<Y>() test17() => DB2.new; // Error.
- ^" in (self::B::•<core::num>) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic>() → self::B<Y%>;
+ ^" in (let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<X> Function<X extends num>()' can't be assigned to a variable of type 'B<Y> Function<Y>()'.
+ - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
+B<Y> Function<Y>() test17() => DB2.new; // Error.
+ ^" in (#C12) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic>() → self::B<Y%>) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic>() → self::B<Y%>;
static method test18() → () → self::B<core::num>
- return self::B::•<core::num>;
+ return #C9;
static method test19() → () → self::B<core::num>
- return self::B::foo<core::num>;
+ return #C10;
static method test20() → () → self::B<core::num>
- return self::B::bar<core::num>;
+ return #C11;
static method test21() → () → self::B<core::num>
- return self::B::•<core::num>;
+ return #C9;
static method test22() → <Y extends core::num = dynamic, Z extends core::String = dynamic>() → self::B<Y>
- return let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:48:62: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y extends num, Z extends String>()'.
- - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-B<Y> Function<Y extends num, Z extends String>() test22() => DB2.new; // Ok.
- ^" in (self::B::•<core::num>) as{TypeError,ForNonNullableByDefault} <Y extends core::num = dynamic, Z extends core::String = dynamic>() → self::B<Y>;
+ return #C13;
static method test23() → <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>
- return let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y, Z>()'.
+ return let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<X> Function<X extends num, Y extends String>()' can't be returned from a function with return type 'B<Y> Function<Y, Z>()'.
- 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-B<Y> Function<Y, Z>() test23() => DB2.new; // Error.
- ^" in (self::B::•<core::num>) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>;
+B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
+ ^" in (let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<X> Function<X extends num, Y extends String>()' can't be assigned to a variable of type 'B<Y> Function<Y, Z>()'.
+ - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
+B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
+ ^" in (#C13) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>;
+static method test24() → () → self::B<core::String>
+ return #C14;
static method main() → dynamic {}
+
+constants {
+ #C1 = constructor-tearoff self::A::•
+ #C2 = instantiation self::A::• <>
+ #C3 = constructor-tearoff self::B::•
+ #C4 = instantiation self::B::• <core::String>
+ #C5 = constructor-tearoff self::B::foo
+ #C6 = instantiation self::B::foo <core::String>
+ #C7 = static-tearoff self::B::bar
+ #C8 = instantiation self::B::bar <core::String>
+ #C9 = instantiation self::B::• <core::num>
+ #C10 = instantiation self::B::foo <core::num>
+ #C11 = instantiation self::B::bar <core::num>
+ #C12 = typedef-tearoff <X extends core::num>.(#C3<X>)
+ #C13 = typedef-tearoff <X extends core::num, unrelated Y extends core::String>.(#C3<X>)
+ #C14 = instantiation self::B::• <Never>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.strong.transformed.expect
index 0a4373e..382b745 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.strong.transformed.expect
@@ -15,24 +15,24 @@
// B<num> Function() test9() => DB1.new; // Error.
// ^
//
-// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:41:44: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y extends num>()'.
-// - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-// B<Y> Function<Y extends num>() test16() => DB2.new; // Ok.
-// ^
-//
-// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y>()'.
+// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<X> Function<X extends num>()' can't be assigned to a variable of type 'B<Y> Function<Y>()'.
// - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
// B<Y> Function<Y>() test17() => DB2.new; // Error.
// ^
//
-// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:48:62: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y extends num, Z extends String>()'.
+// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<X> Function<X extends num>()' can't be returned from a function with return type 'B<Y> Function<Y>()'.
// - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-// B<Y> Function<Y extends num, Z extends String>() test22() => DB2.new; // Ok.
-// ^
+// B<Y> Function<Y>() test17() => DB2.new; // Error.
+// ^
//
-// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y, Z>()'.
+// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<X> Function<X extends num, Y extends String>()' can't be assigned to a variable of type 'B<Y> Function<Y, Z>()'.
// - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-// B<Y> Function<Y, Z>() test23() => DB2.new; // Error.
+// B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<X> Function<X extends num, Y extends String>()' can't be returned from a function with return type 'B<Y> Function<Y, Z>()'.
+// - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
+// B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
// ^
//
import self as self;
@@ -59,64 +59,83 @@
return new self::B::•<self::B::bar::X%>();
}
static method test1() → () → self::A
- return self::A::•;
+ return #C1;
static method test2() → () → self::A
- return self::A::•;
+ return #C1;
static method test3() → () → self::A
- return self::A::•;
+ return #C2;
static method test4() → () → self::A
- return self::A::•;
+ return #C2;
static method test5() → () → self::A
- return self::A::•;
+ return #C1;
static method test6() → () → self::A
- return self::A::•;
+ return #C1;
static method test7() → () → self::B<core::String>
- return self::B::•<core::String>;
+ return #C4;
static method test8() → () → self::B<core::String>
- return self::B::•<core::String>;
+ return #C4;
static method test9() → () → self::B<core::num>
return let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:33:30: Error: A value of type 'B<String> Function()' can't be returned from a function with return type 'B<num> Function()'.
- 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
B<num> Function() test9() => DB1.new; // Error.
- ^" in (self::B::•<core::String>) as{TypeError,ForNonNullableByDefault} () → self::B<core::num>;
+ ^" in (#C4) as{TypeError,ForNonNullableByDefault} () → self::B<core::num>;
static method test10() → () → self::B<core::String>
- return self::B::foo<core::String>;
+ return #C6;
static method test11() → () → self::B<core::String>
- return self::B::bar<core::String>;
+ return #C8;
static method test12() → () → self::B<core::num>
- return self::B::•<core::num>;
+ return #C9;
static method test13() → () → self::B<core::num>
- return self::B::foo<core::num>;
+ return #C10;
static method test14() → () → self::B<core::num>
- return self::B::bar<core::num>;
+ return #C11;
static method test15() → () → self::B<core::num>
- return self::B::•<core::num>;
+ return #C9;
static method test16() → <Y extends core::num = dynamic>() → self::B<Y>
- return let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:41:44: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y extends num>()'.
- - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-B<Y> Function<Y extends num>() test16() => DB2.new; // Ok.
- ^" in (self::B::•<core::num>) as{TypeError,ForNonNullableByDefault} <Y extends core::num = dynamic>() → self::B<Y>;
+ return #C12;
static method test17() → <Y extends core::Object? = dynamic>() → self::B<Y%>
- return let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y>()'.
+ return let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<X> Function<X extends num>()' can't be returned from a function with return type 'B<Y> Function<Y>()'.
- 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
B<Y> Function<Y>() test17() => DB2.new; // Error.
- ^" in (self::B::•<core::num>) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic>() → self::B<Y%>;
+ ^" in let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<X> Function<X extends num>()' can't be assigned to a variable of type 'B<Y> Function<Y>()'.
+ - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
+B<Y> Function<Y>() test17() => DB2.new; // Error.
+ ^" in (#C12) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic>() → self::B<Y%>;
static method test18() → () → self::B<core::num>
- return self::B::•<core::num>;
+ return #C9;
static method test19() → () → self::B<core::num>
- return self::B::foo<core::num>;
+ return #C10;
static method test20() → () → self::B<core::num>
- return self::B::bar<core::num>;
+ return #C11;
static method test21() → () → self::B<core::num>
- return self::B::•<core::num>;
+ return #C9;
static method test22() → <Y extends core::num = dynamic, Z extends core::String = dynamic>() → self::B<Y>
- return let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:48:62: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y extends num, Z extends String>()'.
- - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-B<Y> Function<Y extends num, Z extends String>() test22() => DB2.new; // Ok.
- ^" in (self::B::•<core::num>) as{TypeError,ForNonNullableByDefault} <Y extends core::num = dynamic, Z extends core::String = dynamic>() → self::B<Y>;
+ return #C13;
static method test23() → <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>
- return let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y, Z>()'.
+ return let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<X> Function<X extends num, Y extends String>()' can't be returned from a function with return type 'B<Y> Function<Y, Z>()'.
- 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-B<Y> Function<Y, Z>() test23() => DB2.new; // Error.
- ^" in (self::B::•<core::num>) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>;
+B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
+ ^" in let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<X> Function<X extends num, Y extends String>()' can't be assigned to a variable of type 'B<Y> Function<Y, Z>()'.
+ - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
+B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
+ ^" in (#C13) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>;
+static method test24() → () → self::B<core::String>
+ return #C14;
static method main() → dynamic {}
+
+constants {
+ #C1 = constructor-tearoff self::A::•
+ #C2 = instantiation self::A::• <>
+ #C3 = constructor-tearoff self::B::•
+ #C4 = instantiation self::B::• <core::String>
+ #C5 = constructor-tearoff self::B::foo
+ #C6 = instantiation self::B::foo <core::String>
+ #C7 = static-tearoff self::B::bar
+ #C8 = instantiation self::B::bar <core::String>
+ #C9 = instantiation self::B::• <core::num>
+ #C10 = instantiation self::B::foo <core::num>
+ #C11 = instantiation self::B::bar <core::num>
+ #C12 = typedef-tearoff <X extends core::num>.(#C3<X>)
+ #C13 = typedef-tearoff <X extends core::num, unrelated Y extends core::String>.(#C3<X>)
+ #C14 = instantiation self::B::• <Never>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.textual_outline.expect
index fe0d7be..c3a7ab9 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.textual_outline.expect
@@ -30,6 +30,7 @@
B<num> Function() test19() => DB3<num, String>.foo;
B<num> Function() test20() => DB3<num, String>.bar;
B<num> Function() test21() => DB3.new;
-B<Y> Function<Y extends num, Z extends String>() test22() => DB2.new;
-B<Y> Function<Y, Z>() test23() => DB2.new;
+B<Y> Function<Y extends num, Z extends String>() test22() => DB3.new;
+B<Y> Function<Y, Z>() test23() => DB3.new;
+B<String> Function() test24() => DB2.new;
main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.weak.expect
index 0a4373e..10912e2 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.weak.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.weak.expect
@@ -15,24 +15,24 @@
// B<num> Function() test9() => DB1.new; // Error.
// ^
//
-// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:41:44: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y extends num>()'.
-// - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-// B<Y> Function<Y extends num>() test16() => DB2.new; // Ok.
-// ^
-//
-// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y>()'.
+// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<X> Function<X extends num>()' can't be assigned to a variable of type 'B<Y> Function<Y>()'.
// - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
// B<Y> Function<Y>() test17() => DB2.new; // Error.
// ^
//
-// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:48:62: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y extends num, Z extends String>()'.
+// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<X> Function<X extends num>()' can't be returned from a function with return type 'B<Y> Function<Y>()'.
// - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-// B<Y> Function<Y extends num, Z extends String>() test22() => DB2.new; // Ok.
-// ^
+// B<Y> Function<Y>() test17() => DB2.new; // Error.
+// ^
//
-// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y, Z>()'.
+// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<X> Function<X extends num, Y extends String>()' can't be assigned to a variable of type 'B<Y> Function<Y, Z>()'.
// - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-// B<Y> Function<Y, Z>() test23() => DB2.new; // Error.
+// B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<X> Function<X extends num, Y extends String>()' can't be returned from a function with return type 'B<Y> Function<Y, Z>()'.
+// - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
+// B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
// ^
//
import self as self;
@@ -59,64 +59,83 @@
return new self::B::•<self::B::bar::X%>();
}
static method test1() → () → self::A
- return self::A::•;
+ return #C1;
static method test2() → () → self::A
- return self::A::•;
+ return #C1;
static method test3() → () → self::A
- return self::A::•;
+ return #C2;
static method test4() → () → self::A
- return self::A::•;
+ return #C2;
static method test5() → () → self::A
- return self::A::•;
+ return #C1;
static method test6() → () → self::A
- return self::A::•;
+ return #C1;
static method test7() → () → self::B<core::String>
- return self::B::•<core::String>;
+ return #C4;
static method test8() → () → self::B<core::String>
- return self::B::•<core::String>;
+ return #C4;
static method test9() → () → self::B<core::num>
return let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:33:30: Error: A value of type 'B<String> Function()' can't be returned from a function with return type 'B<num> Function()'.
- 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
B<num> Function() test9() => DB1.new; // Error.
- ^" in (self::B::•<core::String>) as{TypeError,ForNonNullableByDefault} () → self::B<core::num>;
+ ^" in (#C4) as{TypeError,ForNonNullableByDefault} () → self::B<core::num>;
static method test10() → () → self::B<core::String>
- return self::B::foo<core::String>;
+ return #C6;
static method test11() → () → self::B<core::String>
- return self::B::bar<core::String>;
+ return #C8;
static method test12() → () → self::B<core::num>
- return self::B::•<core::num>;
+ return #C9;
static method test13() → () → self::B<core::num>
- return self::B::foo<core::num>;
+ return #C10;
static method test14() → () → self::B<core::num>
- return self::B::bar<core::num>;
+ return #C11;
static method test15() → () → self::B<core::num>
- return self::B::•<core::num>;
+ return #C9;
static method test16() → <Y extends core::num = dynamic>() → self::B<Y>
- return let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:41:44: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y extends num>()'.
- - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-B<Y> Function<Y extends num>() test16() => DB2.new; // Ok.
- ^" in (self::B::•<core::num>) as{TypeError,ForNonNullableByDefault} <Y extends core::num = dynamic>() → self::B<Y>;
+ return #C12;
static method test17() → <Y extends core::Object? = dynamic>() → self::B<Y%>
- return let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y>()'.
+ return let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<X> Function<X extends num>()' can't be returned from a function with return type 'B<Y> Function<Y>()'.
- 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
B<Y> Function<Y>() test17() => DB2.new; // Error.
- ^" in (self::B::•<core::num>) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic>() → self::B<Y%>;
+ ^" in (let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<X> Function<X extends num>()' can't be assigned to a variable of type 'B<Y> Function<Y>()'.
+ - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
+B<Y> Function<Y>() test17() => DB2.new; // Error.
+ ^" in (#C12) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic>() → self::B<Y%>) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic>() → self::B<Y%>;
static method test18() → () → self::B<core::num>
- return self::B::•<core::num>;
+ return #C9;
static method test19() → () → self::B<core::num>
- return self::B::foo<core::num>;
+ return #C10;
static method test20() → () → self::B<core::num>
- return self::B::bar<core::num>;
+ return #C11;
static method test21() → () → self::B<core::num>
- return self::B::•<core::num>;
+ return #C9;
static method test22() → <Y extends core::num = dynamic, Z extends core::String = dynamic>() → self::B<Y>
- return let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:48:62: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y extends num, Z extends String>()'.
- - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-B<Y> Function<Y extends num, Z extends String>() test22() => DB2.new; // Ok.
- ^" in (self::B::•<core::num>) as{TypeError,ForNonNullableByDefault} <Y extends core::num = dynamic, Z extends core::String = dynamic>() → self::B<Y>;
+ return #C13;
static method test23() → <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>
- return let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y, Z>()'.
+ return let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<X> Function<X extends num, Y extends String>()' can't be returned from a function with return type 'B<Y> Function<Y, Z>()'.
- 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-B<Y> Function<Y, Z>() test23() => DB2.new; // Error.
- ^" in (self::B::•<core::num>) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>;
+B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
+ ^" in (let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<X> Function<X extends num, Y extends String>()' can't be assigned to a variable of type 'B<Y> Function<Y, Z>()'.
+ - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
+B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
+ ^" in (#C13) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>;
+static method test24() → () → self::B<core::String>
+ return #C14;
static method main() → dynamic {}
+
+constants {
+ #C1 = constructor-tearoff self::A::•
+ #C2 = instantiation self::A::• <>
+ #C3 = constructor-tearoff self::B::•
+ #C4 = instantiation self::B::• <core::String*>
+ #C5 = constructor-tearoff self::B::foo
+ #C6 = instantiation self::B::foo <core::String*>
+ #C7 = static-tearoff self::B::bar
+ #C8 = instantiation self::B::bar <core::String*>
+ #C9 = instantiation self::B::• <core::num*>
+ #C10 = instantiation self::B::foo <core::num*>
+ #C11 = instantiation self::B::bar <core::num*>
+ #C12 = typedef-tearoff <X extends core::num>.(#C3<X>)
+ #C13 = typedef-tearoff <X extends core::num, unrelated Y extends core::String>.(#C3<X>)
+ #C14 = instantiation self::B::• <Never*>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.weak.outline.expect
index 7110e07..fda6d4f 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.weak.outline.expect
@@ -65,5 +65,7 @@
;
static method test23() → <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>
;
+static method test24() → () → self::B<core::String>
+ ;
static method main() → dynamic
;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.weak.transformed.expect
index 0a4373e..86a1666 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart.weak.transformed.expect
@@ -15,24 +15,24 @@
// B<num> Function() test9() => DB1.new; // Error.
// ^
//
-// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:41:44: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y extends num>()'.
-// - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-// B<Y> Function<Y extends num>() test16() => DB2.new; // Ok.
-// ^
-//
-// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y>()'.
+// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<X> Function<X extends num>()' can't be assigned to a variable of type 'B<Y> Function<Y>()'.
// - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
// B<Y> Function<Y>() test17() => DB2.new; // Error.
// ^
//
-// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:48:62: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y extends num, Z extends String>()'.
+// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<X> Function<X extends num>()' can't be returned from a function with return type 'B<Y> Function<Y>()'.
// - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-// B<Y> Function<Y extends num, Z extends String>() test22() => DB2.new; // Ok.
-// ^
+// B<Y> Function<Y>() test17() => DB2.new; // Error.
+// ^
//
-// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y, Z>()'.
+// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<X> Function<X extends num, Y extends String>()' can't be assigned to a variable of type 'B<Y> Function<Y, Z>()'.
// - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-// B<Y> Function<Y, Z>() test23() => DB2.new; // Error.
+// B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<X> Function<X extends num, Y extends String>()' can't be returned from a function with return type 'B<Y> Function<Y, Z>()'.
+// - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
+// B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
// ^
//
import self as self;
@@ -59,64 +59,83 @@
return new self::B::•<self::B::bar::X%>();
}
static method test1() → () → self::A
- return self::A::•;
+ return #C1;
static method test2() → () → self::A
- return self::A::•;
+ return #C1;
static method test3() → () → self::A
- return self::A::•;
+ return #C2;
static method test4() → () → self::A
- return self::A::•;
+ return #C2;
static method test5() → () → self::A
- return self::A::•;
+ return #C1;
static method test6() → () → self::A
- return self::A::•;
+ return #C1;
static method test7() → () → self::B<core::String>
- return self::B::•<core::String>;
+ return #C4;
static method test8() → () → self::B<core::String>
- return self::B::•<core::String>;
+ return #C4;
static method test9() → () → self::B<core::num>
return let final Never #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:33:30: Error: A value of type 'B<String> Function()' can't be returned from a function with return type 'B<num> Function()'.
- 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
B<num> Function() test9() => DB1.new; // Error.
- ^" in (self::B::•<core::String>) as{TypeError,ForNonNullableByDefault} () → self::B<core::num>;
+ ^" in (#C4) as{TypeError,ForNonNullableByDefault} () → self::B<core::num>;
static method test10() → () → self::B<core::String>
- return self::B::foo<core::String>;
+ return #C6;
static method test11() → () → self::B<core::String>
- return self::B::bar<core::String>;
+ return #C8;
static method test12() → () → self::B<core::num>
- return self::B::•<core::num>;
+ return #C9;
static method test13() → () → self::B<core::num>
- return self::B::foo<core::num>;
+ return #C10;
static method test14() → () → self::B<core::num>
- return self::B::bar<core::num>;
+ return #C11;
static method test15() → () → self::B<core::num>
- return self::B::•<core::num>;
+ return #C9;
static method test16() → <Y extends core::num = dynamic>() → self::B<Y>
- return let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:41:44: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y extends num>()'.
- - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-B<Y> Function<Y extends num>() test16() => DB2.new; // Ok.
- ^" in (self::B::•<core::num>) as{TypeError,ForNonNullableByDefault} <Y extends core::num = dynamic>() → self::B<Y>;
+ return #C12;
static method test17() → <Y extends core::Object? = dynamic>() → self::B<Y%>
- return let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y>()'.
+ return let final Never #t2 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<X> Function<X extends num>()' can't be returned from a function with return type 'B<Y> Function<Y>()'.
- 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
B<Y> Function<Y>() test17() => DB2.new; // Error.
- ^" in (self::B::•<core::num>) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic>() → self::B<Y%>;
+ ^" in let final Never #t3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:42:32: Error: A value of type 'B<X> Function<X extends num>()' can't be assigned to a variable of type 'B<Y> Function<Y>()'.
+ - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
+B<Y> Function<Y>() test17() => DB2.new; // Error.
+ ^" in (#C12) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic>() → self::B<Y%>;
static method test18() → () → self::B<core::num>
- return self::B::•<core::num>;
+ return #C9;
static method test19() → () → self::B<core::num>
- return self::B::foo<core::num>;
+ return #C10;
static method test20() → () → self::B<core::num>
- return self::B::bar<core::num>;
+ return #C11;
static method test21() → () → self::B<core::num>
- return self::B::•<core::num>;
+ return #C9;
static method test22() → <Y extends core::num = dynamic, Z extends core::String = dynamic>() → self::B<Y>
- return let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:48:62: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y extends num, Z extends String>()'.
- - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-B<Y> Function<Y extends num, Z extends String>() test22() => DB2.new; // Ok.
- ^" in (self::B::•<core::num>) as{TypeError,ForNonNullableByDefault} <Y extends core::num = dynamic, Z extends core::String = dynamic>() → self::B<Y>;
+ return #C13;
static method test23() → <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>
- return let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<num> Function()' can't be returned from a function with return type 'B<Y> Function<Y, Z>()'.
+ return let final Never #t4 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<X> Function<X extends num, Y extends String>()' can't be returned from a function with return type 'B<Y> Function<Y, Z>()'.
- 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
-B<Y> Function<Y, Z>() test23() => DB2.new; // Error.
- ^" in (self::B::•<core::num>) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>;
+B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
+ ^" in let final Never #t5 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart:49:35: Error: A value of type 'B<X> Function<X extends num, Y extends String>()' can't be assigned to a variable of type 'B<Y> Function<Y, Z>()'.
+ - 'B' is from 'pkg/front_end/testcases/constructor_tearoffs/typedef_tearoffs.dart'.
+B<Y> Function<Y, Z>() test23() => DB3.new; // Error.
+ ^" in (#C13) as{TypeError,ForNonNullableByDefault} <Y extends core::Object? = dynamic, Z extends core::Object? = dynamic>() → self::B<Y%>;
+static method test24() → () → self::B<core::String>
+ return #C14;
static method main() → dynamic {}
+
+constants {
+ #C1 = constructor-tearoff self::A::•
+ #C2 = instantiation self::A::• <>
+ #C3 = constructor-tearoff self::B::•
+ #C4 = instantiation self::B::• <core::String*>
+ #C5 = constructor-tearoff self::B::foo
+ #C6 = instantiation self::B::foo <core::String*>
+ #C7 = static-tearoff self::B::bar
+ #C8 = instantiation self::B::bar <core::String*>
+ #C9 = instantiation self::B::• <core::num*>
+ #C10 = instantiation self::B::foo <core::num*>
+ #C11 = instantiation self::B::bar <core::num*>
+ #C12 = typedef-tearoff <X extends core::num>.(#C3<X>)
+ #C13 = typedef-tearoff <X extends core::num, unrelated Y extends core::String>.(#C3<X>)
+ #C14 = instantiation self::B::• <Never*>
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart b/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart
index c8527be..5784e0a 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart
+++ b/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart
@@ -16,7 +16,7 @@
const C.new(this.x);
}
-class D extend C {
+class D extends C {
D(int x) : super.new(x * 2);
}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart.strong.expect
index 74eb491..50ef75f8 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart.strong.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart.strong.expect
@@ -1,142 +1,70 @@
library /*isNonNullableByDefault*/;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:6:5: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-// A.new();
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:7:38: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-// factory A.redirectingFactory() = A.new;
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:8:43: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-// factory A.redirectingFactoryChild() = B.new;
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:9:26: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-// A.redirecting() : this.new();
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:16:11: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-// const C.new(this.x);
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:19:9: Error: Expected 'extends' instead of this.
-// class D extend C {
-// ^^^^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:20:20: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-// D(int x) : super.new(x * 2);
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:7:36: Error: Redirection constructor target not found: 'A.new'
-// factory A.redirectingFactory() = A.new;
-// ^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:20:14: Error: Superclass has no constructor named 'Object.new'.
-// D(int x) : super.new(x * 2);
-// ^^^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:25:11: Error: Method not found: 'C.new'.
-// const C.new(1);
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:26:9: Error: Method not found: 'C.new'.
-// new C.new(1);
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:28:14: Error: Getter not found: 'new'.
-// var f1 = A.new;
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:30:14: Error: Getter not found: 'new'.
-// var f3 = C.new;
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:37:23: Error: Getter not found: 'new'.
-// A Function() g1 = A.new;
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:39:28: Error: Getter not found: 'new'.
-// C Function(int x) g3 = C.new;
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:12:7: Error: The superclass, 'A', has no unnamed constructor that takes no arguments.
-// class B extends A {}
-// ^
-//
import self as self;
import "dart:core" as core;
class A extends core::Object {
static final field dynamic _redirecting# = <dynamic>[self::A::redirectingFactory, self::A::redirectingFactoryChild]/*isLegacy*/;
- constructor new() → self::A
+ constructor •() → self::A
: super core::Object::•()
;
constructor redirecting() → self::A
- : this self::A::new()
+ : this self::A::•()
;
static factory redirectingFactory() → self::A
- let dynamic #redirecting_factory = "A.new" in invalid-expression;
+ let dynamic #redirecting_factory = self::A::• in invalid-expression;
static factory redirectingFactoryChild() → self::A
let dynamic #redirecting_factory = self::B::• in invalid-expression;
}
class B extends self::A {
synthetic constructor •() → self::B
- : invalid-initializer
+ : super self::A::•()
;
}
class C extends core::Object /*hasConstConstructor*/ {
final field core::int x;
- const constructor new(core::int x) → self::C
+ const constructor •(core::int x) → self::C
: self::C::x = x, super core::Object::•()
;
}
-class D extends core::Object {
+class D extends self::C {
constructor •(core::int x) → self::D
- : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:20:14: Error: Superclass has no constructor named 'Object.new'.
- D(int x) : super.new(x * 2);
- ^^^^^"
+ : super self::C::•(x.{core::num::*}(2){(core::num) → core::int})
;
}
static method test() → dynamic {
new self::D::•(1);
- invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:25:11: Error: Method not found: 'C.new'.
- const C.new(1);
- ^^^";
- invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:26:9: Error: Method not found: 'C.new'.
- new C.new(1);
- ^^^";
- dynamic f1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:28:14: Error: Getter not found: 'new'.
- var f1 = A.new;
- ^^^";
- () → self::B f2 = self::B::•;
- dynamic f3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:30:14: Error: Getter not found: 'new'.
- var f3 = C.new;
- ^^^";
- (core::int) → self::D f4 = self::D::•;
- f1{dynamic}.call();
+ #C2;
+ new self::C::•(1);
+ () → self::A f1 = #C3;
+ () → self::B f2 = #C4;
+ (core::int) → self::C f3 = #C5;
+ (core::int) → self::D f4 = #C6;
+ f1(){() → self::A};
f2(){() → self::B};
- f3{dynamic}.call(1);
+ f3(1){(core::int) → self::C};
f4(1){(core::int) → self::D};
- () → self::A g1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:37:23: Error: Getter not found: 'new'.
- A Function() g1 = A.new;
- ^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} () → self::A;
- () → self::B g2 = self::B::•;
- (core::int) → self::C g3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:39:28: Error: Getter not found: 'new'.
- C Function(int x) g3 = C.new;
- ^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} (core::int) → self::C;
- (core::int) → self::D g4 = self::D::•;
+ () → self::A g1 = #C3;
+ () → self::B g2 = #C4;
+ (core::int) → self::C g3 = #C5;
+ (core::int) → self::D g4 = #C6;
g1(){() → self::A};
g2(){() → self::B};
g3(1){(core::int) → self::C};
g4(1){(core::int) → self::D};
}
static method main() → dynamic {}
+
+constants {
+ #C1 = 1
+ #C2 = self::C {x:#C1}
+ #C3 = constructor-tearoff self::A::•
+ #C4 = constructor-tearoff self::B::•
+ #C5 = constructor-tearoff self::C::•
+ #C6 = constructor-tearoff self::D::•
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///unnamed_constructor.dart:
+- C. (from org-dartlang-testcase:///unnamed_constructor.dart:16:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart.strong.transformed.expect
index 5779400..44b6f22 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart.strong.transformed.expect
@@ -1,142 +1,70 @@
library /*isNonNullableByDefault*/;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:6:5: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-// A.new();
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:7:38: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-// factory A.redirectingFactory() = A.new;
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:8:43: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-// factory A.redirectingFactoryChild() = B.new;
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:9:26: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-// A.redirecting() : this.new();
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:16:11: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-// const C.new(this.x);
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:19:9: Error: Expected 'extends' instead of this.
-// class D extend C {
-// ^^^^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:20:20: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-// D(int x) : super.new(x * 2);
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:7:36: Error: Redirection constructor target not found: 'A.new'
-// factory A.redirectingFactory() = A.new;
-// ^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:20:14: Error: Superclass has no constructor named 'Object.new'.
-// D(int x) : super.new(x * 2);
-// ^^^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:25:11: Error: Method not found: 'C.new'.
-// const C.new(1);
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:26:9: Error: Method not found: 'C.new'.
-// new C.new(1);
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:28:14: Error: Getter not found: 'new'.
-// var f1 = A.new;
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:30:14: Error: Getter not found: 'new'.
-// var f3 = C.new;
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:37:23: Error: Getter not found: 'new'.
-// A Function() g1 = A.new;
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:39:28: Error: Getter not found: 'new'.
-// C Function(int x) g3 = C.new;
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:12:7: Error: The superclass, 'A', has no unnamed constructor that takes no arguments.
-// class B extends A {}
-// ^
-//
import self as self;
import "dart:core" as core;
class A extends core::Object {
static final field dynamic _redirecting# = <dynamic>[self::A::redirectingFactory, self::A::redirectingFactoryChild]/*isLegacy*/;
- constructor new() → self::A
+ constructor •() → self::A
: super core::Object::•()
;
constructor redirecting() → self::A
- : this self::A::new()
+ : this self::A::•()
;
static factory redirectingFactory() → self::A
- let core::String* #redirecting_factory = "A.new" in invalid-expression;
+ let Never #redirecting_factory = self::A::• in invalid-expression;
static factory redirectingFactoryChild() → self::A
let Never #redirecting_factory = self::B::• in invalid-expression;
}
class B extends self::A {
synthetic constructor •() → self::B
- : invalid-initializer
+ : super self::A::•()
;
}
class C extends core::Object /*hasConstConstructor*/ {
final field core::int x;
- const constructor new(core::int x) → self::C
+ const constructor •(core::int x) → self::C
: self::C::x = x, super core::Object::•()
;
}
-class D extends core::Object {
+class D extends self::C {
constructor •(core::int x) → self::D
- : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:20:14: Error: Superclass has no constructor named 'Object.new'.
- D(int x) : super.new(x * 2);
- ^^^^^"
+ : super self::C::•(x.{core::num::*}(2){(core::num) → core::int})
;
}
static method test() → dynamic {
new self::D::•(1);
- invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:25:11: Error: Method not found: 'C.new'.
- const C.new(1);
- ^^^";
- invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:26:9: Error: Method not found: 'C.new'.
- new C.new(1);
- ^^^";
- dynamic f1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:28:14: Error: Getter not found: 'new'.
- var f1 = A.new;
- ^^^";
- () → self::B f2 = self::B::•;
- dynamic f3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:30:14: Error: Getter not found: 'new'.
- var f3 = C.new;
- ^^^";
- (core::int) → self::D f4 = self::D::•;
- f1{dynamic}.call();
+ #C2;
+ new self::C::•(1);
+ () → self::A f1 = #C3;
+ () → self::B f2 = #C4;
+ (core::int) → self::C f3 = #C5;
+ (core::int) → self::D f4 = #C6;
+ f1(){() → self::A};
f2(){() → self::B};
- f3{dynamic}.call(1);
+ f3(1){(core::int) → self::C};
f4(1){(core::int) → self::D};
- () → self::A g1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:37:23: Error: Getter not found: 'new'.
- A Function() g1 = A.new;
- ^^^";
- () → self::B g2 = self::B::•;
- (core::int) → self::C g3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:39:28: Error: Getter not found: 'new'.
- C Function(int x) g3 = C.new;
- ^^^";
- (core::int) → self::D g4 = self::D::•;
+ () → self::A g1 = #C3;
+ () → self::B g2 = #C4;
+ (core::int) → self::C g3 = #C5;
+ (core::int) → self::D g4 = #C6;
g1(){() → self::A};
g2(){() → self::B};
g3(1){(core::int) → self::C};
g4(1){(core::int) → self::D};
}
static method main() → dynamic {}
+
+constants {
+ #C1 = 1
+ #C2 = self::C {x:#C1}
+ #C3 = constructor-tearoff self::A::•
+ #C4 = constructor-tearoff self::B::•
+ #C5 = constructor-tearoff self::C::•
+ #C6 = constructor-tearoff self::D::•
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///unnamed_constructor.dart:
+- C. (from org-dartlang-testcase:///unnamed_constructor.dart:16:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart.textual_outline.expect
index d70331c..3e34a96 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart.textual_outline.expect
@@ -9,7 +9,7 @@
final int x;
const C.new(this.x);
}
-class D extend C {
+class D extends C {
D(int x) : super.new(x * 2);
}
test() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart.weak.expect
index 74eb491..50ef75f8 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart.weak.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart.weak.expect
@@ -1,142 +1,70 @@
library /*isNonNullableByDefault*/;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:6:5: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-// A.new();
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:7:38: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-// factory A.redirectingFactory() = A.new;
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:8:43: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-// factory A.redirectingFactoryChild() = B.new;
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:9:26: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-// A.redirecting() : this.new();
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:16:11: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-// const C.new(this.x);
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:19:9: Error: Expected 'extends' instead of this.
-// class D extend C {
-// ^^^^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:20:20: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-// D(int x) : super.new(x * 2);
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:7:36: Error: Redirection constructor target not found: 'A.new'
-// factory A.redirectingFactory() = A.new;
-// ^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:20:14: Error: Superclass has no constructor named 'Object.new'.
-// D(int x) : super.new(x * 2);
-// ^^^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:25:11: Error: Method not found: 'C.new'.
-// const C.new(1);
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:26:9: Error: Method not found: 'C.new'.
-// new C.new(1);
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:28:14: Error: Getter not found: 'new'.
-// var f1 = A.new;
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:30:14: Error: Getter not found: 'new'.
-// var f3 = C.new;
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:37:23: Error: Getter not found: 'new'.
-// A Function() g1 = A.new;
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:39:28: Error: Getter not found: 'new'.
-// C Function(int x) g3 = C.new;
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:12:7: Error: The superclass, 'A', has no unnamed constructor that takes no arguments.
-// class B extends A {}
-// ^
-//
import self as self;
import "dart:core" as core;
class A extends core::Object {
static final field dynamic _redirecting# = <dynamic>[self::A::redirectingFactory, self::A::redirectingFactoryChild]/*isLegacy*/;
- constructor new() → self::A
+ constructor •() → self::A
: super core::Object::•()
;
constructor redirecting() → self::A
- : this self::A::new()
+ : this self::A::•()
;
static factory redirectingFactory() → self::A
- let dynamic #redirecting_factory = "A.new" in invalid-expression;
+ let dynamic #redirecting_factory = self::A::• in invalid-expression;
static factory redirectingFactoryChild() → self::A
let dynamic #redirecting_factory = self::B::• in invalid-expression;
}
class B extends self::A {
synthetic constructor •() → self::B
- : invalid-initializer
+ : super self::A::•()
;
}
class C extends core::Object /*hasConstConstructor*/ {
final field core::int x;
- const constructor new(core::int x) → self::C
+ const constructor •(core::int x) → self::C
: self::C::x = x, super core::Object::•()
;
}
-class D extends core::Object {
+class D extends self::C {
constructor •(core::int x) → self::D
- : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:20:14: Error: Superclass has no constructor named 'Object.new'.
- D(int x) : super.new(x * 2);
- ^^^^^"
+ : super self::C::•(x.{core::num::*}(2){(core::num) → core::int})
;
}
static method test() → dynamic {
new self::D::•(1);
- invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:25:11: Error: Method not found: 'C.new'.
- const C.new(1);
- ^^^";
- invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:26:9: Error: Method not found: 'C.new'.
- new C.new(1);
- ^^^";
- dynamic f1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:28:14: Error: Getter not found: 'new'.
- var f1 = A.new;
- ^^^";
- () → self::B f2 = self::B::•;
- dynamic f3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:30:14: Error: Getter not found: 'new'.
- var f3 = C.new;
- ^^^";
- (core::int) → self::D f4 = self::D::•;
- f1{dynamic}.call();
+ #C2;
+ new self::C::•(1);
+ () → self::A f1 = #C3;
+ () → self::B f2 = #C4;
+ (core::int) → self::C f3 = #C5;
+ (core::int) → self::D f4 = #C6;
+ f1(){() → self::A};
f2(){() → self::B};
- f3{dynamic}.call(1);
+ f3(1){(core::int) → self::C};
f4(1){(core::int) → self::D};
- () → self::A g1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:37:23: Error: Getter not found: 'new'.
- A Function() g1 = A.new;
- ^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} () → self::A;
- () → self::B g2 = self::B::•;
- (core::int) → self::C g3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:39:28: Error: Getter not found: 'new'.
- C Function(int x) g3 = C.new;
- ^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} (core::int) → self::C;
- (core::int) → self::D g4 = self::D::•;
+ () → self::A g1 = #C3;
+ () → self::B g2 = #C4;
+ (core::int) → self::C g3 = #C5;
+ (core::int) → self::D g4 = #C6;
g1(){() → self::A};
g2(){() → self::B};
g3(1){(core::int) → self::C};
g4(1){(core::int) → self::D};
}
static method main() → dynamic {}
+
+constants {
+ #C1 = 1
+ #C2 = self::C {x:#C1}
+ #C3 = constructor-tearoff self::A::•
+ #C4 = constructor-tearoff self::B::•
+ #C5 = constructor-tearoff self::C::•
+ #C6 = constructor-tearoff self::D::•
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///unnamed_constructor.dart:
+- C. (from org-dartlang-testcase:///unnamed_constructor.dart:16:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart.weak.outline.expect
index aa40cc6..b0b2882 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart.weak.outline.expect
@@ -1,56 +1,15 @@
library /*isNonNullableByDefault*/;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:6:5: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-// A.new();
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:7:38: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-// factory A.redirectingFactory() = A.new;
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:8:43: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-// factory A.redirectingFactoryChild() = B.new;
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:9:26: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-// A.redirecting() : this.new();
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:16:11: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-// const C.new(this.x);
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:19:9: Error: Expected 'extends' instead of this.
-// class D extend C {
-// ^^^^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:20:20: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-// D(int x) : super.new(x * 2);
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:7:36: Error: Redirection constructor target not found: 'A.new'
-// factory A.redirectingFactory() = A.new;
-// ^
-//
import self as self;
import "dart:core" as core;
class A extends core::Object {
static final field dynamic _redirecting# = <dynamic>[self::A::redirectingFactory, self::A::redirectingFactoryChild]/*isLegacy*/;
- constructor new() → self::A
+ constructor •() → self::A
;
constructor redirecting() → self::A
;
static factory redirectingFactory() → self::A
- let dynamic #redirecting_factory = "A.new" in invalid-expression;
+ let dynamic #redirecting_factory = self::A::• in invalid-expression;
static factory redirectingFactoryChild() → self::A
let dynamic #redirecting_factory = self::B::• in invalid-expression;
}
@@ -60,11 +19,11 @@
}
class C extends core::Object /*hasConstConstructor*/ {
final field core::int x;
- const constructor new(core::int x) → self::C
+ const constructor •(core::int x) → self::C
: self::C::x = x, super core::Object::•()
;
}
-class D extends core::Object {
+class D extends self::C {
constructor •(core::int x) → self::D
;
}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart.weak.transformed.expect
index 5779400..44b6f22 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart.weak.transformed.expect
@@ -1,142 +1,70 @@
library /*isNonNullableByDefault*/;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:6:5: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-// A.new();
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:7:38: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-// factory A.redirectingFactory() = A.new;
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:8:43: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-// factory A.redirectingFactoryChild() = B.new;
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:9:26: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-// A.redirecting() : this.new();
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:16:11: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-// const C.new(this.x);
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:19:9: Error: Expected 'extends' instead of this.
-// class D extend C {
-// ^^^^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:20:20: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
-// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
-// D(int x) : super.new(x * 2);
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:7:36: Error: Redirection constructor target not found: 'A.new'
-// factory A.redirectingFactory() = A.new;
-// ^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:20:14: Error: Superclass has no constructor named 'Object.new'.
-// D(int x) : super.new(x * 2);
-// ^^^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:25:11: Error: Method not found: 'C.new'.
-// const C.new(1);
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:26:9: Error: Method not found: 'C.new'.
-// new C.new(1);
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:28:14: Error: Getter not found: 'new'.
-// var f1 = A.new;
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:30:14: Error: Getter not found: 'new'.
-// var f3 = C.new;
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:37:23: Error: Getter not found: 'new'.
-// A Function() g1 = A.new;
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:39:28: Error: Getter not found: 'new'.
-// C Function(int x) g3 = C.new;
-// ^^^
-//
-// pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:12:7: Error: The superclass, 'A', has no unnamed constructor that takes no arguments.
-// class B extends A {}
-// ^
-//
import self as self;
import "dart:core" as core;
class A extends core::Object {
static final field dynamic _redirecting# = <dynamic>[self::A::redirectingFactory, self::A::redirectingFactoryChild]/*isLegacy*/;
- constructor new() → self::A
+ constructor •() → self::A
: super core::Object::•()
;
constructor redirecting() → self::A
- : this self::A::new()
+ : this self::A::•()
;
static factory redirectingFactory() → self::A
- let core::String* #redirecting_factory = "A.new" in invalid-expression;
+ let Never #redirecting_factory = self::A::• in invalid-expression;
static factory redirectingFactoryChild() → self::A
let Never #redirecting_factory = self::B::• in invalid-expression;
}
class B extends self::A {
synthetic constructor •() → self::B
- : invalid-initializer
+ : super self::A::•()
;
}
class C extends core::Object /*hasConstConstructor*/ {
final field core::int x;
- const constructor new(core::int x) → self::C
+ const constructor •(core::int x) → self::C
: self::C::x = x, super core::Object::•()
;
}
-class D extends core::Object {
+class D extends self::C {
constructor •(core::int x) → self::D
- : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:20:14: Error: Superclass has no constructor named 'Object.new'.
- D(int x) : super.new(x * 2);
- ^^^^^"
+ : super self::C::•(x.{core::num::*}(2){(core::num) → core::int})
;
}
static method test() → dynamic {
new self::D::•(1);
- invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:25:11: Error: Method not found: 'C.new'.
- const C.new(1);
- ^^^";
- invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:26:9: Error: Method not found: 'C.new'.
- new C.new(1);
- ^^^";
- dynamic f1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:28:14: Error: Getter not found: 'new'.
- var f1 = A.new;
- ^^^";
- () → self::B f2 = self::B::•;
- dynamic f3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:30:14: Error: Getter not found: 'new'.
- var f3 = C.new;
- ^^^";
- (core::int) → self::D f4 = self::D::•;
- f1{dynamic}.call();
+ #C2;
+ new self::C::•(1);
+ () → self::A f1 = #C3;
+ () → self::B f2 = #C4;
+ (core::int) → self::C f3 = #C5;
+ (core::int) → self::D f4 = #C6;
+ f1(){() → self::A};
f2(){() → self::B};
- f3{dynamic}.call(1);
+ f3(1){(core::int) → self::C};
f4(1){(core::int) → self::D};
- () → self::A g1 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:37:23: Error: Getter not found: 'new'.
- A Function() g1 = A.new;
- ^^^";
- () → self::B g2 = self::B::•;
- (core::int) → self::C g3 = invalid-expression "pkg/front_end/testcases/constructor_tearoffs/unnamed_constructor.dart:39:28: Error: Getter not found: 'new'.
- C Function(int x) g3 = C.new;
- ^^^";
- (core::int) → self::D g4 = self::D::•;
+ () → self::A g1 = #C3;
+ () → self::B g2 = #C4;
+ (core::int) → self::C g3 = #C5;
+ (core::int) → self::D g4 = #C6;
g1(){() → self::A};
g2(){() → self::B};
g3(1){(core::int) → self::C};
g4(1){(core::int) → self::D};
}
static method main() → dynamic {}
+
+constants {
+ #C1 = 1
+ #C2 = self::C {x:#C1}
+ #C3 = constructor-tearoff self::A::•
+ #C4 = constructor-tearoff self::B::•
+ #C5 = constructor-tearoff self::C::•
+ #C6 = constructor-tearoff self::D::•
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///unnamed_constructor.dart:
+- C. (from org-dartlang-testcase:///unnamed_constructor.dart:16:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/dart2js/instance_getter_invocation.dart.strong.expect b/pkg/front_end/testcases/dart2js/instance_getter_invocation.dart.strong.expect
index e29a84e..d463dc9 100644
--- a/pkg/front_end/testcases/dart2js/instance_getter_invocation.dart.strong.expect
+++ b/pkg/front_end/testcases/dart2js/instance_getter_invocation.dart.strong.expect
@@ -21,5 +21,5 @@
}
constants {
- #C1 = tearoff self::id
+ #C1 = static-tearoff self::id
}
diff --git a/pkg/front_end/testcases/dart2js/instance_getter_invocation.dart.strong.transformed.expect b/pkg/front_end/testcases/dart2js/instance_getter_invocation.dart.strong.transformed.expect
index 6a431a4..977003e 100644
--- a/pkg/front_end/testcases/dart2js/instance_getter_invocation.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/dart2js/instance_getter_invocation.dart.strong.transformed.expect
@@ -21,7 +21,7 @@
}
constants {
- #C1 = tearoff self::id
+ #C1 = static-tearoff self::id
}
Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/dart2js/instance_getter_invocation.dart.weak.expect b/pkg/front_end/testcases/dart2js/instance_getter_invocation.dart.weak.expect
index e29a84e..d463dc9 100644
--- a/pkg/front_end/testcases/dart2js/instance_getter_invocation.dart.weak.expect
+++ b/pkg/front_end/testcases/dart2js/instance_getter_invocation.dart.weak.expect
@@ -21,5 +21,5 @@
}
constants {
- #C1 = tearoff self::id
+ #C1 = static-tearoff self::id
}
diff --git a/pkg/front_end/testcases/dart2js/instance_getter_invocation.dart.weak.transformed.expect b/pkg/front_end/testcases/dart2js/instance_getter_invocation.dart.weak.transformed.expect
index 6a431a4..977003e 100644
--- a/pkg/front_end/testcases/dart2js/instance_getter_invocation.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/dart2js/instance_getter_invocation.dart.weak.transformed.expect
@@ -21,7 +21,7 @@
}
constants {
- #C1 = tearoff self::id
+ #C1 = static-tearoff self::id
}
Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/dartdevc/factory_patch/libraries.json b/pkg/front_end/testcases/dartdevc/factory_patch/libraries.json
new file mode 100644
index 0000000..154c73c
--- /dev/null
+++ b/pkg/front_end/testcases/dartdevc/factory_patch/libraries.json
@@ -0,0 +1,12 @@
+{
+ "none": {
+ "libraries": {
+ "test": {
+ "patches": [
+ "patch_lib.dart"
+ ],
+ "uri": "origin_lib.dart"
+ }
+ }
+ }
+}
diff --git a/tests/lib/js/extends_test/extends_with_es6_subtyping_test.dart b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart
similarity index 70%
copy from tests/lib/js/extends_test/extends_with_es6_subtyping_test.dart
copy to pkg/front_end/testcases/dartdevc/factory_patch/main.dart
index e6185da..8e6257c 100644
--- a/tests/lib/js/extends_test/extends_with_es6_subtyping_test.dart
+++ b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart
@@ -2,9 +2,9 @@
// 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.
-import 'extends_test_util.dart';
+import 'dart:test';
-void main() {
- setUpWithES6Syntax();
- testSubtyping();
+main() {
+ new Class.fact();
+ //const Class.redirect();
}
diff --git a/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.strong.expect b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.strong.expect
new file mode 100644
index 0000000..203b0cf
--- /dev/null
+++ b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.strong.expect
@@ -0,0 +1,36 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:test" as test;
+
+import "dart:test";
+
+static method main() → dynamic {
+ test::Class::fact();
+}
+
+library /*isNonNullableByDefault*/;
+import self as test;
+import "dart:_js_helper" as _js;
+import "dart:core" as core;
+
+import "dart:_js_helper";
+
+@#C1
+class Class extends core::Object {
+ final field core::bool defaultValue /* from org-dartlang-testcase:///patch_lib.dart */;
+ const constructor _internal({core::bool defaultValue = #C2}) → test::Class
+ : test::Class::defaultValue = defaultValue, super core::Object::•()
+ ;
+ @#C1
+ static factory /* from org-dartlang-testcase:///patch_lib.dart */ fact({core::bool defaultValue = #C3}) → test::Class
+ return new test::Class::_internal(defaultValue: defaultValue);
+ @#C1
+ static factory /* from org-dartlang-testcase:///patch_lib.dart */ constFact({core::bool defaultValue = #C3}) → test::Class
+ return throw "unsupported";
+}
+
+constants {
+ #C1 = _js::_Patch {}
+ #C2 = false
+ #C3 = true
+}
diff --git a/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.strong.transformed.expect b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.strong.transformed.expect
new file mode 100644
index 0000000..203b0cf
--- /dev/null
+++ b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.strong.transformed.expect
@@ -0,0 +1,36 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:test" as test;
+
+import "dart:test";
+
+static method main() → dynamic {
+ test::Class::fact();
+}
+
+library /*isNonNullableByDefault*/;
+import self as test;
+import "dart:_js_helper" as _js;
+import "dart:core" as core;
+
+import "dart:_js_helper";
+
+@#C1
+class Class extends core::Object {
+ final field core::bool defaultValue /* from org-dartlang-testcase:///patch_lib.dart */;
+ const constructor _internal({core::bool defaultValue = #C2}) → test::Class
+ : test::Class::defaultValue = defaultValue, super core::Object::•()
+ ;
+ @#C1
+ static factory /* from org-dartlang-testcase:///patch_lib.dart */ fact({core::bool defaultValue = #C3}) → test::Class
+ return new test::Class::_internal(defaultValue: defaultValue);
+ @#C1
+ static factory /* from org-dartlang-testcase:///patch_lib.dart */ constFact({core::bool defaultValue = #C3}) → test::Class
+ return throw "unsupported";
+}
+
+constants {
+ #C1 = _js::_Patch {}
+ #C2 = false
+ #C3 = true
+}
diff --git a/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.textual_outline.expect b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.textual_outline.expect
new file mode 100644
index 0000000..3c9c90e
--- /dev/null
+++ b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.textual_outline.expect
@@ -0,0 +1,3 @@
+import 'dart:test';
+
+main() {}
diff --git a/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..3c9c90e
--- /dev/null
+++ b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.textual_outline_modelled.expect
@@ -0,0 +1,3 @@
+import 'dart:test';
+
+main() {}
diff --git a/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.weak.expect b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.weak.expect
new file mode 100644
index 0000000..203b0cf
--- /dev/null
+++ b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.weak.expect
@@ -0,0 +1,36 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:test" as test;
+
+import "dart:test";
+
+static method main() → dynamic {
+ test::Class::fact();
+}
+
+library /*isNonNullableByDefault*/;
+import self as test;
+import "dart:_js_helper" as _js;
+import "dart:core" as core;
+
+import "dart:_js_helper";
+
+@#C1
+class Class extends core::Object {
+ final field core::bool defaultValue /* from org-dartlang-testcase:///patch_lib.dart */;
+ const constructor _internal({core::bool defaultValue = #C2}) → test::Class
+ : test::Class::defaultValue = defaultValue, super core::Object::•()
+ ;
+ @#C1
+ static factory /* from org-dartlang-testcase:///patch_lib.dart */ fact({core::bool defaultValue = #C3}) → test::Class
+ return new test::Class::_internal(defaultValue: defaultValue);
+ @#C1
+ static factory /* from org-dartlang-testcase:///patch_lib.dart */ constFact({core::bool defaultValue = #C3}) → test::Class
+ return throw "unsupported";
+}
+
+constants {
+ #C1 = _js::_Patch {}
+ #C2 = false
+ #C3 = true
+}
diff --git a/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.weak.outline.expect b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.weak.outline.expect
new file mode 100644
index 0000000..fe1495b
--- /dev/null
+++ b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.weak.outline.expect
@@ -0,0 +1,33 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+import "dart:test";
+
+static method main() → dynamic
+ ;
+
+library /*isNonNullableByDefault*/;
+import self as self2;
+import "dart:_js_helper" as _js;
+import "dart:core" as core;
+
+import "dart:_js_helper";
+
+@_js::patch
+class Class extends core::Object {
+ final field core::bool defaultValue /* from org-dartlang-testcase:///patch_lib.dart */;
+ const constructor _internal({core::bool defaultValue = false}) → self2::Class
+ : self2::Class::defaultValue = defaultValue, super core::Object::•()
+ ;
+ @_js::patch
+ external static factory fact({core::bool defaultValue}) → self2::Class;
+ @_js::patch
+ external static factory constFact({core::bool defaultValue = true}) → self2::Class;
+}
+
+
+Extra constant evaluation status:
+Evaluated: StaticGet @ org-dartlang-testcase:///origin_lib.dart:6:50 -> InstanceConstant(const _Patch{})
+Evaluated: StaticGet @ org-dartlang-testcase:///origin_lib.dart:8:28 -> InstanceConstant(const _Patch{})
+Evaluated: StaticGet @ (unknown position in org-dartlang-testcase:///origin_lib.dart) -> InstanceConstant(const _Patch{})
+Extra constant evaluation: evaluated: 4, effectively constant: 3
diff --git a/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.weak.transformed.expect b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.weak.transformed.expect
new file mode 100644
index 0000000..203b0cf
--- /dev/null
+++ b/pkg/front_end/testcases/dartdevc/factory_patch/main.dart.weak.transformed.expect
@@ -0,0 +1,36 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:test" as test;
+
+import "dart:test";
+
+static method main() → dynamic {
+ test::Class::fact();
+}
+
+library /*isNonNullableByDefault*/;
+import self as test;
+import "dart:_js_helper" as _js;
+import "dart:core" as core;
+
+import "dart:_js_helper";
+
+@#C1
+class Class extends core::Object {
+ final field core::bool defaultValue /* from org-dartlang-testcase:///patch_lib.dart */;
+ const constructor _internal({core::bool defaultValue = #C2}) → test::Class
+ : test::Class::defaultValue = defaultValue, super core::Object::•()
+ ;
+ @#C1
+ static factory /* from org-dartlang-testcase:///patch_lib.dart */ fact({core::bool defaultValue = #C3}) → test::Class
+ return new test::Class::_internal(defaultValue: defaultValue);
+ @#C1
+ static factory /* from org-dartlang-testcase:///patch_lib.dart */ constFact({core::bool defaultValue = #C3}) → test::Class
+ return throw "unsupported";
+}
+
+constants {
+ #C1 = _js::_Patch {}
+ #C2 = false
+ #C3 = true
+}
diff --git a/pkg/front_end/testcases/dartdevc/factory_patch/origin_lib.dart b/pkg/front_end/testcases/dartdevc/factory_patch/origin_lib.dart
new file mode 100644
index 0000000..e7895f2
--- /dev/null
+++ b/pkg/front_end/testcases/dartdevc/factory_patch/origin_lib.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2020, 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 Class {
+ external factory Class.fact({bool defaultValue: true});
+ external const factory Class.constFact({bool defaultValue: true});
+ //external const factory Class.redirect({bool defaultValue: true});
+}
diff --git a/pkg/front_end/testcases/dartdevc/factory_patch/patch_lib.dart b/pkg/front_end/testcases/dartdevc/factory_patch/patch_lib.dart
new file mode 100644
index 0000000..394388b
--- /dev/null
+++ b/pkg/front_end/testcases/dartdevc/factory_patch/patch_lib.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2020, 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.
+
+// ignore: import_internal_library
+import 'dart:_js_helper';
+
+@patch
+class Class {
+ final bool defaultValue;
+
+ const Class._internal({this.defaultValue: false});
+
+ @patch
+ factory Class.fact({bool defaultValue: true}) =>
+ new Class._internal(defaultValue: defaultValue);
+
+ @patch
+ factory Class.constFact({bool defaultValue: true}) => throw 'unsupported';
+
+ /*@patch
+ const factory Class.redirect({bool defaultValue: true}) =
+ this._internal(defaultValue: defaultValue);*/
+}
diff --git a/pkg/front_end/testcases/dartdevc/instance_getter_invocation.dart.strong.expect b/pkg/front_end/testcases/dartdevc/instance_getter_invocation.dart.strong.expect
index e29a84e..d463dc9 100644
--- a/pkg/front_end/testcases/dartdevc/instance_getter_invocation.dart.strong.expect
+++ b/pkg/front_end/testcases/dartdevc/instance_getter_invocation.dart.strong.expect
@@ -21,5 +21,5 @@
}
constants {
- #C1 = tearoff self::id
+ #C1 = static-tearoff self::id
}
diff --git a/pkg/front_end/testcases/dartdevc/instance_getter_invocation.dart.strong.transformed.expect b/pkg/front_end/testcases/dartdevc/instance_getter_invocation.dart.strong.transformed.expect
index 6a431a4..977003e 100644
--- a/pkg/front_end/testcases/dartdevc/instance_getter_invocation.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/dartdevc/instance_getter_invocation.dart.strong.transformed.expect
@@ -21,7 +21,7 @@
}
constants {
- #C1 = tearoff self::id
+ #C1 = static-tearoff self::id
}
Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/dartdevc/instance_getter_invocation.dart.weak.expect b/pkg/front_end/testcases/dartdevc/instance_getter_invocation.dart.weak.expect
index e29a84e..d463dc9 100644
--- a/pkg/front_end/testcases/dartdevc/instance_getter_invocation.dart.weak.expect
+++ b/pkg/front_end/testcases/dartdevc/instance_getter_invocation.dart.weak.expect
@@ -21,5 +21,5 @@
}
constants {
- #C1 = tearoff self::id
+ #C1 = static-tearoff self::id
}
diff --git a/pkg/front_end/testcases/dartdevc/instance_getter_invocation.dart.weak.transformed.expect b/pkg/front_end/testcases/dartdevc/instance_getter_invocation.dart.weak.transformed.expect
index 6a431a4..977003e 100644
--- a/pkg/front_end/testcases/dartdevc/instance_getter_invocation.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/dartdevc/instance_getter_invocation.dart.weak.transformed.expect
@@ -21,7 +21,7 @@
}
constants {
- #C1 = tearoff self::id
+ #C1 = static-tearoff self::id
}
Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/dartdevc/symbol.dart b/pkg/front_end/testcases/dartdevc/symbol.dart
new file mode 100644
index 0000000..e899102
--- /dev/null
+++ b/pkg/front_end/testcases/dartdevc/symbol.dart
@@ -0,0 +1,5 @@
+// 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.
+
+main() => const Symbol('a');
\ No newline at end of file
diff --git a/pkg/front_end/testcases/dartdevc/symbol.dart.strong.expect b/pkg/front_end/testcases/dartdevc/symbol.dart.strong.expect
new file mode 100644
index 0000000..d827f5b
--- /dev/null
+++ b/pkg/front_end/testcases/dartdevc/symbol.dart.strong.expect
@@ -0,0 +1,10 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:_internal" as _in;
+
+static method main() → dynamic
+ return #C1;
+
+constants {
+ #C1 = #a
+}
diff --git a/pkg/front_end/testcases/dartdevc/symbol.dart.strong.transformed.expect b/pkg/front_end/testcases/dartdevc/symbol.dart.strong.transformed.expect
new file mode 100644
index 0000000..d827f5b
--- /dev/null
+++ b/pkg/front_end/testcases/dartdevc/symbol.dart.strong.transformed.expect
@@ -0,0 +1,10 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:_internal" as _in;
+
+static method main() → dynamic
+ return #C1;
+
+constants {
+ #C1 = #a
+}
diff --git a/pkg/front_end/testcases/dartdevc/symbol.dart.textual_outline.expect b/pkg/front_end/testcases/dartdevc/symbol.dart.textual_outline.expect
new file mode 100644
index 0000000..3aa6646
--- /dev/null
+++ b/pkg/front_end/testcases/dartdevc/symbol.dart.textual_outline.expect
@@ -0,0 +1 @@
+main() => const Symbol('a');
diff --git a/pkg/front_end/testcases/dartdevc/symbol.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/dartdevc/symbol.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..3aa6646
--- /dev/null
+++ b/pkg/front_end/testcases/dartdevc/symbol.dart.textual_outline_modelled.expect
@@ -0,0 +1 @@
+main() => const Symbol('a');
diff --git a/pkg/front_end/testcases/dartdevc/symbol.dart.weak.expect b/pkg/front_end/testcases/dartdevc/symbol.dart.weak.expect
new file mode 100644
index 0000000..d827f5b
--- /dev/null
+++ b/pkg/front_end/testcases/dartdevc/symbol.dart.weak.expect
@@ -0,0 +1,10 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:_internal" as _in;
+
+static method main() → dynamic
+ return #C1;
+
+constants {
+ #C1 = #a
+}
diff --git a/pkg/front_end/testcases/dartdevc/symbol.dart.weak.outline.expect b/pkg/front_end/testcases/dartdevc/symbol.dart.weak.outline.expect
new file mode 100644
index 0000000..e2cba6b
--- /dev/null
+++ b/pkg/front_end/testcases/dartdevc/symbol.dart.weak.outline.expect
@@ -0,0 +1,5 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/dartdevc/symbol.dart.weak.transformed.expect b/pkg/front_end/testcases/dartdevc/symbol.dart.weak.transformed.expect
new file mode 100644
index 0000000..d827f5b
--- /dev/null
+++ b/pkg/front_end/testcases/dartdevc/symbol.dart.weak.transformed.expect
@@ -0,0 +1,10 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:_internal" as _in;
+
+static method main() → dynamic
+ return #C1;
+
+constants {
+ #C1 = #a
+}
diff --git a/pkg/front_end/testcases/extension_types/simple_show_hide.dart b/pkg/front_end/testcases/extension_types/simple_show_hide.dart
new file mode 100644
index 0000000..e64df54
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/simple_show_hide.dart
@@ -0,0 +1,41 @@
+// 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.
+
+extension E1 on int show num {}
+
+test1(E1 e1) {
+ e1.ceil(); // Ok.
+ e2.floor(); // Ok.
+ e1.isEven; // Error.
+}
+
+extension E2 on int show num hide ceil {}
+
+test2(E2 e2) {
+ e2.ceil(); // Error.
+ e2.floor(); // Ok.
+ e2.isEven; // Error.
+}
+
+extension E3 on int hide isEven {}
+
+test3(E3 e3) {
+ e3.isOdd; // Ok.
+ e3.isEven; // Error.
+}
+
+extension type MyInt on int show num, isEven hide floor {
+ int get twice => 2 * this;
+}
+
+test() {
+ MyInt m = 42;
+ m.twice; // OK, in the extension type.
+ m.isEven; // OK, a shown instance member.
+ m.ceil(); // OK, a shown instance member.
+ m.toString(); // OK, an `Object` member.
+ m.floor(); // Error, hidden.
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extension_types/simple_show_hide.dart.strong.expect b/pkg/front_end/testcases/extension_types/simple_show_hide.dart.strong.expect
new file mode 100644
index 0000000..d246aca
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/simple_show_hide.dart.strong.expect
@@ -0,0 +1,256 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:5:17: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension E1 on int show num {}
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:5:26: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension E1 on int show num {}
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:13:17: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension E2 on int show num hide ceil {}
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:13:26: Error: Expected ';' after this.
+// extension E2 on int show num hide ceil {}
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:13:26: Error: 'num' is already declared in this scope.
+// extension E2 on int show num hide ceil {}
+// ^^^
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:5:26: Context: Previous declaration of 'num'.
+// extension E1 on int show num {}
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:13:35: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension E2 on int show num hide ceil {}
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:21:17: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension E3 on int hide isEven {}
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:21:26: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension E3 on int hide isEven {}
+// ^^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:28:25: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension type MyInt on int show num, isEven hide floor {
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:28:39: Error: Expected ';' after this.
+// extension type MyInt on int show num, isEven hide floor {
+// ^^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:28:34: Error: 'num' is already declared in this scope.
+// extension type MyInt on int show num, isEven hide floor {
+// ^^^
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:13:26: Context: Previous declaration of 'num'.
+// extension E2 on int show num hide ceil {}
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:28:39: Error: 'isEven' is already declared in this scope.
+// extension type MyInt on int show num, isEven hide floor {
+// ^^^^^^
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:21:26: Context: Previous declaration of 'isEven'.
+// extension E3 on int hide isEven {}
+// ^^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:28:51: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension type MyInt on int show num, isEven hide floor {
+// ^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:5:21: Error: Type 'show' not found.
+// extension E1 on int show num {}
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:13:21: Error: Type 'show' not found.
+// extension E2 on int show num hide ceil {}
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:13:30: Error: Type 'hide' not found.
+// extension E2 on int show num hide ceil {}
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:21:21: Error: Type 'hide' not found.
+// extension E3 on int hide isEven {}
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:28:29: Error: Type 'show' not found.
+// extension type MyInt on int show num, isEven hide floor {
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:28:46: Error: Type 'hide' not found.
+// extension type MyInt on int show num, isEven hide floor {
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:9:3: Error: Getter not found: 'e2'.
+// e2.floor(); // Ok.
+// ^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:8:6: Error: The method 'ceil' isn't defined for the extension 'E1'.
+// Try correcting the name to the name of an existing method, or defining a method name 'ceil'.
+// e1.ceil(); // Ok.
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:10:6: Error: The getter 'isEven' isn't defined for the extension 'E1'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'isEven'.
+// e1.isEven; // Error.
+// ^^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:13:21: Error: 'show' isn't a type.
+// extension E2 on int show num hide ceil {}
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:16:6: Error: The method 'ceil' isn't defined for the extension 'E2'.
+// Try correcting the name to the name of an existing method, or defining a method name 'ceil'.
+// e2.ceil(); // Error.
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:17:6: Error: The method 'floor' isn't defined for the extension 'E2'.
+// Try correcting the name to the name of an existing method, or defining a method name 'floor'.
+// e2.floor(); // Ok.
+// ^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:18:6: Error: The getter 'isEven' isn't defined for the extension 'E2'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'isEven'.
+// e2.isEven; // Error.
+// ^^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:24:6: Error: The getter 'isOdd' isn't defined for the extension 'E3'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'isOdd'.
+// e3.isOdd; // Ok.
+// ^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:25:6: Error: The getter 'isEven' isn't defined for the extension 'E3'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'isEven'.
+// e3.isEven; // Error.
+// ^^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:28:29: Error: 'show' isn't a type.
+// extension type MyInt on int show num, isEven hide floor {
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:29:7: Error: Expected ';' after this.
+// int get twice => 2 * this;
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:29:17: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// int get twice => 2 * this;
+// ^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:29:24: Error: Expected identifier, but got 'this'.
+// int get twice => 2 * this;
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:34:5: Error: The getter 'twice' isn't defined for the extension 'MyInt'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'twice'.
+// m.twice; // OK, in the extension type.
+// ^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:35:5: Error: The getter 'isEven' isn't defined for the extension 'MyInt'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'isEven'.
+// m.isEven; // OK, a shown instance member.
+// ^^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:36:5: Error: The method 'ceil' isn't defined for the extension 'MyInt'.
+// Try correcting the name to the name of an existing method, or defining a method name 'ceil'.
+// m.ceil(); // OK, a shown instance member.
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:38:5: Error: The method 'floor' isn't defined for the extension 'MyInt'.
+// Try correcting the name to the name of an existing method, or defining a method name 'floor'.
+// m.floor(); // Error, hidden.
+// ^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+extension E1 on core::int {
+}
+extension E2 on core::int {
+}
+extension E3 on core::int {
+}
+extension type MyInt on core::int {
+}
+static method num() → invalid-type {}
+static method test1(self::E1 e1) → dynamic {
+ invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide.dart:8:6: Error: The method 'ceil' isn't defined for the extension 'E1'.
+Try correcting the name to the name of an existing method, or defining a method name 'ceil'.
+ e1.ceil(); // Ok.
+ ^^^^";
+ invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide.dart:9:3: Error: Getter not found: 'e2'.
+ e2.floor(); // Ok.
+ ^^"{dynamic}.floor();
+ invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide.dart:10:6: Error: The getter 'isEven' isn't defined for the extension 'E1'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'isEven'.
+ e1.isEven; // Error.
+ ^^^^^^";
+}
+static method ceil() → invalid-type {}
+static method test2(self::E2 e2) → dynamic {
+ invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide.dart:16:6: Error: The method 'ceil' isn't defined for the extension 'E2'.
+Try correcting the name to the name of an existing method, or defining a method name 'ceil'.
+ e2.ceil(); // Error.
+ ^^^^";
+ invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide.dart:17:6: Error: The method 'floor' isn't defined for the extension 'E2'.
+Try correcting the name to the name of an existing method, or defining a method name 'floor'.
+ e2.floor(); // Ok.
+ ^^^^^";
+ invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide.dart:18:6: Error: The getter 'isEven' isn't defined for the extension 'E2'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'isEven'.
+ e2.isEven; // Error.
+ ^^^^^^";
+}
+static method isEven() → invalid-type {}
+static method test3(self::E3 e3) → dynamic {
+ invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide.dart:24:6: Error: The getter 'isOdd' isn't defined for the extension 'E3'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'isOdd'.
+ e3.isOdd; // Ok.
+ ^^^^^";
+ invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide.dart:25:6: Error: The getter 'isEven' isn't defined for the extension 'E3'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'isEven'.
+ e3.isEven; // Error.
+ ^^^^^^";
+}
+static method floor() → invalid-type {
+ core::int get;
+ function twice() → core::num
+ return 2.{core::num::*}(invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide.dart:29:24: Error: Expected identifier, but got 'this'.
+ int get twice => 2 * this;
+ ^^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} core::num){(core::num) → core::num};
+}
+static method test() → dynamic {
+ self::MyInt m = 42;
+ invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide.dart:34:5: Error: The getter 'twice' isn't defined for the extension 'MyInt'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'twice'.
+ m.twice; // OK, in the extension type.
+ ^^^^^";
+ invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide.dart:35:5: Error: The getter 'isEven' isn't defined for the extension 'MyInt'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'isEven'.
+ m.isEven; // OK, a shown instance member.
+ ^^^^^^";
+ invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide.dart:36:5: Error: The method 'ceil' isn't defined for the extension 'MyInt'.
+Try correcting the name to the name of an existing method, or defining a method name 'ceil'.
+ m.ceil(); // OK, a shown instance member.
+ ^^^^";
+ m.{core::Object::toString}(){() → core::String};
+ invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide.dart:38:5: Error: The method 'floor' isn't defined for the extension 'MyInt'.
+Try correcting the name to the name of an existing method, or defining a method name 'floor'.
+ m.floor(); // Error, hidden.
+ ^^^^^";
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/extension_types/simple_show_hide.dart.textual_outline.expect b/pkg/front_end/testcases/extension_types/simple_show_hide.dart.textual_outline.expect
new file mode 100644
index 0000000..6296476
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/simple_show_hide.dart.textual_outline.expect
@@ -0,0 +1,15 @@
+extension E1 on int {}
+show num (){}
+test1(E1 e1) {}
+extension E2 on int {}
+show num ;
+hide ceil (){}
+test2(E2 e2) {}
+extension E3 on int {}
+hide isEven (){}
+test3(E3 e3) {}
+extension type MyInt on int {}
+show num, isEven ;
+hide floor (){}
+test() {}
+main() {}
diff --git a/pkg/front_end/testcases/extension_types/simple_show_hide.dart.weak.expect b/pkg/front_end/testcases/extension_types/simple_show_hide.dart.weak.expect
new file mode 100644
index 0000000..d246aca
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/simple_show_hide.dart.weak.expect
@@ -0,0 +1,256 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:5:17: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension E1 on int show num {}
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:5:26: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension E1 on int show num {}
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:13:17: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension E2 on int show num hide ceil {}
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:13:26: Error: Expected ';' after this.
+// extension E2 on int show num hide ceil {}
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:13:26: Error: 'num' is already declared in this scope.
+// extension E2 on int show num hide ceil {}
+// ^^^
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:5:26: Context: Previous declaration of 'num'.
+// extension E1 on int show num {}
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:13:35: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension E2 on int show num hide ceil {}
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:21:17: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension E3 on int hide isEven {}
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:21:26: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension E3 on int hide isEven {}
+// ^^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:28:25: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension type MyInt on int show num, isEven hide floor {
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:28:39: Error: Expected ';' after this.
+// extension type MyInt on int show num, isEven hide floor {
+// ^^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:28:34: Error: 'num' is already declared in this scope.
+// extension type MyInt on int show num, isEven hide floor {
+// ^^^
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:13:26: Context: Previous declaration of 'num'.
+// extension E2 on int show num hide ceil {}
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:28:39: Error: 'isEven' is already declared in this scope.
+// extension type MyInt on int show num, isEven hide floor {
+// ^^^^^^
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:21:26: Context: Previous declaration of 'isEven'.
+// extension E3 on int hide isEven {}
+// ^^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:28:51: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension type MyInt on int show num, isEven hide floor {
+// ^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:5:21: Error: Type 'show' not found.
+// extension E1 on int show num {}
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:13:21: Error: Type 'show' not found.
+// extension E2 on int show num hide ceil {}
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:13:30: Error: Type 'hide' not found.
+// extension E2 on int show num hide ceil {}
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:21:21: Error: Type 'hide' not found.
+// extension E3 on int hide isEven {}
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:28:29: Error: Type 'show' not found.
+// extension type MyInt on int show num, isEven hide floor {
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:28:46: Error: Type 'hide' not found.
+// extension type MyInt on int show num, isEven hide floor {
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:9:3: Error: Getter not found: 'e2'.
+// e2.floor(); // Ok.
+// ^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:8:6: Error: The method 'ceil' isn't defined for the extension 'E1'.
+// Try correcting the name to the name of an existing method, or defining a method name 'ceil'.
+// e1.ceil(); // Ok.
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:10:6: Error: The getter 'isEven' isn't defined for the extension 'E1'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'isEven'.
+// e1.isEven; // Error.
+// ^^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:13:21: Error: 'show' isn't a type.
+// extension E2 on int show num hide ceil {}
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:16:6: Error: The method 'ceil' isn't defined for the extension 'E2'.
+// Try correcting the name to the name of an existing method, or defining a method name 'ceil'.
+// e2.ceil(); // Error.
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:17:6: Error: The method 'floor' isn't defined for the extension 'E2'.
+// Try correcting the name to the name of an existing method, or defining a method name 'floor'.
+// e2.floor(); // Ok.
+// ^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:18:6: Error: The getter 'isEven' isn't defined for the extension 'E2'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'isEven'.
+// e2.isEven; // Error.
+// ^^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:24:6: Error: The getter 'isOdd' isn't defined for the extension 'E3'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'isOdd'.
+// e3.isOdd; // Ok.
+// ^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:25:6: Error: The getter 'isEven' isn't defined for the extension 'E3'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'isEven'.
+// e3.isEven; // Error.
+// ^^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:28:29: Error: 'show' isn't a type.
+// extension type MyInt on int show num, isEven hide floor {
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:29:7: Error: Expected ';' after this.
+// int get twice => 2 * this;
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:29:17: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// int get twice => 2 * this;
+// ^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:29:24: Error: Expected identifier, but got 'this'.
+// int get twice => 2 * this;
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:34:5: Error: The getter 'twice' isn't defined for the extension 'MyInt'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'twice'.
+// m.twice; // OK, in the extension type.
+// ^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:35:5: Error: The getter 'isEven' isn't defined for the extension 'MyInt'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'isEven'.
+// m.isEven; // OK, a shown instance member.
+// ^^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:36:5: Error: The method 'ceil' isn't defined for the extension 'MyInt'.
+// Try correcting the name to the name of an existing method, or defining a method name 'ceil'.
+// m.ceil(); // OK, a shown instance member.
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:38:5: Error: The method 'floor' isn't defined for the extension 'MyInt'.
+// Try correcting the name to the name of an existing method, or defining a method name 'floor'.
+// m.floor(); // Error, hidden.
+// ^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+extension E1 on core::int {
+}
+extension E2 on core::int {
+}
+extension E3 on core::int {
+}
+extension type MyInt on core::int {
+}
+static method num() → invalid-type {}
+static method test1(self::E1 e1) → dynamic {
+ invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide.dart:8:6: Error: The method 'ceil' isn't defined for the extension 'E1'.
+Try correcting the name to the name of an existing method, or defining a method name 'ceil'.
+ e1.ceil(); // Ok.
+ ^^^^";
+ invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide.dart:9:3: Error: Getter not found: 'e2'.
+ e2.floor(); // Ok.
+ ^^"{dynamic}.floor();
+ invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide.dart:10:6: Error: The getter 'isEven' isn't defined for the extension 'E1'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'isEven'.
+ e1.isEven; // Error.
+ ^^^^^^";
+}
+static method ceil() → invalid-type {}
+static method test2(self::E2 e2) → dynamic {
+ invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide.dart:16:6: Error: The method 'ceil' isn't defined for the extension 'E2'.
+Try correcting the name to the name of an existing method, or defining a method name 'ceil'.
+ e2.ceil(); // Error.
+ ^^^^";
+ invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide.dart:17:6: Error: The method 'floor' isn't defined for the extension 'E2'.
+Try correcting the name to the name of an existing method, or defining a method name 'floor'.
+ e2.floor(); // Ok.
+ ^^^^^";
+ invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide.dart:18:6: Error: The getter 'isEven' isn't defined for the extension 'E2'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'isEven'.
+ e2.isEven; // Error.
+ ^^^^^^";
+}
+static method isEven() → invalid-type {}
+static method test3(self::E3 e3) → dynamic {
+ invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide.dart:24:6: Error: The getter 'isOdd' isn't defined for the extension 'E3'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'isOdd'.
+ e3.isOdd; // Ok.
+ ^^^^^";
+ invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide.dart:25:6: Error: The getter 'isEven' isn't defined for the extension 'E3'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'isEven'.
+ e3.isEven; // Error.
+ ^^^^^^";
+}
+static method floor() → invalid-type {
+ core::int get;
+ function twice() → core::num
+ return 2.{core::num::*}(invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide.dart:29:24: Error: Expected identifier, but got 'this'.
+ int get twice => 2 * this;
+ ^^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} core::num){(core::num) → core::num};
+}
+static method test() → dynamic {
+ self::MyInt m = 42;
+ invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide.dart:34:5: Error: The getter 'twice' isn't defined for the extension 'MyInt'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'twice'.
+ m.twice; // OK, in the extension type.
+ ^^^^^";
+ invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide.dart:35:5: Error: The getter 'isEven' isn't defined for the extension 'MyInt'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'isEven'.
+ m.isEven; // OK, a shown instance member.
+ ^^^^^^";
+ invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide.dart:36:5: Error: The method 'ceil' isn't defined for the extension 'MyInt'.
+Try correcting the name to the name of an existing method, or defining a method name 'ceil'.
+ m.ceil(); // OK, a shown instance member.
+ ^^^^";
+ m.{core::Object::toString}(){() → core::String};
+ invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide.dart:38:5: Error: The method 'floor' isn't defined for the extension 'MyInt'.
+Try correcting the name to the name of an existing method, or defining a method name 'floor'.
+ m.floor(); // Error, hidden.
+ ^^^^^";
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/extension_types/simple_show_hide.dart.weak.outline.expect b/pkg/front_end/testcases/extension_types/simple_show_hide.dart.weak.outline.expect
new file mode 100644
index 0000000..7a2b050
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/simple_show_hide.dart.weak.outline.expect
@@ -0,0 +1,126 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:5:17: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension E1 on int show num {}
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:5:26: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension E1 on int show num {}
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:13:17: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension E2 on int show num hide ceil {}
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:13:26: Error: Expected ';' after this.
+// extension E2 on int show num hide ceil {}
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:13:26: Error: 'num' is already declared in this scope.
+// extension E2 on int show num hide ceil {}
+// ^^^
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:5:26: Context: Previous declaration of 'num'.
+// extension E1 on int show num {}
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:13:35: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension E2 on int show num hide ceil {}
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:21:17: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension E3 on int hide isEven {}
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:21:26: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension E3 on int hide isEven {}
+// ^^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:28:25: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension type MyInt on int show num, isEven hide floor {
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:28:39: Error: Expected ';' after this.
+// extension type MyInt on int show num, isEven hide floor {
+// ^^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:28:34: Error: 'num' is already declared in this scope.
+// extension type MyInt on int show num, isEven hide floor {
+// ^^^
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:13:26: Context: Previous declaration of 'num'.
+// extension E2 on int show num hide ceil {}
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:28:39: Error: 'isEven' is already declared in this scope.
+// extension type MyInt on int show num, isEven hide floor {
+// ^^^^^^
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:21:26: Context: Previous declaration of 'isEven'.
+// extension E3 on int hide isEven {}
+// ^^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:28:51: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension type MyInt on int show num, isEven hide floor {
+// ^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:5:21: Error: Type 'show' not found.
+// extension E1 on int show num {}
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:13:21: Error: Type 'show' not found.
+// extension E2 on int show num hide ceil {}
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:13:30: Error: Type 'hide' not found.
+// extension E2 on int show num hide ceil {}
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:21:21: Error: Type 'hide' not found.
+// extension E3 on int hide isEven {}
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:28:29: Error: Type 'show' not found.
+// extension type MyInt on int show num, isEven hide floor {
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide.dart:28:46: Error: Type 'hide' not found.
+// extension type MyInt on int show num, isEven hide floor {
+// ^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+extension E1 on core::int {
+}
+extension E2 on core::int {
+}
+extension E3 on core::int {
+}
+extension type MyInt on core::int {
+}
+static method num() → invalid-type
+ ;
+static method test1(self::E1 e1) → dynamic
+ ;
+static method ceil() → invalid-type
+ ;
+static method test2(self::E2 e2) → dynamic
+ ;
+static method isEven() → invalid-type
+ ;
+static method test3(self::E3 e3) → dynamic
+ ;
+static method floor() → invalid-type
+ ;
+static method test() → dynamic
+ ;
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart b/pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart
new file mode 100644
index 0000000..7f5ac0d
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart
@@ -0,0 +1,20 @@
+// 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.
+
+extension E1 on int show num {
+ int ceil() {} // Error.
+}
+
+extension E2 on int show num hide ceil {
+ int ceil() {} // Ok.
+ int floor() {} // Error.
+}
+
+extension E3 on int hide isEven {
+ // `on int hide isEven` means `on int show int hide isEven`.
+ bool get isOdd => throw 42; // Error.
+ bool get isEven => throw 42; // Ok.
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart.strong.expect b/pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart.strong.expect
new file mode 100644
index 0000000..6d68160
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart.strong.expect
@@ -0,0 +1,141 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:5:17: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension E1 on int show num {
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:5:26: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension E1 on int show num {
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:17: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension E2 on int show num hide ceil {
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:26: Error: Expected ';' after this.
+// extension E2 on int show num hide ceil {
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:26: Error: 'num' is already declared in this scope.
+// extension E2 on int show num hide ceil {
+// ^^^
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:5:26: Context: Previous declaration of 'num'.
+// extension E1 on int show num {
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:35: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension E2 on int show num hide ceil {
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:14:17: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension E3 on int hide isEven {
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:14:26: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension E3 on int hide isEven {
+// ^^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:5:21: Error: Type 'show' not found.
+// extension E1 on int show num {
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:21: Error: Type 'show' not found.
+// extension E2 on int show num hide ceil {
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:30: Error: Type 'hide' not found.
+// extension E2 on int show num hide ceil {
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:14:21: Error: Type 'hide' not found.
+// extension E3 on int hide isEven {
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:6:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+// int ceil() {} // Error.
+// ^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:21: Error: 'show' isn't a type.
+// extension E2 on int show num hide ceil {
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:10:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+// int ceil() {} // Ok.
+// ^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:11:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+// int floor() {} // Error.
+// ^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:16:8: Error: Expected ';' after this.
+// bool get isOdd => throw 42; // Error.
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:16:18: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// bool get isOdd => throw 42; // Error.
+// ^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:17:8: Error: 'get' is already declared in this scope.
+// bool get isEven => throw 42; // Ok.
+// ^^^
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:16:8: Context: Previous declaration of 'get'.
+// bool get isOdd => throw 42; // Error.
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:17:8: Error: Expected ';' after this.
+// bool get isEven => throw 42; // Ok.
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:17:19: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// bool get isEven => throw 42; // Ok.
+// ^^
+//
+import self as self;
+import "dart:core" as core;
+
+extension E1 on core::int {
+}
+extension E2 on core::int {
+}
+extension E3 on core::int {
+}
+static method num() → invalid-type {
+ function ceil() → core::int {
+ return let final Never #t1 = invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:6:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+ int ceil() {} // Error.
+ ^" in null;
+ }
+}
+static method ceil() → invalid-type {
+ function ceil() → core::int {
+ return let final Never #t2 = invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:10:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+ int ceil() {} // Ok.
+ ^" in null;
+ }
+ function floor() → core::int {
+ return let final Never #t3 = invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:11:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+ int floor() {} // Error.
+ ^" in null;
+ }
+}
+static method isEven() → invalid-type {
+ core::bool get;
+ function isOdd() → Never
+ return throw 42;
+ core::bool get = invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:17:8: Error: 'get' is already declared in this scope.
+ bool get isEven => throw 42; // Ok.
+ ^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} core::bool;
+ function isEven() → Never
+ return throw 42;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart.strong.transformed.expect b/pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart.strong.transformed.expect
new file mode 100644
index 0000000..9fe722e
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart.strong.transformed.expect
@@ -0,0 +1,141 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:5:17: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension E1 on int show num {
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:5:26: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension E1 on int show num {
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:17: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension E2 on int show num hide ceil {
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:26: Error: Expected ';' after this.
+// extension E2 on int show num hide ceil {
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:26: Error: 'num' is already declared in this scope.
+// extension E2 on int show num hide ceil {
+// ^^^
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:5:26: Context: Previous declaration of 'num'.
+// extension E1 on int show num {
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:35: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension E2 on int show num hide ceil {
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:14:17: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension E3 on int hide isEven {
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:14:26: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension E3 on int hide isEven {
+// ^^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:5:21: Error: Type 'show' not found.
+// extension E1 on int show num {
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:21: Error: Type 'show' not found.
+// extension E2 on int show num hide ceil {
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:30: Error: Type 'hide' not found.
+// extension E2 on int show num hide ceil {
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:14:21: Error: Type 'hide' not found.
+// extension E3 on int hide isEven {
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:6:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+// int ceil() {} // Error.
+// ^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:21: Error: 'show' isn't a type.
+// extension E2 on int show num hide ceil {
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:10:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+// int ceil() {} // Ok.
+// ^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:11:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+// int floor() {} // Error.
+// ^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:16:8: Error: Expected ';' after this.
+// bool get isOdd => throw 42; // Error.
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:16:18: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// bool get isOdd => throw 42; // Error.
+// ^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:17:8: Error: 'get' is already declared in this scope.
+// bool get isEven => throw 42; // Ok.
+// ^^^
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:16:8: Context: Previous declaration of 'get'.
+// bool get isOdd => throw 42; // Error.
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:17:8: Error: Expected ';' after this.
+// bool get isEven => throw 42; // Ok.
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:17:19: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// bool get isEven => throw 42; // Ok.
+// ^^
+//
+import self as self;
+import "dart:core" as core;
+
+extension E1 on core::int {
+}
+extension E2 on core::int {
+}
+extension E3 on core::int {
+}
+static method num() → invalid-type {
+ function ceil() → core::int {
+ return let final Never #t1 = invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:6:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+ int ceil() {} // Error.
+ ^" in null;
+ }
+}
+static method ceil() → invalid-type {
+ function ceil() → core::int {
+ return let final Never #t2 = invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:10:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+ int ceil() {} // Ok.
+ ^" in null;
+ }
+ function floor() → core::int {
+ return let final Never #t3 = invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:11:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+ int floor() {} // Error.
+ ^" in null;
+ }
+}
+static method isEven() → invalid-type {
+ core::bool get;
+ function isOdd() → Never
+ return throw 42;
+ core::bool get = invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:17:8: Error: 'get' is already declared in this scope.
+ bool get isEven => throw 42; // Ok.
+ ^^^";
+ function isEven() → Never
+ return throw 42;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart.textual_outline.expect b/pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart.textual_outline.expect
new file mode 100644
index 0000000..b92215c
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart.textual_outline.expect
@@ -0,0 +1,13 @@
+extension E1 on int {}
+
+show num() {}
+
+extension E2 on int {}
+
+show num;
+hide ceil() {}
+
+extension E3 on int {}
+
+hide isEven() {}
+main() {}
diff --git a/pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..4d9e489
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart.textual_outline_modelled.expect
@@ -0,0 +1,11 @@
+extension E1 on int {}
+
+extension E2 on int {}
+
+extension E3 on int {}
+
+hide ceil() {}
+hide isEven() {}
+main() {}
+show num() {}
+show num;
diff --git a/pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart.weak.expect b/pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart.weak.expect
new file mode 100644
index 0000000..6d68160
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart.weak.expect
@@ -0,0 +1,141 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:5:17: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension E1 on int show num {
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:5:26: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension E1 on int show num {
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:17: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension E2 on int show num hide ceil {
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:26: Error: Expected ';' after this.
+// extension E2 on int show num hide ceil {
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:26: Error: 'num' is already declared in this scope.
+// extension E2 on int show num hide ceil {
+// ^^^
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:5:26: Context: Previous declaration of 'num'.
+// extension E1 on int show num {
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:35: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension E2 on int show num hide ceil {
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:14:17: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension E3 on int hide isEven {
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:14:26: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension E3 on int hide isEven {
+// ^^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:5:21: Error: Type 'show' not found.
+// extension E1 on int show num {
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:21: Error: Type 'show' not found.
+// extension E2 on int show num hide ceil {
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:30: Error: Type 'hide' not found.
+// extension E2 on int show num hide ceil {
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:14:21: Error: Type 'hide' not found.
+// extension E3 on int hide isEven {
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:6:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+// int ceil() {} // Error.
+// ^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:21: Error: 'show' isn't a type.
+// extension E2 on int show num hide ceil {
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:10:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+// int ceil() {} // Ok.
+// ^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:11:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+// int floor() {} // Error.
+// ^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:16:8: Error: Expected ';' after this.
+// bool get isOdd => throw 42; // Error.
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:16:18: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// bool get isOdd => throw 42; // Error.
+// ^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:17:8: Error: 'get' is already declared in this scope.
+// bool get isEven => throw 42; // Ok.
+// ^^^
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:16:8: Context: Previous declaration of 'get'.
+// bool get isOdd => throw 42; // Error.
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:17:8: Error: Expected ';' after this.
+// bool get isEven => throw 42; // Ok.
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:17:19: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// bool get isEven => throw 42; // Ok.
+// ^^
+//
+import self as self;
+import "dart:core" as core;
+
+extension E1 on core::int {
+}
+extension E2 on core::int {
+}
+extension E3 on core::int {
+}
+static method num() → invalid-type {
+ function ceil() → core::int {
+ return let final Never #t1 = invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:6:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+ int ceil() {} // Error.
+ ^" in null;
+ }
+}
+static method ceil() → invalid-type {
+ function ceil() → core::int {
+ return let final Never #t2 = invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:10:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+ int ceil() {} // Ok.
+ ^" in null;
+ }
+ function floor() → core::int {
+ return let final Never #t3 = invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:11:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+ int floor() {} // Error.
+ ^" in null;
+ }
+}
+static method isEven() → invalid-type {
+ core::bool get;
+ function isOdd() → Never
+ return throw 42;
+ core::bool get = invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:17:8: Error: 'get' is already declared in this scope.
+ bool get isEven => throw 42; // Ok.
+ ^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} core::bool;
+ function isEven() → Never
+ return throw 42;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart.weak.outline.expect b/pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart.weak.outline.expect
new file mode 100644
index 0000000..5c68071
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart.weak.outline.expect
@@ -0,0 +1,78 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:5:17: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension E1 on int show num {
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:5:26: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension E1 on int show num {
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:17: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension E2 on int show num hide ceil {
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:26: Error: Expected ';' after this.
+// extension E2 on int show num hide ceil {
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:26: Error: 'num' is already declared in this scope.
+// extension E2 on int show num hide ceil {
+// ^^^
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:5:26: Context: Previous declaration of 'num'.
+// extension E1 on int show num {
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:35: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension E2 on int show num hide ceil {
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:14:17: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension E3 on int hide isEven {
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:14:26: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension E3 on int hide isEven {
+// ^^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:5:21: Error: Type 'show' not found.
+// extension E1 on int show num {
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:21: Error: Type 'show' not found.
+// extension E2 on int show num hide ceil {
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:30: Error: Type 'hide' not found.
+// extension E2 on int show num hide ceil {
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:14:21: Error: Type 'hide' not found.
+// extension E3 on int hide isEven {
+// ^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+extension E1 on core::int {
+}
+extension E2 on core::int {
+}
+extension E3 on core::int {
+}
+static method num() → invalid-type
+ ;
+static method ceil() → invalid-type
+ ;
+static method isEven() → invalid-type
+ ;
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart.weak.transformed.expect b/pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart.weak.transformed.expect
new file mode 100644
index 0000000..9fe722e
--- /dev/null
+++ b/pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart.weak.transformed.expect
@@ -0,0 +1,141 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:5:17: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension E1 on int show num {
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:5:26: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension E1 on int show num {
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:17: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension E2 on int show num hide ceil {
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:26: Error: Expected ';' after this.
+// extension E2 on int show num hide ceil {
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:26: Error: 'num' is already declared in this scope.
+// extension E2 on int show num hide ceil {
+// ^^^
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:5:26: Context: Previous declaration of 'num'.
+// extension E1 on int show num {
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:35: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension E2 on int show num hide ceil {
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:14:17: Error: A extension declaration must have a body, even if it is empty.
+// Try adding an empty body.
+// extension E3 on int hide isEven {
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:14:26: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// extension E3 on int hide isEven {
+// ^^^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:5:21: Error: Type 'show' not found.
+// extension E1 on int show num {
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:21: Error: Type 'show' not found.
+// extension E2 on int show num hide ceil {
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:30: Error: Type 'hide' not found.
+// extension E2 on int show num hide ceil {
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:14:21: Error: Type 'hide' not found.
+// extension E3 on int hide isEven {
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:6:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+// int ceil() {} // Error.
+// ^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:9:21: Error: 'show' isn't a type.
+// extension E2 on int show num hide ceil {
+// ^^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:10:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+// int ceil() {} // Ok.
+// ^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:11:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+// int floor() {} // Error.
+// ^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:16:8: Error: Expected ';' after this.
+// bool get isOdd => throw 42; // Error.
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:16:18: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// bool get isOdd => throw 42; // Error.
+// ^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:17:8: Error: 'get' is already declared in this scope.
+// bool get isEven => throw 42; // Ok.
+// ^^^
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:16:8: Context: Previous declaration of 'get'.
+// bool get isOdd => throw 42; // Error.
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:17:8: Error: Expected ';' after this.
+// bool get isEven => throw 42; // Ok.
+// ^^^
+//
+// pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:17:19: Error: A function declaration needs an explicit list of parameters.
+// Try adding a parameter list to the function declaration.
+// bool get isEven => throw 42; // Ok.
+// ^^
+//
+import self as self;
+import "dart:core" as core;
+
+extension E1 on core::int {
+}
+extension E2 on core::int {
+}
+extension E3 on core::int {
+}
+static method num() → invalid-type {
+ function ceil() → core::int {
+ return let final Never #t1 = invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:6:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+ int ceil() {} // Error.
+ ^" in null;
+ }
+}
+static method ceil() → invalid-type {
+ function ceil() → core::int {
+ return let final Never #t2 = invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:10:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+ int ceil() {} // Ok.
+ ^" in null;
+ }
+ function floor() → core::int {
+ return let final Never #t3 = invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:11:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+ int floor() {} // Error.
+ ^" in null;
+ }
+}
+static method isEven() → invalid-type {
+ core::bool get;
+ function isOdd() → Never
+ return throw 42;
+ core::bool get = invalid-expression "pkg/front_end/testcases/extension_types/simple_show_hide_conflicts.dart:17:8: Error: 'get' is already declared in this scope.
+ bool get isEven => throw 42; // Ok.
+ ^^^";
+ function isEven() → Never
+ return throw 42;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/extensions/default_values.dart.weak.expect b/pkg/front_end/testcases/extensions/default_values.dart.weak.expect
index f4256f5..99dd7ec 100644
--- a/pkg/front_end/testcases/extensions/default_values.dart.weak.expect
+++ b/pkg/front_end/testcases/extensions/default_values.dart.weak.expect
@@ -71,5 +71,5 @@
#C1 = null
#C2 = 42
#C3 = 87
- #C4 = tearoff self::Extension|staticMethod
+ #C4 = static-tearoff self::Extension|staticMethod
}
diff --git a/pkg/front_end/testcases/extensions/default_values.dart.weak.transformed.expect b/pkg/front_end/testcases/extensions/default_values.dart.weak.transformed.expect
index f4256f5..99dd7ec 100644
--- a/pkg/front_end/testcases/extensions/default_values.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/extensions/default_values.dart.weak.transformed.expect
@@ -71,5 +71,5 @@
#C1 = null
#C2 = 42
#C3 = 87
- #C4 = tearoff self::Extension|staticMethod
+ #C4 = static-tearoff self::Extension|staticMethod
}
diff --git a/pkg/front_end/testcases/extensions/direct_static_access.dart.weak.expect b/pkg/front_end/testcases/extensions/direct_static_access.dart.weak.expect
index bef26cf..942973c 100644
--- a/pkg/front_end/testcases/extensions/direct_static_access.dart.weak.expect
+++ b/pkg/front_end/testcases/extensions/direct_static_access.dart.weak.expect
@@ -232,11 +232,11 @@
constants {
#C1 = null
- #C2 = tearoff self::Extension|readGetter
- #C3 = tearoff self::Extension|writeSetterRequired
- #C4 = tearoff self::Extension|writeSetterOptional
- #C5 = tearoff self::Extension|writeSetterNamed
- #C6 = tearoff self::Extension|genericWriteSetterRequired
- #C7 = tearoff self::Extension|genericWriteSetterOptional
- #C8 = tearoff self::Extension|genericWriteSetterNamed
+ #C2 = static-tearoff self::Extension|readGetter
+ #C3 = static-tearoff self::Extension|writeSetterRequired
+ #C4 = static-tearoff self::Extension|writeSetterOptional
+ #C5 = static-tearoff self::Extension|writeSetterNamed
+ #C6 = static-tearoff self::Extension|genericWriteSetterRequired
+ #C7 = static-tearoff self::Extension|genericWriteSetterOptional
+ #C8 = static-tearoff self::Extension|genericWriteSetterNamed
}
diff --git a/pkg/front_end/testcases/extensions/direct_static_access.dart.weak.transformed.expect b/pkg/front_end/testcases/extensions/direct_static_access.dart.weak.transformed.expect
index bef26cf..942973c 100644
--- a/pkg/front_end/testcases/extensions/direct_static_access.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/extensions/direct_static_access.dart.weak.transformed.expect
@@ -232,11 +232,11 @@
constants {
#C1 = null
- #C2 = tearoff self::Extension|readGetter
- #C3 = tearoff self::Extension|writeSetterRequired
- #C4 = tearoff self::Extension|writeSetterOptional
- #C5 = tearoff self::Extension|writeSetterNamed
- #C6 = tearoff self::Extension|genericWriteSetterRequired
- #C7 = tearoff self::Extension|genericWriteSetterOptional
- #C8 = tearoff self::Extension|genericWriteSetterNamed
+ #C2 = static-tearoff self::Extension|readGetter
+ #C3 = static-tearoff self::Extension|writeSetterRequired
+ #C4 = static-tearoff self::Extension|writeSetterOptional
+ #C5 = static-tearoff self::Extension|writeSetterNamed
+ #C6 = static-tearoff self::Extension|genericWriteSetterRequired
+ #C7 = static-tearoff self::Extension|genericWriteSetterOptional
+ #C8 = static-tearoff self::Extension|genericWriteSetterNamed
}
diff --git a/pkg/front_end/testcases/extensions/export_from_dill/main.dart.weak.expect b/pkg/front_end/testcases/extensions/export_from_dill/main.dart.weak.expect
index d7c5320..214f428 100644
--- a/pkg/front_end/testcases/extensions/export_from_dill/main.dart.weak.expect
+++ b/pkg/front_end/testcases/extensions/export_from_dill/main.dart.weak.expect
@@ -56,5 +56,5 @@
constants {
#C1 = 42
- #C2 = tearoff mai::Extension|staticMethod
+ #C2 = static-tearoff mai::Extension|staticMethod
}
diff --git a/pkg/front_end/testcases/extensions/export_from_dill/main.dart.weak.transformed.expect b/pkg/front_end/testcases/extensions/export_from_dill/main.dart.weak.transformed.expect
index d7c5320..214f428 100644
--- a/pkg/front_end/testcases/extensions/export_from_dill/main.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/extensions/export_from_dill/main.dart.weak.transformed.expect
@@ -56,5 +56,5 @@
constants {
#C1 = 42
- #C2 = tearoff mai::Extension|staticMethod
+ #C2 = static-tearoff mai::Extension|staticMethod
}
diff --git a/pkg/front_end/testcases/extensions/import_from_dill/main.dart.weak.expect b/pkg/front_end/testcases/extensions/import_from_dill/main.dart.weak.expect
index dda54b1..4dc6953 100644
--- a/pkg/front_end/testcases/extensions/import_from_dill/main.dart.weak.expect
+++ b/pkg/front_end/testcases/extensions/import_from_dill/main.dart.weak.expect
@@ -48,5 +48,5 @@
constants {
#C1 = 42
- #C2 = tearoff mai::Extension|staticMethod
+ #C2 = static-tearoff mai::Extension|staticMethod
}
diff --git a/pkg/front_end/testcases/extensions/import_from_dill/main.dart.weak.transformed.expect b/pkg/front_end/testcases/extensions/import_from_dill/main.dart.weak.transformed.expect
index dda54b1..4dc6953 100644
--- a/pkg/front_end/testcases/extensions/import_from_dill/main.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/extensions/import_from_dill/main.dart.weak.transformed.expect
@@ -48,5 +48,5 @@
constants {
#C1 = 42
- #C2 = tearoff mai::Extension|staticMethod
+ #C2 = static-tearoff mai::Extension|staticMethod
}
diff --git a/pkg/front_end/testcases/extensions/static_access.dart.weak.expect b/pkg/front_end/testcases/extensions/static_access.dart.weak.expect
index 5cc472a..973805f 100644
--- a/pkg/front_end/testcases/extensions/static_access.dart.weak.expect
+++ b/pkg/front_end/testcases/extensions/static_access.dart.weak.expect
@@ -53,6 +53,6 @@
}
constants {
- #C1 = tearoff self::Extension|method
- #C2 = tearoff self::Extension|genericMethod
+ #C1 = static-tearoff self::Extension|method
+ #C2 = static-tearoff self::Extension|genericMethod
}
diff --git a/pkg/front_end/testcases/extensions/static_access.dart.weak.transformed.expect b/pkg/front_end/testcases/extensions/static_access.dart.weak.transformed.expect
index 5cc472a..973805f 100644
--- a/pkg/front_end/testcases/extensions/static_access.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/extensions/static_access.dart.weak.transformed.expect
@@ -53,6 +53,6 @@
}
constants {
- #C1 = tearoff self::Extension|method
- #C2 = tearoff self::Extension|genericMethod
+ #C1 = static-tearoff self::Extension|method
+ #C2 = static-tearoff self::Extension|genericMethod
}
diff --git a/pkg/front_end/testcases/general/argument.dart.weak.expect b/pkg/front_end/testcases/general/argument.dart.weak.expect
index 90b185e..e667193 100644
--- a/pkg/front_end/testcases/general/argument.dart.weak.expect
+++ b/pkg/front_end/testcases/general/argument.dart.weak.expect
@@ -47,6 +47,6 @@
}
constants {
- #C1 = tearoff self::foo_escaped
- #C2 = tearoff self::bar_escaped
+ #C1 = static-tearoff self::foo_escaped
+ #C2 = static-tearoff self::bar_escaped
}
diff --git a/pkg/front_end/testcases/general/argument.dart.weak.transformed.expect b/pkg/front_end/testcases/general/argument.dart.weak.transformed.expect
index 90b185e..e667193 100644
--- a/pkg/front_end/testcases/general/argument.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/argument.dart.weak.transformed.expect
@@ -47,6 +47,6 @@
}
constants {
- #C1 = tearoff self::foo_escaped
- #C2 = tearoff self::bar_escaped
+ #C1 = static-tearoff self::foo_escaped
+ #C2 = static-tearoff self::bar_escaped
}
diff --git a/pkg/front_end/testcases/general/async_nested.dart.weak.transformed.expect b/pkg/front_end/testcases/general/async_nested.dart.weak.transformed.expect
index 45a2ff8..758329d 100644
--- a/pkg/front_end/testcases/general/async_nested.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/async_nested.dart.weak.transformed.expect
@@ -36,9 +36,9 @@
core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
- dynamic :async_temporary_0;
- dynamic :async_temporary_1;
- dynamic :async_temporary_2;
+ self::Node* :async_temporary_0;
+ self::Node* :async_temporary_1;
+ self::Node* :async_temporary_2;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
#L1:
diff --git a/pkg/front_end/testcases/general/await_complex.dart.weak.expect b/pkg/front_end/testcases/general/await_complex.dart.weak.expect
index df8fc27..20324c7 100644
--- a/pkg/front_end/testcases/general/await_complex.dart.weak.expect
+++ b/pkg/front_end/testcases/general/await_complex.dart.weak.expect
@@ -254,7 +254,7 @@
}
constants {
- #C1 = tearoff self::id
- #C2 = tearoff self::future
+ #C1 = static-tearoff self::id
+ #C2 = static-tearoff self::future
#C3 = 2
}
diff --git a/pkg/front_end/testcases/general/await_complex.dart.weak.transformed.expect b/pkg/front_end/testcases/general/await_complex.dart.weak.transformed.expect
index cb5a62a..087766ec 100644
--- a/pkg/front_end/testcases/general/await_complex.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/await_complex.dart.weak.transformed.expect
@@ -65,12 +65,12 @@
core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
- dynamic :async_temporary_0;
- dynamic :async_temporary_1;
- dynamic :async_temporary_2;
- dynamic :async_temporary_3;
- dynamic :async_temporary_4;
- dynamic :async_temporary_5;
+ core::int* :async_temporary_0;
+ core::int* :async_temporary_1;
+ core::int* :async_temporary_2;
+ core::int* :async_temporary_3;
+ core::int* :async_temporary_4;
+ core::int* :async_temporary_5;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
#L1:
@@ -121,11 +121,11 @@
core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
- dynamic :async_temporary_0;
- dynamic :async_temporary_1;
- dynamic :async_temporary_2;
- dynamic :async_temporary_3;
- dynamic :async_temporary_4;
+ core::int* :async_temporary_0;
+ core::int* :async_temporary_1;
+ core::int* :async_temporary_2;
+ core::int* :async_temporary_3;
+ core::int* :async_temporary_4;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
#L2:
@@ -172,11 +172,11 @@
core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
- dynamic :async_temporary_0;
- dynamic :async_temporary_1;
- dynamic :async_temporary_2;
- dynamic :async_temporary_3;
- dynamic :async_temporary_4;
+ core::int* :async_temporary_0;
+ core::int* :async_temporary_1;
+ core::int* :async_temporary_2;
+ core::int* :async_temporary_3;
+ core::int* :async_temporary_4;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
#L3:
@@ -225,10 +225,10 @@
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
dynamic :async_temporary_0;
- dynamic :async_temporary_1;
- dynamic :async_temporary_2;
- dynamic :async_temporary_3;
- dynamic :async_temporary_4;
+ core::int* :async_temporary_1;
+ core::int* :async_temporary_2;
+ core::List<core::int*>* :async_temporary_3;
+ core::int* :async_temporary_4;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
#L4:
@@ -288,13 +288,13 @@
core::bool* a = false;
core::bool* b = true;
:async_temporary_0 = (a || b) =={core::Object::==}{(core::Object) → core::bool} true;
- if(:async_temporary_0)
+ if(_in::unsafeCast<core::bool*>(:async_temporary_0))
;
else {
[yield] let dynamic #t22 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
:async_temporary_0 = :result as{TypeError,ForDynamic} core::bool* =={core::Object::==}{(core::Object) → core::bool} true;
}
- core::bool* c = :async_temporary_0;
+ core::bool* c = _in::unsafeCast<core::bool*>(:async_temporary_0);
self::expect(true, c);
if(a || b) {
:async_temporary_1 = a;
@@ -426,8 +426,8 @@
dynamic :saved_try_context_var3;
dynamic :exception0;
dynamic :stack_trace0;
- dynamic :async_temporary_0;
- dynamic :async_temporary_1;
+ core::List<dynamic>* :async_temporary_0;
+ core::List<dynamic>* :async_temporary_1;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
#L7:
@@ -811,7 +811,7 @@
}
constants {
- #C1 = tearoff self::id
- #C2 = tearoff self::future
+ #C1 = static-tearoff self::id
+ #C2 = static-tearoff self::future
#C3 = 2
}
diff --git a/pkg/front_end/testcases/general/bug33206.dart.weak.transformed.expect b/pkg/front_end/testcases/general/bug33206.dart.weak.transformed.expect
index 7178e45..85541c5 100644
--- a/pkg/front_end/testcases/general/bug33206.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/bug33206.dart.weak.transformed.expect
@@ -105,7 +105,7 @@
core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
- dynamic :async_temporary_0;
+ self::Y* :async_temporary_0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
#L3:
diff --git a/pkg/front_end/testcases/general/constants/js_semantics/issue46123.dart b/pkg/front_end/testcases/general/constants/js_semantics/issue46123.dart
new file mode 100644
index 0000000..0210c32
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/js_semantics/issue46123.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2020, 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.
+
+import 'package:js/js.dart';
+
+@JS()
+@anonymous
+class ParallaxOptions {
+ external const factory ParallaxOptions();
+}
+
+test() => const ParallaxOptions();
+
+main() {}
diff --git a/pkg/front_end/testcases/general/constants/js_semantics/issue46123.dart.textual_outline.expect b/pkg/front_end/testcases/general/constants/js_semantics/issue46123.dart.textual_outline.expect
new file mode 100644
index 0000000..8b3f432
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/js_semantics/issue46123.dart.textual_outline.expect
@@ -0,0 +1,10 @@
+import 'package:js/js.dart';
+
+@JS()
+@anonymous
+class ParallaxOptions {
+ external const factory ParallaxOptions();
+}
+
+test() => const ParallaxOptions();
+main() {}
diff --git a/pkg/front_end/testcases/general/constants/js_semantics/issue46123.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/constants/js_semantics/issue46123.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..bef2d3d
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/js_semantics/issue46123.dart.textual_outline_modelled.expect
@@ -0,0 +1,10 @@
+import 'package:js/js.dart';
+
+@JS()
+@anonymous
+class ParallaxOptions {
+ external const factory ParallaxOptions();
+}
+
+main() {}
+test() => const ParallaxOptions();
diff --git a/pkg/front_end/testcases/general/constants/js_semantics/issue46123.dart.weak.expect b/pkg/front_end/testcases/general/constants/js_semantics/issue46123.dart.weak.expect
new file mode 100644
index 0000000..c1c307d
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/js_semantics/issue46123.dart.weak.expect
@@ -0,0 +1,37 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/constants/js_semantics/issue46123.dart:13:17: Error: Constant evaluation error:
+// test() => const ParallaxOptions();
+// ^
+// pkg/front_end/testcases/general/constants/js_semantics/issue46123.dart:13:17: Context: External factory constructors can't be evaluated in constant expressions.
+// test() => const ParallaxOptions();
+// ^
+//
+import self as self;
+import "package:js/js.dart" as js;
+import "dart:core" as core;
+
+import "package:js/js.dart";
+
+@#C2
+@#C3
+class ParallaxOptions extends core::Object {
+ external static factory •() → self::ParallaxOptions;
+}
+static method test() → dynamic
+ return invalid-expression "External factory constructors can't be evaluated in constant expressions.";
+static method main() → dynamic {}
+
+constants {
+ #C1 = null
+ #C2 = js::JS {name:#C1}
+ #C3 = js::_Anonymous {}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue46123.dart:
+- JS. (from org-dartlang-testcase-sdk:///pkg/js/lib/js.dart:21:9)
+- Object. (from org-dartlang-sdk:///lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general/constants/js_semantics/issue46123.dart.weak.outline.expect b/pkg/front_end/testcases/general/constants/js_semantics/issue46123.dart.weak.outline.expect
new file mode 100644
index 0000000..d5602f8
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/js_semantics/issue46123.dart.weak.outline.expect
@@ -0,0 +1,22 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "package:js/js.dart" as js;
+import "dart:core" as core;
+
+import "package:js/js.dart";
+
+@js::JS::•()
+@js::anonymous
+class ParallaxOptions extends core::Object {
+ external static factory •() → self::ParallaxOptions;
+}
+static method test() → dynamic
+ ;
+static method main() → dynamic
+ ;
+
+
+Extra constant evaluation status:
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///issue46123.dart:7:2 -> InstanceConstant(const JS{JS.name: null})
+Evaluated: StaticGet @ org-dartlang-testcase:///issue46123.dart:8:2 -> InstanceConstant(const _Anonymous{})
+Extra constant evaluation: evaluated: 2, effectively constant: 2
diff --git a/pkg/front_end/testcases/general/constants/js_semantics/issue46123.dart.weak.transformed.expect b/pkg/front_end/testcases/general/constants/js_semantics/issue46123.dart.weak.transformed.expect
new file mode 100644
index 0000000..c1c307d
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/js_semantics/issue46123.dart.weak.transformed.expect
@@ -0,0 +1,37 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/constants/js_semantics/issue46123.dart:13:17: Error: Constant evaluation error:
+// test() => const ParallaxOptions();
+// ^
+// pkg/front_end/testcases/general/constants/js_semantics/issue46123.dart:13:17: Context: External factory constructors can't be evaluated in constant expressions.
+// test() => const ParallaxOptions();
+// ^
+//
+import self as self;
+import "package:js/js.dart" as js;
+import "dart:core" as core;
+
+import "package:js/js.dart";
+
+@#C2
+@#C3
+class ParallaxOptions extends core::Object {
+ external static factory •() → self::ParallaxOptions;
+}
+static method test() → dynamic
+ return invalid-expression "External factory constructors can't be evaluated in constant expressions.";
+static method main() → dynamic {}
+
+constants {
+ #C1 = null
+ #C2 = js::JS {name:#C1}
+ #C3 = js::_Anonymous {}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue46123.dart:
+- JS. (from org-dartlang-testcase-sdk:///pkg/js/lib/js.dart:21:9)
+- Object. (from org-dartlang-sdk:///lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general/constants/js_semantics/issue46123b.dart b/pkg/front_end/testcases/general/constants/js_semantics/issue46123b.dart
new file mode 100644
index 0000000..ecc1c05
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/js_semantics/issue46123b.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2020, 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.
+
+import 'package:js/js.dart';
+
+@JS()
+@anonymous
+class ParallaxOptions {
+ external const ParallaxOptions();
+}
+
+test() => const ParallaxOptions();
+
+main() {}
diff --git a/pkg/front_end/testcases/general/constants/js_semantics/issue46123b.dart.textual_outline.expect b/pkg/front_end/testcases/general/constants/js_semantics/issue46123b.dart.textual_outline.expect
new file mode 100644
index 0000000..2d26ea3
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/js_semantics/issue46123b.dart.textual_outline.expect
@@ -0,0 +1,10 @@
+import 'package:js/js.dart';
+
+@JS()
+@anonymous
+class ParallaxOptions {
+ external const ParallaxOptions();
+}
+
+test() => const ParallaxOptions();
+main() {}
diff --git a/pkg/front_end/testcases/general/constants/js_semantics/issue46123b.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/constants/js_semantics/issue46123b.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..0c3a93a
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/js_semantics/issue46123b.dart.textual_outline_modelled.expect
@@ -0,0 +1,10 @@
+import 'package:js/js.dart';
+
+@JS()
+@anonymous
+class ParallaxOptions {
+ external const ParallaxOptions();
+}
+
+main() {}
+test() => const ParallaxOptions();
diff --git a/pkg/front_end/testcases/general/constants/js_semantics/issue46123b.dart.weak.expect b/pkg/front_end/testcases/general/constants/js_semantics/issue46123b.dart.weak.expect
new file mode 100644
index 0000000..29f09a1
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/js_semantics/issue46123b.dart.weak.expect
@@ -0,0 +1,39 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/constants/js_semantics/issue46123b.dart:13:17: Error: Constant evaluation error:
+// test() => const ParallaxOptions();
+// ^
+// pkg/front_end/testcases/general/constants/js_semantics/issue46123b.dart:13:17: Context: External constructors can't be evaluated in constant expressions.
+// test() => const ParallaxOptions();
+// ^
+//
+import self as self;
+import "package:js/js.dart" as js;
+import "dart:core" as core;
+
+import "package:js/js.dart";
+
+@#C2
+@#C3
+class ParallaxOptions extends core::Object /*hasConstConstructor*/ {
+ external const constructor •() → self::ParallaxOptions
+ : super core::Object::•()
+ ;
+}
+static method test() → dynamic
+ return invalid-expression "External constructors can't be evaluated in constant expressions.";
+static method main() → dynamic {}
+
+constants {
+ #C1 = null
+ #C2 = js::JS {name:#C1}
+ #C3 = js::_Anonymous {}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue46123b.dart:
+- JS. (from org-dartlang-testcase-sdk:///pkg/js/lib/js.dart:21:9)
+- Object. (from org-dartlang-sdk:///lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general/constants/js_semantics/issue46123b.dart.weak.outline.expect b/pkg/front_end/testcases/general/constants/js_semantics/issue46123b.dart.weak.outline.expect
new file mode 100644
index 0000000..78273bc
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/js_semantics/issue46123b.dart.weak.outline.expect
@@ -0,0 +1,24 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "package:js/js.dart" as js;
+import "dart:core" as core;
+
+import "package:js/js.dart";
+
+@js::JS::•()
+@js::anonymous
+class ParallaxOptions extends core::Object /*hasConstConstructor*/ {
+ external const constructor •() → self::ParallaxOptions
+ : super core::Object::•()
+ ;
+}
+static method test() → dynamic
+ ;
+static method main() → dynamic
+ ;
+
+
+Extra constant evaluation status:
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///issue46123b.dart:7:2 -> InstanceConstant(const JS{JS.name: null})
+Evaluated: StaticGet @ org-dartlang-testcase:///issue46123b.dart:8:2 -> InstanceConstant(const _Anonymous{})
+Extra constant evaluation: evaluated: 2, effectively constant: 2
diff --git a/pkg/front_end/testcases/general/constants/js_semantics/issue46123b.dart.weak.transformed.expect b/pkg/front_end/testcases/general/constants/js_semantics/issue46123b.dart.weak.transformed.expect
new file mode 100644
index 0000000..29f09a1
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/js_semantics/issue46123b.dart.weak.transformed.expect
@@ -0,0 +1,39 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/constants/js_semantics/issue46123b.dart:13:17: Error: Constant evaluation error:
+// test() => const ParallaxOptions();
+// ^
+// pkg/front_end/testcases/general/constants/js_semantics/issue46123b.dart:13:17: Context: External constructors can't be evaluated in constant expressions.
+// test() => const ParallaxOptions();
+// ^
+//
+import self as self;
+import "package:js/js.dart" as js;
+import "dart:core" as core;
+
+import "package:js/js.dart";
+
+@#C2
+@#C3
+class ParallaxOptions extends core::Object /*hasConstConstructor*/ {
+ external const constructor •() → self::ParallaxOptions
+ : super core::Object::•()
+ ;
+}
+static method test() → dynamic
+ return invalid-expression "External constructors can't be evaluated in constant expressions.";
+static method main() → dynamic {}
+
+constants {
+ #C1 = null
+ #C2 = js::JS {name:#C1}
+ #C3 = js::_Anonymous {}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue46123b.dart:
+- JS. (from org-dartlang-testcase-sdk:///pkg/js/lib/js.dart:21:9)
+- Object. (from org-dartlang-sdk:///lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general/constants/various.dart.weak.expect b/pkg/front_end/testcases/general/constants/various.dart.weak.expect
index 8c8d29f..1cde25c 100644
--- a/pkg/front_end/testcases/general/constants/various.dart.weak.expect
+++ b/pkg/front_end/testcases/general/constants/various.dart.weak.expect
@@ -621,8 +621,8 @@
#C18 = #I.Have.Dots
#C19 = self::ClassWithTypeArguments<core::int*, core::int*, core::int*> {}
#C20 = self::ClassWithTypeArguments<dynamic, dynamic, dynamic> {}
- #C21 = tearoff self::id1
- #C22 = partial-instantiation self::id1 <core::int*>
+ #C21 = static-tearoff self::id1
+ #C22 = instantiation self::id1 <core::int*>
}
diff --git a/pkg/front_end/testcases/general/constants/various.dart.weak.transformed.expect b/pkg/front_end/testcases/general/constants/various.dart.weak.transformed.expect
index 6998464..f39f9ab 100644
--- a/pkg/front_end/testcases/general/constants/various.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/constants/various.dart.weak.transformed.expect
@@ -621,8 +621,8 @@
#C18 = #I.Have.Dots
#C19 = self::ClassWithTypeArguments<core::int*, core::int*, core::int*> {}
#C20 = self::ClassWithTypeArguments<dynamic, dynamic, dynamic> {}
- #C21 = tearoff self::id1
- #C22 = partial-instantiation self::id1 <core::int*>
+ #C21 = static-tearoff self::id1
+ #C22 = instantiation self::id1 <core::int*>
}
Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart.weak.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart.weak.expect
index 9b677e7..ce2a935 100644
--- a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart.weak.expect
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart.weak.expect
@@ -232,7 +232,7 @@
#C38 = eval const core::bool::fromEnvironment(#C33) ?{self::Subclass<self::A>?} #C9 : self::Subclass<self::A*>{(self::A{}) as{ForNonNullableByDefault} self::A*}
#C39 = eval const core::bool::fromEnvironment(#C33) ?{self::Subclass<self::B>?} #C9 : self::Subclass<self::B*>{(self::B{}) as{ForNonNullableByDefault} self::B*}
#C40 = TypeLiteralConstant((core::int*, {named: core::int*}) →* core::int*)
- #C41 = tearoff self::procedure
+ #C41 = static-tearoff self::procedure
#C42 = self::ConstClassWithF {foo:#C41}
#C43 = eval const core::bool::fromEnvironment(#C1)
#C44 = eval !const core::bool::fromEnvironment(#C1)
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart.weak.transformed.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart.weak.transformed.expect
index b2b5426..fef7a55 100644
--- a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart.weak.transformed.expect
@@ -232,7 +232,7 @@
#C38 = eval const core::bool::fromEnvironment(#C33) ?{self::Subclass<self::A>?} #C9 : self::Subclass<self::A*>{(self::A{}) as{ForNonNullableByDefault} self::A*}
#C39 = eval const core::bool::fromEnvironment(#C33) ?{self::Subclass<self::B>?} #C9 : self::Subclass<self::B*>{(self::B{}) as{ForNonNullableByDefault} self::B*}
#C40 = TypeLiteralConstant((core::int*, {named: core::int*}) →* core::int*)
- #C41 = tearoff self::procedure
+ #C41 = static-tearoff self::procedure
#C42 = self::ConstClassWithF {foo:#C41}
#C43 = eval const core::bool::fromEnvironment(#C1)
#C44 = eval !const core::bool::fromEnvironment(#C1)
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.weak.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.weak.expect
index 65655e9..942009a 100644
--- a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.weak.expect
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.weak.expect
@@ -103,8 +103,8 @@
constants {
#C1 = TypeLiteralConstant(core::Object*)
- #C2 = tearoff var::id1
- #C3 = partial-instantiation var::id1 <core::int*>
+ #C2 = static-tearoff var::id1
+ #C3 = instantiation var::id1 <core::int*>
#C4 = 0
#C5 = var::Class<core::int*> {field:#C4}
#C6 = 42
@@ -121,10 +121,10 @@
#C17 = null
#C18 = <dynamic, dynamic>{#C7:#C15, #C17:#C7)
#C19 = true
- #C20 = tearoff var::id2
+ #C20 = static-tearoff var::id2
#C21 = eval const core::identical(#C3, const core::bool::fromEnvironment(#C15) ?{(core::int) → core::int} #C2<core::int> : #C20<core::int>)
#C22 = eval const core::bool::fromEnvironment(#C15) ?{(core::int) → core::int} #C2<core::int> : #C20<core::int>
- #C23 = tearoff core::identical
+ #C23 = static-tearoff core::identical
}
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.weak.transformed.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.weak.transformed.expect
index 8f668a2..6a48cb7 100644
--- a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.weak.transformed.expect
@@ -103,8 +103,8 @@
constants {
#C1 = TypeLiteralConstant(core::Object*)
- #C2 = tearoff var::id1
- #C3 = partial-instantiation var::id1 <core::int*>
+ #C2 = static-tearoff var::id1
+ #C3 = instantiation var::id1 <core::int*>
#C4 = 0
#C5 = var::Class<core::int*> {field:#C4}
#C6 = 42
@@ -121,11 +121,11 @@
#C17 = null
#C18 = <dynamic, dynamic>{#C7:#C15, #C17:#C7)
#C19 = true
- #C20 = tearoff var::id2
+ #C20 = static-tearoff var::id2
#C21 = eval const core::identical(#C3, const core::bool::fromEnvironment(#C15) ?{(core::int) → core::int} #C2<core::int> : #C20<core::int>)
#C22 = eval const core::bool::fromEnvironment(#C15) ?{(core::int) → core::int} #C2<core::int> : #C20<core::int>
#C23 = eval const core::identical(#C3, const core::bool::fromEnvironment(#C15) ?{(core::int) → core::int} #C2<core::int> : #C20<core::int>)
- #C24 = tearoff core::identical
+ #C24 = static-tearoff core::identical
#C25 = eval const core::bool::fromEnvironment(#C15) ?{(core::int) → core::int} #C2<core::int> : #C20<core::int>
}
diff --git a/pkg/front_end/testcases/general/constructor_patch/libraries.json b/pkg/front_end/testcases/general/constructor_patch/libraries.json
new file mode 100644
index 0000000..154c73c
--- /dev/null
+++ b/pkg/front_end/testcases/general/constructor_patch/libraries.json
@@ -0,0 +1,12 @@
+{
+ "none": {
+ "libraries": {
+ "test": {
+ "patches": [
+ "patch_lib.dart"
+ ],
+ "uri": "origin_lib.dart"
+ }
+ }
+ }
+}
diff --git a/tests/lib/js/extends_test/extends_with_es6_subtyping_test.dart b/pkg/front_end/testcases/general/constructor_patch/main.dart
similarity index 70%
copy from tests/lib/js/extends_test/extends_with_es6_subtyping_test.dart
copy to pkg/front_end/testcases/general/constructor_patch/main.dart
index e6185da..dd2a110 100644
--- a/tests/lib/js/extends_test/extends_with_es6_subtyping_test.dart
+++ b/pkg/front_end/testcases/general/constructor_patch/main.dart
@@ -2,9 +2,9 @@
// 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.
-import 'extends_test_util.dart';
+import 'dart:test';
-void main() {
- setUpWithES6Syntax();
- testSubtyping();
+main() {
+ new Class.generative();
+ const Class.constGenerative();
}
diff --git a/pkg/front_end/testcases/general/constructor_patch/main.dart.textual_outline.expect b/pkg/front_end/testcases/general/constructor_patch/main.dart.textual_outline.expect
new file mode 100644
index 0000000..3c9c90e
--- /dev/null
+++ b/pkg/front_end/testcases/general/constructor_patch/main.dart.textual_outline.expect
@@ -0,0 +1,3 @@
+import 'dart:test';
+
+main() {}
diff --git a/pkg/front_end/testcases/general/constructor_patch/main.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/constructor_patch/main.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..3c9c90e
--- /dev/null
+++ b/pkg/front_end/testcases/general/constructor_patch/main.dart.textual_outline_modelled.expect
@@ -0,0 +1,3 @@
+import 'dart:test';
+
+main() {}
diff --git a/pkg/front_end/testcases/general/constructor_patch/main.dart.weak.expect b/pkg/front_end/testcases/general/constructor_patch/main.dart.weak.expect
new file mode 100644
index 0000000..40f37f3
--- /dev/null
+++ b/pkg/front_end/testcases/general/constructor_patch/main.dart.weak.expect
@@ -0,0 +1,42 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:test" as test;
+
+import "dart:test";
+
+static method main() → dynamic {
+ new test::Class::generative();
+ #C2;
+}
+
+library /*isNonNullableByDefault*/;
+import self as test;
+import "dart:_internal" as _in;
+import "dart:core" as core;
+
+import "dart:_internal";
+
+@#C3
+class Class extends core::Object /*hasConstConstructor*/ {
+ final field core::bool defaultValue /* from org-dartlang-testcase:///patch_lib.dart */;
+ @#C3
+ constructor generative({core::bool defaultValue = #C1}) → test::Class
+ : test::Class::defaultValue = defaultValue, super core::Object::•()
+ ;
+ @#C3
+ const constructor constGenerative({core::bool defaultValue = #C1}) → test::Class
+ : test::Class::defaultValue = defaultValue, super core::Object::•()
+ ;
+}
+
+constants {
+ #C1 = true
+ #C2 = test::Class {defaultValue:#C1}
+ #C3 = _in::_Patch {}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///main.dart:
+- Class.constGenerative (from org-dartlang-testcase:///patch_lib.dart:16:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/general/constructor_patch/main.dart.weak.outline.expect b/pkg/front_end/testcases/general/constructor_patch/main.dart.weak.outline.expect
new file mode 100644
index 0000000..d5e5658
--- /dev/null
+++ b/pkg/front_end/testcases/general/constructor_patch/main.dart.weak.outline.expect
@@ -0,0 +1,33 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+import "dart:test";
+
+static method main() → dynamic
+ ;
+
+library /*isNonNullableByDefault*/;
+import self as self2;
+import "dart:_internal" as _in;
+import "dart:core" as core;
+
+import "dart:_internal";
+
+@_in::patch
+class Class extends core::Object /*hasConstConstructor*/ {
+ final field core::bool defaultValue /* from org-dartlang-testcase:///patch_lib.dart */;
+ @_in::patch
+ external constructor generative({core::bool defaultValue}) → self2::Class
+ ;
+ @_in::patch
+ const constructor constGenerative({core::bool defaultValue = true}) → self2::Class
+ : self2::Class::defaultValue = defaultValue, super core::Object::•()
+ ;
+}
+
+
+Extra constant evaluation status:
+Evaluated: StaticGet @ org-dartlang-testcase:///origin_lib.dart:6:49 -> InstanceConstant(const _Patch{})
+Evaluated: StaticGet @ org-dartlang-testcase:///origin_lib.dart:7:44 -> InstanceConstant(const _Patch{})
+Evaluated: StaticGet @ org-dartlang-testcase:///patch_lib.dart:16:9 -> InstanceConstant(const _Patch{})
+Extra constant evaluation: evaluated: 4, effectively constant: 3
diff --git a/pkg/front_end/testcases/general/constructor_patch/main.dart.weak.transformed.expect b/pkg/front_end/testcases/general/constructor_patch/main.dart.weak.transformed.expect
new file mode 100644
index 0000000..40f37f3
--- /dev/null
+++ b/pkg/front_end/testcases/general/constructor_patch/main.dart.weak.transformed.expect
@@ -0,0 +1,42 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:test" as test;
+
+import "dart:test";
+
+static method main() → dynamic {
+ new test::Class::generative();
+ #C2;
+}
+
+library /*isNonNullableByDefault*/;
+import self as test;
+import "dart:_internal" as _in;
+import "dart:core" as core;
+
+import "dart:_internal";
+
+@#C3
+class Class extends core::Object /*hasConstConstructor*/ {
+ final field core::bool defaultValue /* from org-dartlang-testcase:///patch_lib.dart */;
+ @#C3
+ constructor generative({core::bool defaultValue = #C1}) → test::Class
+ : test::Class::defaultValue = defaultValue, super core::Object::•()
+ ;
+ @#C3
+ const constructor constGenerative({core::bool defaultValue = #C1}) → test::Class
+ : test::Class::defaultValue = defaultValue, super core::Object::•()
+ ;
+}
+
+constants {
+ #C1 = true
+ #C2 = test::Class {defaultValue:#C1}
+ #C3 = _in::_Patch {}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///main.dart:
+- Class.constGenerative (from org-dartlang-testcase:///patch_lib.dart:16:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/tests/lib/js/extends_test/extends_subtyping_test.dart b/pkg/front_end/testcases/general/constructor_patch/origin_lib.dart
similarity index 60%
copy from tests/lib/js/extends_test/extends_subtyping_test.dart
copy to pkg/front_end/testcases/general/constructor_patch/origin_lib.dart
index 76dc51e..2906fbf 100644
--- a/tests/lib/js/extends_test/extends_subtyping_test.dart
+++ b/pkg/front_end/testcases/general/constructor_patch/origin_lib.dart
@@ -2,9 +2,7 @@
// 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.
-import 'extends_test_util.dart';
-
-void main() {
- setUpWithoutES6Syntax();
- testSubtyping();
+class Class {
+ external Class.generative({bool defaultValue: true});
+ external const Class.constGenerative({bool defaultValue: true});
}
diff --git a/pkg/front_end/testcases/general/constructor_patch/patch_lib.dart b/pkg/front_end/testcases/general/constructor_patch/patch_lib.dart
new file mode 100644
index 0000000..0c4899c
--- /dev/null
+++ b/pkg/front_end/testcases/general/constructor_patch/patch_lib.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2020, 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.
+
+// ignore: import_internal_library
+import 'dart:_internal';
+
+@patch
+class Class {
+ final bool defaultValue;
+
+ @patch
+ Class.generative({this.defaultValue: true});
+
+ @patch
+ const Class.constGenerative({this.defaultValue: true});
+}
diff --git a/pkg/front_end/testcases/general/crashes/crash_04/main.dart.weak.expect b/pkg/front_end/testcases/general/crashes/crash_04/main.dart.weak.expect
new file mode 100644
index 0000000..9b02f5d
--- /dev/null
+++ b/pkg/front_end/testcases/general/crashes/crash_04/main.dart.weak.expect
@@ -0,0 +1,32 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/crashes/crash_04/main.dart:1:19: Error: Type 'C' not found.
+// mixin A<T extends C> on D {}
+// ^
+//
+// pkg/front_end/testcases/general/crashes/crash_04/main.dart:1:25: Error: Type 'D' not found.
+// mixin A<T extends C> on D {}
+// ^
+//
+// pkg/front_end/testcases/general/crashes/crash_04/main.dart:3:17: Error: Type 'D' not found.
+// class B extends D with A {}
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A<T extends invalid-type> extends core::Object /*isMixinDeclaration*/ {
+}
+abstract class _B&D&A = core::Object with self::A<invalid-type> /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_B&D&A
+ : super core::Object::•()
+ ;
+}
+class B extends self::_B&D&A {
+ synthetic constructor •() → self::B
+ : super self::_B&D&A::•()
+ ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/crashes/crash_04/main.dart.weak.outline.expect b/pkg/front_end/testcases/general/crashes/crash_04/main.dart.weak.outline.expect
new file mode 100644
index 0000000..e9d2a26
--- /dev/null
+++ b/pkg/front_end/testcases/general/crashes/crash_04/main.dart.weak.outline.expect
@@ -0,0 +1,31 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/crashes/crash_04/main.dart:1:19: Error: Type 'C' not found.
+// mixin A<T extends C> on D {}
+// ^
+//
+// pkg/front_end/testcases/general/crashes/crash_04/main.dart:1:25: Error: Type 'D' not found.
+// mixin A<T extends C> on D {}
+// ^
+//
+// pkg/front_end/testcases/general/crashes/crash_04/main.dart:3:17: Error: Type 'D' not found.
+// class B extends D with A {}
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A<T extends invalid-type> extends core::Object /*isMixinDeclaration*/ {
+}
+abstract class _B&D&A = core::Object with self::A<invalid-type> /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_B&D&A
+ ;
+}
+class B extends self::_B&D&A {
+ synthetic constructor •() → self::B
+ ;
+}
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/general/crashes/crash_04/main.dart.weak.transformed.expect b/pkg/front_end/testcases/general/crashes/crash_04/main.dart.weak.transformed.expect
new file mode 100644
index 0000000..8b03fd8a
--- /dev/null
+++ b/pkg/front_end/testcases/general/crashes/crash_04/main.dart.weak.transformed.expect
@@ -0,0 +1,32 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/crashes/crash_04/main.dart:1:19: Error: Type 'C' not found.
+// mixin A<T extends C> on D {}
+// ^
+//
+// pkg/front_end/testcases/general/crashes/crash_04/main.dart:1:25: Error: Type 'D' not found.
+// mixin A<T extends C> on D {}
+// ^
+//
+// pkg/front_end/testcases/general/crashes/crash_04/main.dart:3:17: Error: Type 'D' not found.
+// class B extends D with A {}
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A<T extends invalid-type> extends core::Object /*isMixinDeclaration*/ {
+}
+abstract class _B&D&A extends core::Object implements self::A<invalid-type> /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor •() → self::_B&D&A
+ : super core::Object::•()
+ ;
+}
+class B extends self::_B&D&A {
+ synthetic constructor •() → self::B
+ : super self::_B&D&A::•()
+ ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/external.dart.weak.expect b/pkg/front_end/testcases/general/external.dart.weak.expect
index ab78ddb..5e9b241 100644
--- a/pkg/front_end/testcases/general/external.dart.weak.expect
+++ b/pkg/front_end/testcases/general/external.dart.weak.expect
@@ -19,5 +19,5 @@
}
constants {
- #C1 = tearoff self::onData
+ #C1 = static-tearoff self::onData
}
diff --git a/pkg/front_end/testcases/general/external.dart.weak.transformed.expect b/pkg/front_end/testcases/general/external.dart.weak.transformed.expect
index ab78ddb..5e9b241 100644
--- a/pkg/front_end/testcases/general/external.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/external.dart.weak.transformed.expect
@@ -19,5 +19,5 @@
}
constants {
- #C1 = tearoff self::onData
+ #C1 = static-tearoff self::onData
}
diff --git a/pkg/front_end/testcases/general/factory_patch/libraries.json b/pkg/front_end/testcases/general/factory_patch/libraries.json
new file mode 100644
index 0000000..154c73c
--- /dev/null
+++ b/pkg/front_end/testcases/general/factory_patch/libraries.json
@@ -0,0 +1,12 @@
+{
+ "none": {
+ "libraries": {
+ "test": {
+ "patches": [
+ "patch_lib.dart"
+ ],
+ "uri": "origin_lib.dart"
+ }
+ }
+ }
+}
diff --git a/tests/lib/js/extends_test/extends_with_es6_subtyping_test.dart b/pkg/front_end/testcases/general/factory_patch/main.dart
similarity index 70%
copy from tests/lib/js/extends_test/extends_with_es6_subtyping_test.dart
copy to pkg/front_end/testcases/general/factory_patch/main.dart
index e6185da..8e6257c 100644
--- a/tests/lib/js/extends_test/extends_with_es6_subtyping_test.dart
+++ b/pkg/front_end/testcases/general/factory_patch/main.dart
@@ -2,9 +2,9 @@
// 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.
-import 'extends_test_util.dart';
+import 'dart:test';
-void main() {
- setUpWithES6Syntax();
- testSubtyping();
+main() {
+ new Class.fact();
+ //const Class.redirect();
}
diff --git a/pkg/front_end/testcases/general/factory_patch/main.dart.textual_outline.expect b/pkg/front_end/testcases/general/factory_patch/main.dart.textual_outline.expect
new file mode 100644
index 0000000..3c9c90e
--- /dev/null
+++ b/pkg/front_end/testcases/general/factory_patch/main.dart.textual_outline.expect
@@ -0,0 +1,3 @@
+import 'dart:test';
+
+main() {}
diff --git a/pkg/front_end/testcases/general/factory_patch/main.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/factory_patch/main.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..3c9c90e
--- /dev/null
+++ b/pkg/front_end/testcases/general/factory_patch/main.dart.textual_outline_modelled.expect
@@ -0,0 +1,3 @@
+import 'dart:test';
+
+main() {}
diff --git a/pkg/front_end/testcases/general/factory_patch/main.dart.weak.expect b/pkg/front_end/testcases/general/factory_patch/main.dart.weak.expect
new file mode 100644
index 0000000..3cddf53
--- /dev/null
+++ b/pkg/front_end/testcases/general/factory_patch/main.dart.weak.expect
@@ -0,0 +1,48 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:test" as test;
+
+import "dart:test";
+
+static method main() → dynamic {
+ test::Class::fact();
+}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/factory_patch/patch_lib.dart:22:52: Error: Can't have a default value here because any default values of 'Class._internal' would be used instead.
+// Try removing the default value.
+// const factory Class.redirect({bool defaultValue: true}) = Class._internal;
+// ^
+//
+import self as test;
+import "dart:_internal" as _in;
+import "dart:core" as core;
+
+import "dart:_internal";
+
+@#C1
+class Class extends core::Object {
+ final field core::bool defaultValue /* from org-dartlang-testcase:///patch_lib.dart */;
+ static final field dynamic _redirecting# = <dynamic>[test::Class::redirect]/*isLegacy*/;
+ const constructor _internal({core::bool defaultValue = #C2}) → test::Class
+ : test::Class::defaultValue = defaultValue, super core::Object::•()
+ ;
+ @#C1
+ static factory /* from org-dartlang-testcase:///patch_lib.dart */ fact({core::bool defaultValue = #C3}) → test::Class
+ return new test::Class::_internal(defaultValue: defaultValue);
+ @#C1
+ static factory /* from org-dartlang-testcase:///patch_lib.dart */ constFact({core::bool defaultValue = #C3}) → test::Class
+ return throw "unsupported";
+ @#C1
+ static factory /* from org-dartlang-testcase:///patch_lib.dart */ redirect({core::bool defaultValue = #C3}) → test::Class
+ let dynamic #redirecting_factory = test::Class::_internal in invalid-expression;
+}
+
+constants {
+ #C1 = _in::_Patch {}
+ #C2 = false
+ #C3 = true
+}
diff --git a/pkg/front_end/testcases/general/factory_patch/main.dart.weak.outline.expect b/pkg/front_end/testcases/general/factory_patch/main.dart.weak.outline.expect
new file mode 100644
index 0000000..62a00f1
--- /dev/null
+++ b/pkg/front_end/testcases/general/factory_patch/main.dart.weak.outline.expect
@@ -0,0 +1,38 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+import "dart:test";
+
+static method main() → dynamic
+ ;
+
+library /*isNonNullableByDefault*/;
+import self as self2;
+import "dart:_internal" as _in;
+import "dart:core" as core;
+
+import "dart:_internal";
+
+@_in::patch
+class Class extends core::Object {
+ final field core::bool defaultValue /* from org-dartlang-testcase:///patch_lib.dart */;
+ static final field dynamic _redirecting# = <dynamic>[self2::Class::redirect]/*isLegacy*/;
+ const constructor _internal({core::bool defaultValue = false}) → self2::Class
+ : self2::Class::defaultValue = defaultValue, super core::Object::•()
+ ;
+ @_in::patch
+ external static factory fact({core::bool defaultValue}) → self2::Class;
+ @_in::patch
+ external static factory constFact({core::bool defaultValue = true}) → self2::Class;
+ @_in::patch
+ static factory /* from org-dartlang-testcase:///patch_lib.dart */ redirect({core::bool defaultValue = true}) → self2::Class
+ let dynamic #redirecting_factory = self2::Class::_internal in invalid-expression;
+}
+
+
+Extra constant evaluation status:
+Evaluated: StaticGet @ org-dartlang-testcase:///origin_lib.dart:6:49 -> InstanceConstant(const _Patch{})
+Evaluated: StaticGet @ org-dartlang-testcase:///origin_lib.dart:8:27 -> InstanceConstant(const _Patch{})
+Evaluated: StaticGet @ (unknown position in org-dartlang-testcase:///origin_lib.dart) -> InstanceConstant(const _Patch{})
+Evaluated: StaticGet @ org-dartlang-testcase:///patch_lib.dart:22:17 -> InstanceConstant(const _Patch{})
+Extra constant evaluation: evaluated: 9, effectively constant: 4
diff --git a/pkg/front_end/testcases/general/factory_patch/main.dart.weak.transformed.expect b/pkg/front_end/testcases/general/factory_patch/main.dart.weak.transformed.expect
new file mode 100644
index 0000000..3cddf53
--- /dev/null
+++ b/pkg/front_end/testcases/general/factory_patch/main.dart.weak.transformed.expect
@@ -0,0 +1,48 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:test" as test;
+
+import "dart:test";
+
+static method main() → dynamic {
+ test::Class::fact();
+}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/factory_patch/patch_lib.dart:22:52: Error: Can't have a default value here because any default values of 'Class._internal' would be used instead.
+// Try removing the default value.
+// const factory Class.redirect({bool defaultValue: true}) = Class._internal;
+// ^
+//
+import self as test;
+import "dart:_internal" as _in;
+import "dart:core" as core;
+
+import "dart:_internal";
+
+@#C1
+class Class extends core::Object {
+ final field core::bool defaultValue /* from org-dartlang-testcase:///patch_lib.dart */;
+ static final field dynamic _redirecting# = <dynamic>[test::Class::redirect]/*isLegacy*/;
+ const constructor _internal({core::bool defaultValue = #C2}) → test::Class
+ : test::Class::defaultValue = defaultValue, super core::Object::•()
+ ;
+ @#C1
+ static factory /* from org-dartlang-testcase:///patch_lib.dart */ fact({core::bool defaultValue = #C3}) → test::Class
+ return new test::Class::_internal(defaultValue: defaultValue);
+ @#C1
+ static factory /* from org-dartlang-testcase:///patch_lib.dart */ constFact({core::bool defaultValue = #C3}) → test::Class
+ return throw "unsupported";
+ @#C1
+ static factory /* from org-dartlang-testcase:///patch_lib.dart */ redirect({core::bool defaultValue = #C3}) → test::Class
+ let dynamic #redirecting_factory = test::Class::_internal in invalid-expression;
+}
+
+constants {
+ #C1 = _in::_Patch {}
+ #C2 = false
+ #C3 = true
+}
diff --git a/pkg/front_end/testcases/general/factory_patch/origin_lib.dart b/pkg/front_end/testcases/general/factory_patch/origin_lib.dart
new file mode 100644
index 0000000..300b31e
--- /dev/null
+++ b/pkg/front_end/testcases/general/factory_patch/origin_lib.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2020, 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 Class {
+ external factory Class.fact({bool defaultValue: true});
+ external const factory Class.constFact({bool defaultValue: true});
+ external const factory Class.redirect({bool defaultValue: true});
+}
diff --git a/pkg/front_end/testcases/general/factory_patch/patch_lib.dart b/pkg/front_end/testcases/general/factory_patch/patch_lib.dart
new file mode 100644
index 0000000..e1fe3fd
--- /dev/null
+++ b/pkg/front_end/testcases/general/factory_patch/patch_lib.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2020, 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.
+
+// ignore: import_internal_library
+import 'dart:_internal';
+
+@patch
+class Class {
+ final bool defaultValue;
+
+ const Class._internal({this.defaultValue: false});
+
+ @patch
+ factory Class.fact({bool defaultValue: true}) =>
+ new Class._internal(defaultValue: defaultValue);
+
+ @patch
+ factory Class.constFact({bool defaultValue: true}) => throw 'unsupported';
+
+ @patch
+ const factory Class.redirect({bool defaultValue: true}) = Class._internal;
+}
diff --git a/pkg/front_end/testcases/general/function_type_assignments.dart.weak.expect b/pkg/front_end/testcases/general/function_type_assignments.dart.weak.expect
index 0d92c04..cc24e09 100644
--- a/pkg/front_end/testcases/general/function_type_assignments.dart.weak.expect
+++ b/pkg/front_end/testcases/general/function_type_assignments.dart.weak.expect
@@ -39,7 +39,7 @@
static method main() → dynamic {}
constants {
- #C1 = tearoff self::identity
- #C2 = tearoff self::identityObject
- #C3 = tearoff self::identityList
+ #C1 = static-tearoff self::identity
+ #C2 = static-tearoff self::identityObject
+ #C3 = static-tearoff self::identityList
}
diff --git a/pkg/front_end/testcases/general/function_type_assignments.dart.weak.transformed.expect b/pkg/front_end/testcases/general/function_type_assignments.dart.weak.transformed.expect
index 0d92c04..cc24e09 100644
--- a/pkg/front_end/testcases/general/function_type_assignments.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/function_type_assignments.dart.weak.transformed.expect
@@ -39,7 +39,7 @@
static method main() → dynamic {}
constants {
- #C1 = tearoff self::identity
- #C2 = tearoff self::identityObject
- #C3 = tearoff self::identityList
+ #C1 = static-tearoff self::identity
+ #C2 = static-tearoff self::identityObject
+ #C3 = static-tearoff self::identityList
}
diff --git a/pkg/front_end/testcases/general/generic_function_type_in_message.dart.weak.expect b/pkg/front_end/testcases/general/generic_function_type_in_message.dart.weak.expect
index 61a26ba..c406e1e 100644
--- a/pkg/front_end/testcases/general/generic_function_type_in_message.dart.weak.expect
+++ b/pkg/front_end/testcases/general/generic_function_type_in_message.dart.weak.expect
@@ -22,5 +22,5 @@
}
constants {
- #C1 = tearoff self::add
+ #C1 = static-tearoff self::add
}
diff --git a/pkg/front_end/testcases/general/generic_function_type_in_message.dart.weak.transformed.expect b/pkg/front_end/testcases/general/generic_function_type_in_message.dart.weak.transformed.expect
index 61a26ba..c406e1e 100644
--- a/pkg/front_end/testcases/general/generic_function_type_in_message.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/generic_function_type_in_message.dart.weak.transformed.expect
@@ -22,5 +22,5 @@
}
constants {
- #C1 = tearoff self::add
+ #C1 = static-tearoff self::add
}
diff --git a/pkg/front_end/testcases/general/getter_call.dart.weak.expect b/pkg/front_end/testcases/general/getter_call.dart.weak.expect
index 9430786..bcf489c 100644
--- a/pkg/front_end/testcases/general/getter_call.dart.weak.expect
+++ b/pkg/front_end/testcases/general/getter_call.dart.weak.expect
@@ -176,12 +176,12 @@
}
constants {
- #C1 = tearoff self::method1
- #C2 = tearoff self::method2
- #C3 = tearoff self::method3
- #C4 = tearoff self::method4
- #C5 = tearoff self::method5
- #C6 = tearoff self::method6
- #C7 = tearoff self::method7
+ #C1 = static-tearoff self::method1
+ #C2 = static-tearoff self::method2
+ #C3 = static-tearoff self::method3
+ #C4 = static-tearoff self::method4
+ #C5 = static-tearoff self::method5
+ #C6 = static-tearoff self::method6
+ #C7 = static-tearoff self::method7
#C8 = 0
}
diff --git a/pkg/front_end/testcases/general/getter_call.dart.weak.transformed.expect b/pkg/front_end/testcases/general/getter_call.dart.weak.transformed.expect
index c9ab79c..1ff1cbc 100644
--- a/pkg/front_end/testcases/general/getter_call.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/getter_call.dart.weak.transformed.expect
@@ -176,13 +176,13 @@
}
constants {
- #C1 = tearoff self::method1
- #C2 = tearoff self::method2
- #C3 = tearoff self::method3
- #C4 = tearoff self::method4
- #C5 = tearoff self::method5
- #C6 = tearoff self::method6
- #C7 = tearoff self::method7
+ #C1 = static-tearoff self::method1
+ #C2 = static-tearoff self::method2
+ #C3 = static-tearoff self::method3
+ #C4 = static-tearoff self::method4
+ #C5 = static-tearoff self::method5
+ #C6 = static-tearoff self::method6
+ #C7 = static-tearoff self::method7
#C8 = 0
}
diff --git a/pkg/front_end/testcases/general/identical_instantiated_function_tearoffs.dart.weak.expect b/pkg/front_end/testcases/general/identical_instantiated_function_tearoffs.dart.weak.expect
index daf6f36..db34700 100644
--- a/pkg/front_end/testcases/general/identical_instantiated_function_tearoffs.dart.weak.expect
+++ b/pkg/front_end/testcases/general/identical_instantiated_function_tearoffs.dart.weak.expect
@@ -22,6 +22,6 @@
}
constants {
- #C1 = tearoff self::id
- #C2 = partial-instantiation self::id <core::int*>
+ #C1 = static-tearoff self::id
+ #C2 = instantiation self::id <core::int*>
}
diff --git a/pkg/front_end/testcases/general/identical_instantiated_function_tearoffs.dart.weak.transformed.expect b/pkg/front_end/testcases/general/identical_instantiated_function_tearoffs.dart.weak.transformed.expect
index e0f574c..acbe826 100644
--- a/pkg/front_end/testcases/general/identical_instantiated_function_tearoffs.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/identical_instantiated_function_tearoffs.dart.weak.transformed.expect
@@ -22,8 +22,8 @@
}
constants {
- #C1 = tearoff self::id
- #C2 = partial-instantiation self::id <core::int*>
+ #C1 = static-tearoff self::id
+ #C2 = instantiation self::id <core::int*>
}
Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/general/invalid_cast.dart.weak.expect b/pkg/front_end/testcases/general/invalid_cast.dart.weak.expect
index 95af468..e123159 100644
--- a/pkg/front_end/testcases/general/invalid_cast.dart.weak.expect
+++ b/pkg/front_end/testcases/general/invalid_cast.dart.weak.expect
@@ -169,6 +169,6 @@
static method main() → dynamic {}
constants {
- #C1 = tearoff self::C::staticFunction
- #C2 = tearoff self::topLevelFunction
+ #C1 = static-tearoff self::C::staticFunction
+ #C2 = static-tearoff self::topLevelFunction
}
diff --git a/pkg/front_end/testcases/general/invalid_cast.dart.weak.transformed.expect b/pkg/front_end/testcases/general/invalid_cast.dart.weak.transformed.expect
index 7cd74f4..c4466eb 100644
--- a/pkg/front_end/testcases/general/invalid_cast.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/invalid_cast.dart.weak.transformed.expect
@@ -169,6 +169,6 @@
static method main() → dynamic {}
constants {
- #C1 = tearoff self::C::staticFunction
- #C2 = tearoff self::topLevelFunction
+ #C1 = static-tearoff self::C::staticFunction
+ #C2 = static-tearoff self::topLevelFunction
}
diff --git a/pkg/front_end/testcases/general/invalid_super_initializer.dart b/pkg/front_end/testcases/general/invalid_super_initializer.dart
new file mode 100644
index 0000000..1e3f1aa
--- /dev/null
+++ b/pkg/front_end/testcases/general/invalid_super_initializer.dart
@@ -0,0 +1,15 @@
+// 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.
+
+abstract class A {}
+
+class B extends A {
+ B(): super()?.foo() {}
+}
+
+bad() {
+ new B();
+}
+
+main() {}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/general/invalid_super_initializer.dart.textual_outline.expect b/pkg/front_end/testcases/general/invalid_super_initializer.dart.textual_outline.expect
new file mode 100644
index 0000000..946f9ea
--- /dev/null
+++ b/pkg/front_end/testcases/general/invalid_super_initializer.dart.textual_outline.expect
@@ -0,0 +1,6 @@
+abstract class A {}
+class B extends A {
+ B(): super()?.foo() {}
+}
+bad() {}
+main() {}
diff --git a/pkg/front_end/testcases/general/invalid_super_initializer.dart.weak.expect b/pkg/front_end/testcases/general/invalid_super_initializer.dart.weak.expect
new file mode 100644
index 0000000..d8ef127
--- /dev/null
+++ b/pkg/front_end/testcases/general/invalid_super_initializer.dart.weak.expect
@@ -0,0 +1,32 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/invalid_super_initializer.dart:8:8: Error: Can't use 'super' as an expression.
+// To delegate a constructor to a super constructor, put the super call as an initializer.
+// B(): super()?.foo() {}
+// ^
+//
+// pkg/front_end/testcases/general/invalid_super_initializer.dart:8:8: Error: Expected an initializer.
+// B(): super()?.foo() {}
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+ synthetic constructor •() → self::A
+ : super core::Object::•()
+ ;
+}
+class B extends self::A {
+ constructor •() → self::B
+ : final dynamic #t1 = let final dynamic #t2 = invalid-expression "pkg/front_end/testcases/general/invalid_super_initializer.dart:8:8: Error: Can't use 'super' as an expression.
+To delegate a constructor to a super constructor, put the super call as an initializer.
+ B(): super()?.foo() {}
+ ^" in #t2 == null ?{dynamic} null : #t2{dynamic}.foo() {}
+}
+static method bad() → dynamic {
+ new self::B::•();
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/invalid_super_initializer.dart.weak.outline.expect b/pkg/front_end/testcases/general/invalid_super_initializer.dart.weak.outline.expect
new file mode 100644
index 0000000..13e0b1e
--- /dev/null
+++ b/pkg/front_end/testcases/general/invalid_super_initializer.dart.weak.outline.expect
@@ -0,0 +1,16 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+ synthetic constructor •() → self::A
+ ;
+}
+class B extends self::A {
+ constructor •() → self::B
+ ;
+}
+static method bad() → dynamic
+ ;
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/general/invalid_super_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/general/invalid_super_initializer.dart.weak.transformed.expect
new file mode 100644
index 0000000..d8ef127
--- /dev/null
+++ b/pkg/front_end/testcases/general/invalid_super_initializer.dart.weak.transformed.expect
@@ -0,0 +1,32 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/invalid_super_initializer.dart:8:8: Error: Can't use 'super' as an expression.
+// To delegate a constructor to a super constructor, put the super call as an initializer.
+// B(): super()?.foo() {}
+// ^
+//
+// pkg/front_end/testcases/general/invalid_super_initializer.dart:8:8: Error: Expected an initializer.
+// B(): super()?.foo() {}
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+ synthetic constructor •() → self::A
+ : super core::Object::•()
+ ;
+}
+class B extends self::A {
+ constructor •() → self::B
+ : final dynamic #t1 = let final dynamic #t2 = invalid-expression "pkg/front_end/testcases/general/invalid_super_initializer.dart:8:8: Error: Can't use 'super' as an expression.
+To delegate a constructor to a super constructor, put the super call as an initializer.
+ B(): super()?.foo() {}
+ ^" in #t2 == null ?{dynamic} null : #t2{dynamic}.foo() {}
+}
+static method bad() → dynamic {
+ new self::B::•();
+}
+static method main() → dynamic {}
diff --git a/pkg/kernel/test/regression_37753_test.dart b/pkg/front_end/testcases/general/issue37753.dart
similarity index 100%
rename from pkg/kernel/test/regression_37753_test.dart
rename to pkg/front_end/testcases/general/issue37753.dart
diff --git a/pkg/front_end/testcases/general/issue37753.dart.textual_outline.expect b/pkg/front_end/testcases/general/issue37753.dart.textual_outline.expect
new file mode 100644
index 0000000..771fd22
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue37753.dart.textual_outline.expect
@@ -0,0 +1,3 @@
+// @dart = 2.9
+Iterable<int> getElements() sync* {}
+main() => print(getElements());
diff --git a/pkg/front_end/testcases/general/issue37753.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/issue37753.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..771fd22
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue37753.dart.textual_outline_modelled.expect
@@ -0,0 +1,3 @@
+// @dart = 2.9
+Iterable<int> getElements() sync* {}
+main() => print(getElements());
diff --git a/pkg/front_end/testcases/general/issue37753.dart.weak.expect b/pkg/front_end/testcases/general/issue37753.dart.weak.expect
new file mode 100644
index 0000000..8ce1e9b
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue37753.dart.weak.expect
@@ -0,0 +1,13 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method getElements() → core::Iterable<core::int*>* sync* {
+ core::Iterable<core::int*>* elements;
+ elements = (() → core::Iterable<core::int*>* sync* {
+ yield 7;
+ })(){() →* core::Iterable<core::int*>*};
+ yield* elements;
+}
+static method main() → dynamic
+ return core::print(self::getElements());
diff --git a/pkg/front_end/testcases/general/issue37753.dart.weak.outline.expect b/pkg/front_end/testcases/general/issue37753.dart.weak.outline.expect
new file mode 100644
index 0000000..2032eab
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue37753.dart.weak.outline.expect
@@ -0,0 +1,8 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method getElements() → core::Iterable<core::int*>* sync*
+ ;
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/general/issue37753.dart.weak.transformed.expect b/pkg/front_end/testcases/general/issue37753.dart.weak.transformed.expect
new file mode 100644
index 0000000..7321092
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue37753.dart.weak.transformed.expect
@@ -0,0 +1,41 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method getElements() → core::Iterable<core::int*>* /* originally sync* */ {
+ function :sync_op_gen() → (core::_SyncIterator<dynamic>*, dynamic, dynamic) →* core::bool* {
+ core::int* :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ function :sync_op(core::_SyncIterator<dynamic>* :iterator, dynamic :exception, dynamic :stack_trace) → core::bool* yielding {
+ {
+ core::Iterable<core::int*>* elements;
+ elements = (() → core::Iterable<core::int*>* /* originally sync* */ {
+ function :sync_op_gen() → (core::_SyncIterator<dynamic>*, dynamic, dynamic) →* core::bool* {
+ core::int* :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ function :sync_op(core::_SyncIterator<dynamic>* :iterator, dynamic :exception, dynamic :stack_trace) → core::bool* yielding {
+ {
+ {
+ :iterator.{core::_SyncIterator::_current} = 7;
+ [yield] true;
+ }
+ }
+ return false;
+ }
+ return :sync_op;
+ }
+ return new core::_SyncIterable::•<core::int*>(:sync_op_gen);
+ })(){() →* core::Iterable<core::int*>*};
+ {
+ :iterator.{core::_SyncIterator::_yieldEachIterable} = elements;
+ [yield] true;
+ }
+ }
+ return false;
+ }
+ return :sync_op;
+ }
+ return new core::_SyncIterable::•<core::int*>(:sync_op_gen);
+}
+static method main() → dynamic
+ return core::print(self::getElements());
diff --git a/pkg/front_end/testcases/general/issue40662.dart b/pkg/front_end/testcases/general/issue40662.dart
index 611fc81..fba166b 100644
--- a/pkg/front_end/testcases/general/issue40662.dart
+++ b/pkg/front_end/testcases/general/issue40662.dart
@@ -3,7 +3,9 @@
// BSD-style license that can be found in the LICENSE file.
//
// Regression test for https://github.com/dart-lang/sdk/issues/40662.
+
// @dart=2.9
+
bar(int a, List<int> b) {
expect(-1, a);
expect(-1, (b[0] - 2));
diff --git a/pkg/front_end/testcases/general/issue40662.dart.weak.transformed.expect b/pkg/front_end/testcases/general/issue40662.dart.weak.transformed.expect
index b5dfa01..90be483 100644
--- a/pkg/front_end/testcases/general/issue40662.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/issue40662.dart.weak.transformed.expect
@@ -17,10 +17,10 @@
core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
- dynamic :async_temporary_0;
- dynamic :async_temporary_1;
+ core::int* :async_temporary_0;
+ core::int* :async_temporary_1;
core::List<core::int*>* :async_temporary_2;
- dynamic :async_temporary_3;
+ core::int* :async_temporary_3;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
#L1:
@@ -35,7 +35,7 @@
else {
:async_temporary_2 = null;
}
- :return_value = self::bar(_in::unsafeCast<core::int*>(:async_temporary_3), :async_temporary_2);
+ :return_value = self::bar(_in::unsafeCast<core::int*>(:async_temporary_3), _in::unsafeCast<core::List<core::int*>*>(:async_temporary_2));
break #L1;
}
asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
@@ -86,6 +86,6 @@
Extra constant evaluation status:
-Evaluated: InstanceInvocation @ org-dartlang-testcase:///issue40662.dart:8:10 -> IntConstant(-1)
-Evaluated: InstanceInvocation @ org-dartlang-testcase:///issue40662.dart:9:10 -> IntConstant(-1)
-Extra constant evaluation: evaluated: 93, effectively constant: 2
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///issue40662.dart:10:10 -> IntConstant(-1)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///issue40662.dart:11:10 -> IntConstant(-1)
+Extra constant evaluation: evaluated: 94, effectively constant: 2
diff --git a/pkg/front_end/testcases/general/issue44007.dart b/pkg/front_end/testcases/general/issue44007.dart
new file mode 100644
index 0000000..9e5ebd9
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue44007.dart
@@ -0,0 +1,19 @@
+// 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.
+
+void test() {
+ var list = [
+ DateTime.now().add(Duration(days: 3)),
+ DateTime.now().add(Duration(days: 2)),
+ DateTime.now(),
+ DateTime.now().subtract(Duration(days: 1))
+ ];
+
+ list.sort((a, b) => a.compareTo(b));
+ print(list);
+
+ print(DateTime.parse(2019-01-17 00:00:00.000));
+}
+
+main() {}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/general/issue44007.dart.textual_outline.expect b/pkg/front_end/testcases/general/issue44007.dart.textual_outline.expect
new file mode 100644
index 0000000..31c91a2
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue44007.dart.textual_outline.expect
@@ -0,0 +1,2 @@
+void test() {}
+main() {}
diff --git a/pkg/front_end/testcases/general/issue44007.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/issue44007.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..4742c78
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue44007.dart.textual_outline_modelled.expect
@@ -0,0 +1,2 @@
+main() {}
+void test() {}
diff --git a/pkg/front_end/testcases/general/issue44007.dart.weak.expect b/pkg/front_end/testcases/general/issue44007.dart.weak.expect
new file mode 100644
index 0000000..efd3a92
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue44007.dart.weak.expect
@@ -0,0 +1,35 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/issue44007.dart:16:35: Error: Expected ',' before this.
+// print(DateTime.parse(2019-01-17 00:00:00.000));
+// ^^
+//
+// pkg/front_end/testcases/general/issue44007.dart:16:35: Error: Expected an identifier, but got '00'.
+// Try inserting an identifier before '00'.
+// print(DateTime.parse(2019-01-17 00:00:00.000));
+// ^^
+//
+// pkg/front_end/testcases/general/issue44007.dart:16:40: Error: Expected ')' before this.
+// print(DateTime.parse(2019-01-17 00:00:00.000));
+// ^
+//
+// pkg/front_end/testcases/general/issue44007.dart:16:18: Error: Expected an identifier, but got 'parse'.
+// Try inserting an identifier before 'parse'.
+// print(DateTime.parse(2019-01-17 00:00:00.000));
+// ^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+static method test() → void {
+ core::List<core::DateTime> list = <core::DateTime>[new core::DateTime::now().{core::DateTime::add}(new core::Duration::•(days: 3)){(core::Duration) → core::DateTime}, new core::DateTime::now().{core::DateTime::add}(new core::Duration::•(days: 2)){(core::Duration) → core::DateTime}, new core::DateTime::now(), new core::DateTime::now().{core::DateTime::subtract}(new core::Duration::•(days: 1)){(core::Duration) → core::DateTime}];
+ list.{core::List::sort}((core::DateTime a, core::DateTime b) → core::int => a.{core::DateTime::compareTo}(b){(core::DateTime) → core::int}){([(core::DateTime, core::DateTime) →? core::int]) → void};
+ core::print(list);
+ core::print(invalid-expression "pkg/front_end/testcases/general/issue44007.dart:16:18: Error: Expected an identifier, but got 'parse'.
+Try inserting an identifier before 'parse'.
+ print(DateTime.parse(2019-01-17 00:00:00.000));
+ ^^^^^");
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/issue44007.dart.weak.outline.expect b/pkg/front_end/testcases/general/issue44007.dart.weak.outline.expect
new file mode 100644
index 0000000..d7d3d2f
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue44007.dart.weak.outline.expect
@@ -0,0 +1,7 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+static method test() → void
+ ;
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/general/issue44007.dart.weak.transformed.expect b/pkg/front_end/testcases/general/issue44007.dart.weak.transformed.expect
new file mode 100644
index 0000000..244d264
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue44007.dart.weak.transformed.expect
@@ -0,0 +1,35 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/issue44007.dart:16:35: Error: Expected ',' before this.
+// print(DateTime.parse(2019-01-17 00:00:00.000));
+// ^^
+//
+// pkg/front_end/testcases/general/issue44007.dart:16:35: Error: Expected an identifier, but got '00'.
+// Try inserting an identifier before '00'.
+// print(DateTime.parse(2019-01-17 00:00:00.000));
+// ^^
+//
+// pkg/front_end/testcases/general/issue44007.dart:16:40: Error: Expected ')' before this.
+// print(DateTime.parse(2019-01-17 00:00:00.000));
+// ^
+//
+// pkg/front_end/testcases/general/issue44007.dart:16:18: Error: Expected an identifier, but got 'parse'.
+// Try inserting an identifier before 'parse'.
+// print(DateTime.parse(2019-01-17 00:00:00.000));
+// ^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+static method test() → void {
+ core::List<core::DateTime> list = core::_GrowableList::_literal4<core::DateTime>(new core::DateTime::now().{core::DateTime::add}(new core::Duration::•(days: 3)){(core::Duration) → core::DateTime}, new core::DateTime::now().{core::DateTime::add}(new core::Duration::•(days: 2)){(core::Duration) → core::DateTime}, new core::DateTime::now(), new core::DateTime::now().{core::DateTime::subtract}(new core::Duration::•(days: 1)){(core::Duration) → core::DateTime});
+ list.{core::List::sort}((core::DateTime a, core::DateTime b) → core::int => a.{core::DateTime::compareTo}(b){(core::DateTime) → core::int}){([(core::DateTime, core::DateTime) →? core::int]) → void};
+ core::print(list);
+ core::print(invalid-expression "pkg/front_end/testcases/general/issue44007.dart:16:18: Error: Expected an identifier, but got 'parse'.
+Try inserting an identifier before 'parse'.
+ print(DateTime.parse(2019-01-17 00:00:00.000));
+ ^^^^^");
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/issue44347.dart b/pkg/front_end/testcases/general/issue44347.dart
index 2d9a01e..074b4e5 100644
--- a/pkg/front_end/testcases/general/issue44347.dart
+++ b/pkg/front_end/testcases/general/issue44347.dart
@@ -1,7 +1,9 @@
// Copyright (c) 2020, 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.
+
// @dart=2.9
+
test() {
Set<int>.();
}
diff --git a/pkg/front_end/testcases/general/issue44347.dart.weak.expect b/pkg/front_end/testcases/general/issue44347.dart.weak.expect
index 23f91b5..fc179e1 100644
--- a/pkg/front_end/testcases/general/issue44347.dart.weak.expect
+++ b/pkg/front_end/testcases/general/issue44347.dart.weak.expect
@@ -2,17 +2,17 @@
//
// Problems in library:
//
-// pkg/front_end/testcases/general/issue44347.dart:6:6: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
+// pkg/front_end/testcases/general/issue44347.dart:8:6: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
// Set<int>.();
// ^
//
-// pkg/front_end/testcases/general/issue44347.dart:6:13: Error: Expected an identifier, but got ')'.
+// pkg/front_end/testcases/general/issue44347.dart:8:13: Error: Expected an identifier, but got ')'.
// Try inserting an identifier before ')'.
// Set<int>.();
// ^
//
-// pkg/front_end/testcases/general/issue44347.dart:6:12: Error: Expected an identifier, but got '('.
+// pkg/front_end/testcases/general/issue44347.dart:8:12: Error: Expected an identifier, but got '('.
// Try inserting an identifier before '('.
// Set<int>.();
// ^
@@ -20,7 +20,7 @@
import self as self;
static method test() → dynamic {
- invalid-expression "pkg/front_end/testcases/general/issue44347.dart:6:12: Error: Expected an identifier, but got '('.
+ invalid-expression "pkg/front_end/testcases/general/issue44347.dart:8:12: Error: Expected an identifier, but got '('.
Try inserting an identifier before '('.
Set<int>.();
^";
diff --git a/pkg/front_end/testcases/general/issue44347.dart.weak.transformed.expect b/pkg/front_end/testcases/general/issue44347.dart.weak.transformed.expect
index 23f91b5..fc179e1 100644
--- a/pkg/front_end/testcases/general/issue44347.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/issue44347.dart.weak.transformed.expect
@@ -2,17 +2,17 @@
//
// Problems in library:
//
-// pkg/front_end/testcases/general/issue44347.dart:6:6: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
+// pkg/front_end/testcases/general/issue44347.dart:8:6: Error: This requires the 'constructor-tearoffs' language feature to be enabled.
// Try updating your pubspec.yaml to set the minimum SDK constraint to 2.14 or higher, and running 'pub get'.
// Set<int>.();
// ^
//
-// pkg/front_end/testcases/general/issue44347.dart:6:13: Error: Expected an identifier, but got ')'.
+// pkg/front_end/testcases/general/issue44347.dart:8:13: Error: Expected an identifier, but got ')'.
// Try inserting an identifier before ')'.
// Set<int>.();
// ^
//
-// pkg/front_end/testcases/general/issue44347.dart:6:12: Error: Expected an identifier, but got '('.
+// pkg/front_end/testcases/general/issue44347.dart:8:12: Error: Expected an identifier, but got '('.
// Try inserting an identifier before '('.
// Set<int>.();
// ^
@@ -20,7 +20,7 @@
import self as self;
static method test() → dynamic {
- invalid-expression "pkg/front_end/testcases/general/issue44347.dart:6:12: Error: Expected an identifier, but got '('.
+ invalid-expression "pkg/front_end/testcases/general/issue44347.dart:8:12: Error: Expected an identifier, but got '('.
Try inserting an identifier before '('.
Set<int>.();
^";
diff --git a/pkg/front_end/testcases/general/issue44733.dart b/pkg/front_end/testcases/general/issue44733.dart
new file mode 100644
index 0000000..92227d1
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue44733.dart
@@ -0,0 +1,25 @@
+// 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.
+
+abstract class B extends A with C {}
+
+mixin C on D {}
+
+B get x => super.x;
+void f() {
+ switch (x.y.z) {
+ }
+}
+
+abstract class E {}
+
+abstract class D {
+ E get y {}
+}
+
+abstract class A {
+ F get y => super.y as F;
+}
+
+main() {}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/general/issue44733.dart.textual_outline.expect b/pkg/front_end/testcases/general/issue44733.dart.textual_outline.expect
new file mode 100644
index 0000000..7fafd11
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue44733.dart.textual_outline.expect
@@ -0,0 +1,17 @@
+abstract class B extends A with C {}
+
+mixin C on D {}
+B get x => super.x;
+void f() {}
+
+abstract class E {}
+
+abstract class D {
+ E get y {}
+}
+
+abstract class A {
+ F get y => super.y as F;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/issue44733.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/issue44733.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..ba7e44d
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue44733.dart.textual_outline_modelled.expect
@@ -0,0 +1,17 @@
+B get x => super.x;
+
+abstract class A {
+ F get y => super.y as F;
+}
+
+abstract class B extends A with C {}
+
+abstract class D {
+ E get y {}
+}
+
+abstract class E {}
+
+main() {}
+mixin C on D {}
+void f() {}
diff --git a/pkg/front_end/testcases/general/issue44733.dart.weak.expect b/pkg/front_end/testcases/general/issue44733.dart.weak.expect
new file mode 100644
index 0000000..186db3f
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue44733.dart.weak.expect
@@ -0,0 +1,79 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/issue44733.dart:22:3: Error: Type 'F' not found.
+// F get y => super.y as F;
+// ^
+//
+// pkg/front_end/testcases/general/issue44733.dart:5:16: Error: 'A' doesn't implement 'D' so it can't be used with 'C'.
+// - 'A' is from 'pkg/front_end/testcases/general/issue44733.dart'.
+// - 'D' is from 'pkg/front_end/testcases/general/issue44733.dart'.
+// - 'C' is from 'pkg/front_end/testcases/general/issue44733.dart'.
+// abstract class B extends A with C {}
+// ^
+//
+// pkg/front_end/testcases/general/issue44733.dart:9:12: Error: Expected identifier, but got 'super'.
+// B get x => super.x;
+// ^^^^^
+//
+// pkg/front_end/testcases/general/issue44733.dart:18:9: Error: A non-null value must be returned since the return type 'E' doesn't allow null.
+// - 'E' is from 'pkg/front_end/testcases/general/issue44733.dart'.
+// E get y {}
+// ^
+//
+// pkg/front_end/testcases/general/issue44733.dart:22:25: Error: 'F' isn't a type.
+// F get y => super.y as F;
+// ^
+//
+// pkg/front_end/testcases/general/issue44733.dart:22:20: Error: Superclass has no getter named 'y'.
+// F get y => super.y as F;
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class _B&A&C = self::A with self::C /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_B&A&C
+ : super self::A::•()
+ ;
+}
+abstract class B extends self::_B&A&C {
+ synthetic constructor •() → self::B
+ : super self::_B&A&C::•()
+ ;
+}
+abstract class C extends self::D /*isMixinDeclaration*/ {
+}
+abstract class E extends core::Object {
+ synthetic constructor •() → self::E
+ : super core::Object::•()
+ ;
+}
+abstract class D extends core::Object {
+ synthetic constructor •() → self::D
+ : super core::Object::•()
+ ;
+ get y() → self::E {
+ return let final Never #t1 = invalid-expression "pkg/front_end/testcases/general/issue44733.dart:18:9: Error: A non-null value must be returned since the return type 'E' doesn't allow null.
+ - 'E' is from 'pkg/front_end/testcases/general/issue44733.dart'.
+ E get y {}
+ ^" in null;
+ }
+}
+abstract class A extends core::Object {
+ synthetic constructor •() → self::A
+ : super core::Object::•()
+ ;
+ get y() → invalid-type
+ return super.y as{ForNonNullableByDefault} invalid-type;
+}
+static get x() → self::B
+ return invalid-expression "pkg/front_end/testcases/general/issue44733.dart:9:12: Error: Expected identifier, but got 'super'.
+B get x => super.x;
+ ^^^^^"{dynamic}.x as{TypeError,ForDynamic,ForNonNullableByDefault} self::B;
+static method f() → void {
+ switch(self::x.{self::A::y}{invalid-type}{<invalid>}.z) {
+ }
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/issue44733.dart.weak.outline.expect b/pkg/front_end/testcases/general/issue44733.dart.weak.outline.expect
new file mode 100644
index 0000000..b1f8519
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue44733.dart.weak.outline.expect
@@ -0,0 +1,51 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/issue44733.dart:22:3: Error: Type 'F' not found.
+// F get y => super.y as F;
+// ^
+//
+// pkg/front_end/testcases/general/issue44733.dart:5:16: Error: 'A' doesn't implement 'D' so it can't be used with 'C'.
+// - 'A' is from 'pkg/front_end/testcases/general/issue44733.dart'.
+// - 'D' is from 'pkg/front_end/testcases/general/issue44733.dart'.
+// - 'C' is from 'pkg/front_end/testcases/general/issue44733.dart'.
+// abstract class B extends A with C {}
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class _B&A&C = self::A with self::C /*isAnonymousMixin*/ {
+ synthetic constructor •() → self::_B&A&C
+ : super self::A::•()
+ ;
+}
+abstract class B extends self::_B&A&C {
+ synthetic constructor •() → self::B
+ ;
+}
+abstract class C extends self::D /*isMixinDeclaration*/ {
+}
+abstract class E extends core::Object {
+ synthetic constructor •() → self::E
+ ;
+}
+abstract class D extends core::Object {
+ synthetic constructor •() → self::D
+ ;
+ get y() → self::E
+ ;
+}
+abstract class A extends core::Object {
+ synthetic constructor •() → self::A
+ ;
+ get y() → invalid-type
+ ;
+}
+static get x() → self::B
+ ;
+static method f() → void
+ ;
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/general/issue45101/main.dart.weak.outline.expect b/pkg/front_end/testcases/general/issue45101/main.dart.weak.outline.expect
index c56c375..68f366e 100644
--- a/pkg/front_end/testcases/general/issue45101/main.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/general/issue45101/main.dart.weak.outline.expect
@@ -34,7 +34,7 @@
class Array<T extends core::Object* = dynamic> extends core::Object {
static final field dynamic _redirecting# = <dynamic>[self2::Array::•];
@_in::patch
- external static factory •<T extends core::Object* = dynamic>(core::int* foo) → self2::Array<self2::Array::•::T*>*
+ static factory /* from org-dartlang-testcase:///patch_lib.dart */ •<T extends core::Object* = dynamic>(core::int* foo) → self2::Array<self2::Array::•::T*>*
let dynamic #redirecting_factory = self2::_ArraySize::• in let self2::Array::•::T* #typeArg0 = null in invalid-expression;
abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
@@ -52,5 +52,5 @@
Extra constant evaluation status:
Evaluated: StaticGet @ org-dartlang-testcase:///origin_lib.dart:10:1 -> InstanceConstant(const _Patch{})
Evaluated: ConstructorInvocation @ (unknown position in org-dartlang-testcase:///origin_lib.dart) -> InstanceConstant(const pragma{pragma.name: "vm:entry-point", pragma.options: null})
-Evaluated: StaticGet @ (unknown position in org-dartlang-testcase:///origin_lib.dart) -> InstanceConstant(const _Patch{})
+Evaluated: StaticGet @ org-dartlang-testcase:///patch_lib.dart:14:17 -> InstanceConstant(const _Patch{})
Extra constant evaluation: evaluated: 9, effectively constant: 3
diff --git a/pkg/front_end/testcases/general/issue46745.dart b/pkg/front_end/testcases/general/issue46745.dart
new file mode 100644
index 0000000..8eb5b1b
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue46745.dart
@@ -0,0 +1,11 @@
+// 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 A {
+ A._();
+ factory A.foo() => A._();
+ A.foo();
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/issue46745.dart.textual_outline.expect b/pkg/front_end/testcases/general/issue46745.dart.textual_outline.expect
new file mode 100644
index 0000000..59dd347
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue46745.dart.textual_outline.expect
@@ -0,0 +1,7 @@
+class A {
+ A._();
+ factory A.foo() => A._();
+ A.foo();
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/issue46745.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/issue46745.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..77788ac
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue46745.dart.textual_outline_modelled.expect
@@ -0,0 +1,7 @@
+class A {
+ A._();
+ A.foo();
+ factory A.foo() => A._();
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/issue46745.dart.weak.expect b/pkg/front_end/testcases/general/issue46745.dart.weak.expect
new file mode 100644
index 0000000..a375575
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue46745.dart.weak.expect
@@ -0,0 +1,22 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/issue46745.dart:8:3: Error: 'A.foo' is already declared in this scope.
+// A.foo();
+// ^^^^^
+// pkg/front_end/testcases/general/issue46745.dart:7:11: Context: Previous declaration of 'A.foo'.
+// factory A.foo() => A._();
+// ^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ constructor _() → self::A
+ : super core::Object::•()
+ ;
+ static factory foo() → self::A
+ return new self::A::_();
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/issue46745.dart.weak.outline.expect b/pkg/front_end/testcases/general/issue46745.dart.weak.outline.expect
new file mode 100644
index 0000000..eb5a0eb
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue46745.dart.weak.outline.expect
@@ -0,0 +1,22 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/issue46745.dart:8:3: Error: 'A.foo' is already declared in this scope.
+// A.foo();
+// ^^^^^
+// pkg/front_end/testcases/general/issue46745.dart:7:11: Context: Previous declaration of 'A.foo'.
+// factory A.foo() => A._();
+// ^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ constructor _() → self::A
+ ;
+ static factory foo() → self::A
+ ;
+}
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/general/issue46745.dart.weak.transformed.expect b/pkg/front_end/testcases/general/issue46745.dart.weak.transformed.expect
new file mode 100644
index 0000000..a375575
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue46745.dart.weak.transformed.expect
@@ -0,0 +1,22 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/issue46745.dart:8:3: Error: 'A.foo' is already declared in this scope.
+// A.foo();
+// ^^^^^
+// pkg/front_end/testcases/general/issue46745.dart:7:11: Context: Previous declaration of 'A.foo'.
+// factory A.foo() => A._();
+// ^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ constructor _() → self::A
+ : super core::Object::•()
+ ;
+ static factory foo() → self::A
+ return new self::A::_();
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/redirecting_factory_default_value.dart b/pkg/front_end/testcases/general/redirecting_factory_default_value.dart
new file mode 100644
index 0000000..9a68b87
--- /dev/null
+++ b/pkg/front_end/testcases/general/redirecting_factory_default_value.dart
@@ -0,0 +1,22 @@
+// 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 A {
+ final int field;
+
+ A([this.field = 42]);
+
+ factory A.redirect([int field = 87]) = A;
+}
+
+main() {
+ expect(42, new A().field);
+ expect(123, new A(123).field);
+ expect(42, new A.redirect().field);
+ expect(123, new A.redirect(123).field);
+}
+
+expect(expected, actual) {
+ if (expected != actual) throw 'Expected $expected, actual $actual';
+}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/general/redirecting_factory_default_value.dart.textual_outline.expect b/pkg/front_end/testcases/general/redirecting_factory_default_value.dart.textual_outline.expect
new file mode 100644
index 0000000..6351dd7
--- /dev/null
+++ b/pkg/front_end/testcases/general/redirecting_factory_default_value.dart.textual_outline.expect
@@ -0,0 +1,8 @@
+class A {
+ final int field;
+ A([this.field = 42]);
+ factory A.redirect([int field = 87]) = A;
+}
+
+main() {}
+expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/general/redirecting_factory_default_value.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/redirecting_factory_default_value.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..23adf6f
--- /dev/null
+++ b/pkg/front_end/testcases/general/redirecting_factory_default_value.dart.textual_outline_modelled.expect
@@ -0,0 +1,8 @@
+class A {
+ A([this.field = 42]);
+ factory A.redirect([int field = 87]) = A;
+ final int field;
+}
+
+expect(expected, actual) {}
+main() {}
diff --git a/pkg/front_end/testcases/general/redirecting_factory_default_value.dart.weak.expect b/pkg/front_end/testcases/general/redirecting_factory_default_value.dart.weak.expect
new file mode 100644
index 0000000..1e7a7cc4
--- /dev/null
+++ b/pkg/front_end/testcases/general/redirecting_factory_default_value.dart.weak.expect
@@ -0,0 +1,35 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/redirecting_factory_default_value.dart:10:35: Error: Can't have a default value here because any default values of 'A' would be used instead.
+// Try removing the default value.
+// factory A.redirect([int field = 87]) = A;
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ final field core::int field;
+ static final field dynamic _redirecting# = <dynamic>[self::A::redirect]/*isLegacy*/;
+ constructor •([core::int field = #C1]) → self::A
+ : self::A::field = field, super core::Object::•()
+ ;
+ static factory redirect([core::int field]) → self::A
+ let dynamic #redirecting_factory = self::A::• in invalid-expression;
+}
+static method main() → dynamic {
+ self::expect(42, new self::A::•().{self::A::field}{core::int});
+ self::expect(123, new self::A::•(123).{self::A::field}{core::int});
+ self::expect(42, new self::A::•().{self::A::field}{core::int});
+ self::expect(123, new self::A::•(123).{self::A::field}{core::int});
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+
+constants {
+ #C1 = 42
+}
diff --git a/pkg/front_end/testcases/general/redirecting_factory_default_value.dart.weak.outline.expect b/pkg/front_end/testcases/general/redirecting_factory_default_value.dart.weak.outline.expect
new file mode 100644
index 0000000..352e5d1
--- /dev/null
+++ b/pkg/front_end/testcases/general/redirecting_factory_default_value.dart.weak.outline.expect
@@ -0,0 +1,16 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ final field core::int field;
+ static final field dynamic _redirecting# = <dynamic>[self::A::redirect]/*isLegacy*/;
+ constructor •([core::int field]) → self::A
+ ;
+ static factory redirect([core::int field]) → self::A
+ let dynamic #redirecting_factory = self::A::• in invalid-expression;
+}
+static method main() → dynamic
+ ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+ ;
diff --git a/pkg/front_end/testcases/general/redirecting_factory_default_value.dart.weak.transformed.expect b/pkg/front_end/testcases/general/redirecting_factory_default_value.dart.weak.transformed.expect
new file mode 100644
index 0000000..6b1dd68
--- /dev/null
+++ b/pkg/front_end/testcases/general/redirecting_factory_default_value.dart.weak.transformed.expect
@@ -0,0 +1,35 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/redirecting_factory_default_value.dart:10:35: Error: Can't have a default value here because any default values of 'A' would be used instead.
+// Try removing the default value.
+// factory A.redirect([int field = 87]) = A;
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ final field core::int field;
+ static final field dynamic _redirecting# = <dynamic>[self::A::redirect]/*isLegacy*/;
+ constructor •([core::int field = #C1]) → self::A
+ : self::A::field = field, super core::Object::•()
+ ;
+ static factory redirect([core::int field]) → self::A
+ let Never #redirecting_factory = self::A::• in invalid-expression;
+}
+static method main() → dynamic {
+ self::expect(42, new self::A::•().{self::A::field}{core::int});
+ self::expect(123, new self::A::•(123).{self::A::field}{core::int});
+ self::expect(42, new self::A::•().{self::A::field}{core::int});
+ self::expect(123, new self::A::•(123).{self::A::field}{core::int});
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+
+constants {
+ #C1 = 42
+}
diff --git a/pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart b/pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart
new file mode 100644
index 0000000..d12b28b
--- /dev/null
+++ b/pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart
@@ -0,0 +1,63 @@
+// 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.md file.
+
+class Class1 {
+ int field = 0;
+
+ factory Class1() = Class1._;
+
+ Class1._();
+
+ int get getter => 0;
+}
+
+class Class2 extends Class1 {
+ final Class2 _c2;
+
+ Class2(this._c2) : super._() {
+ // Invocation inside an invalid unary expression.
+ -new Class1();
+ // Invocation inside an invalid binary expression.
+ ('' + '') - new Class1();
+ // Invocation inside an invalid index set.
+ (0 + 1)[0] = new Class1();
+ _c2[0] = new Class1();
+ // Invocation inside an invalid index get.
+ (0 + 1)[new Class1()];
+ // Invocation inside an invalid property get.
+ new Class1().foo;
+ // Invocation inside an invalid property set.
+ (0 + 1).foo = new Class1();
+ // Invocation inside an invalid invocation.
+ new Class1().foo();
+ // Invocation inside an invalid implicit call invocation.
+ new Class1()();
+ // Invocation inside an invalid implicit field invocation.
+ new Class1().field();
+ // Invocation inside an invalid implicit getter invocation.
+ new Class1().getter();
+ // Invocation inside an invalid implicit call-getter invocation.
+ _c2(new Class1());
+ // Duplicate named arguments
+ method(a: 0, a: new Class1());
+ // Triple named arguments
+ method(a: 0, a: 1, a: new Class1());
+ // Invocation inside an invalid super index get.
+ super[new Class1()];
+ // Invocation inside an invalid super index set.
+ super[0] = new Class1();
+ // Invocation inside an invalid super set.
+ super.foo = new Class1();
+ // Invocation inside an invalid super invocation.
+ super.foo(new Class1());
+ // Invocation inside an invalid super binary.
+ super + new Class1();
+ }
+
+ method({a}) {}
+
+ int get call => 0;
+}
+
+main() {}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart.textual_outline.expect b/pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart.textual_outline.expect
new file mode 100644
index 0000000..607b231
--- /dev/null
+++ b/pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart.textual_outline.expect
@@ -0,0 +1,15 @@
+class Class1 {
+ int field = 0;
+ factory Class1() = Class1._;
+ Class1._();
+ int get getter => 0;
+}
+
+class Class2 extends Class1 {
+ final Class2 _c2;
+ Class2(this._c2) : super._() {}
+ method({a}) {}
+ int get call => 0;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..ca3ab16
--- /dev/null
+++ b/pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart.textual_outline_modelled.expect
@@ -0,0 +1,15 @@
+class Class1 {
+ Class1._();
+ factory Class1() = Class1._;
+ int field = 0;
+ int get getter => 0;
+}
+
+class Class2 extends Class1 {
+ Class2(this._c2) : super._() {}
+ final Class2 _c2;
+ int get call => 0;
+ method({a}) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart.weak.expect b/pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart.weak.expect
new file mode 100644
index 0000000..232d5ac
--- /dev/null
+++ b/pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart.weak.expect
@@ -0,0 +1,187 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:47:10: Error: Superclass has no method named '[]'.
+// super[new Class1()];
+// ^
+//
+// pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:49:10: Error: Superclass has no method named '[]='.
+// super[0] = new Class1();
+// ^
+//
+// pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:51:11: Error: Superclass has no setter named 'foo'.
+// super.foo = new Class1();
+// ^^^
+//
+// pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:53:11: Error: Superclass has no method named 'foo'.
+// super.foo(new Class1());
+// ^^^
+//
+// pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:55:11: Error: Superclass has no method named '+'.
+// super + new Class1();
+// ^
+//
+// pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:20:5: Error: The operator 'unary-' isn't defined for the class 'Class1'.
+// - 'Class1' is from 'pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart'.
+// Try correcting the operator to an existing operator, or defining a 'unary-' operator.
+// -new Class1();
+// ^
+//
+// pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:22:15: Error: The operator '-' isn't defined for the class 'String'.
+// Try correcting the operator to an existing operator, or defining a '-' operator.
+// ('' + '') - new Class1();
+// ^
+//
+// pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:24:12: Error: The operator '[]=' isn't defined for the class 'int'.
+// Try correcting the operator to an existing operator, or defining a '[]=' operator.
+// (0 + 1)[0] = new Class1();
+// ^
+//
+// pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:25:8: Error: The operator '[]=' isn't defined for the class 'Class2'.
+// - 'Class2' is from 'pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart'.
+// Try correcting the operator to an existing operator, or defining a '[]=' operator.
+// _c2[0] = new Class1();
+// ^
+//
+// pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:27:12: Error: The operator '[]' isn't defined for the class 'int'.
+// Try correcting the operator to an existing operator, or defining a '[]' operator.
+// (0 + 1)[new Class1()];
+// ^
+//
+// pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:29:18: Error: The getter 'foo' isn't defined for the class 'Class1'.
+// - 'Class1' is from 'pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'foo'.
+// new Class1().foo;
+// ^^^
+//
+// pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:31:13: Error: The setter 'foo' isn't defined for the class 'int'.
+// Try correcting the name to the name of an existing setter, or defining a setter or field named 'foo'.
+// (0 + 1).foo = new Class1();
+// ^^^
+//
+// pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:33:18: Error: The method 'foo' isn't defined for the class 'Class1'.
+// - 'Class1' is from 'pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart'.
+// Try correcting the name to the name of an existing method, or defining a method named 'foo'.
+// new Class1().foo();
+// ^^^
+//
+// pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:35:17: Error: The method 'call' isn't defined for the class 'Class1'.
+// - 'Class1' is from 'pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart'.
+// Try correcting the name to the name of an existing method, or defining a method named 'call'.
+// new Class1()();
+// ^
+//
+// pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:37:23: Error: 'field' isn't a function or method and can't be invoked.
+// new Class1().field();
+// ^^^^...
+//
+// pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:39:24: Error: 'getter' isn't a function or method and can't be invoked.
+// new Class1().getter();
+// ^^^^...
+//
+// pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:41:8: Error: 'call' isn't a function or method and can't be invoked.
+// _c2(new Class1());
+// ^^^^
+//
+// pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:43:18: Error: Duplicated named argument 'a'.
+// method(a: 0, a: new Class1());
+// ^
+//
+// pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:45:18: Error: Duplicated named argument 'a'.
+// method(a: 0, a: 1, a: new Class1());
+// ^
+//
+// pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:45:24: Error: Duplicated named argument 'a'.
+// method(a: 0, a: 1, a: new Class1());
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+ field core::int field = 0;
+ static final field dynamic _redirecting# = <dynamic>[self::Class1::•]/*isLegacy*/;
+ constructor _() → self::Class1
+ : super core::Object::•()
+ ;
+ static factory •() → self::Class1
+ let dynamic #redirecting_factory = self::Class1::_ in invalid-expression;
+ get getter() → core::int
+ return 0;
+}
+class Class2 extends self::Class1 {
+ final field self::Class2 _c2;
+ constructor •(self::Class2 _c2) → self::Class2
+ : self::Class2::_c2 = _c2, super self::Class1::_() {
+ invalid-expression "pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:20:5: Error: The operator 'unary-' isn't defined for the class 'Class1'.
+ - 'Class1' is from 'pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart'.
+Try correcting the operator to an existing operator, or defining a 'unary-' operator.
+ -new Class1();
+ ^";
+ invalid-expression "pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:22:15: Error: The operator '-' isn't defined for the class 'String'.
+Try correcting the operator to an existing operator, or defining a '-' operator.
+ ('' + '') - new Class1();
+ ^";
+ invalid-expression "pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:24:12: Error: The operator '[]=' isn't defined for the class 'int'.
+Try correcting the operator to an existing operator, or defining a '[]=' operator.
+ (0 + 1)[0] = new Class1();
+ ^";
+ invalid-expression "pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:25:8: Error: The operator '[]=' isn't defined for the class 'Class2'.
+ - 'Class2' is from 'pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart'.
+Try correcting the operator to an existing operator, or defining a '[]=' operator.
+ _c2[0] = new Class1();
+ ^";
+ invalid-expression "pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:27:12: Error: The operator '[]' isn't defined for the class 'int'.
+Try correcting the operator to an existing operator, or defining a '[]' operator.
+ (0 + 1)[new Class1()];
+ ^";
+ invalid-expression "pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:29:18: Error: The getter 'foo' isn't defined for the class 'Class1'.
+ - 'Class1' is from 'pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'foo'.
+ new Class1().foo;
+ ^^^";
+ invalid-expression "pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:31:13: Error: The setter 'foo' isn't defined for the class 'int'.
+Try correcting the name to the name of an existing setter, or defining a setter or field named 'foo'.
+ (0 + 1).foo = new Class1();
+ ^^^";
+ invalid-expression "pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:33:18: Error: The method 'foo' isn't defined for the class 'Class1'.
+ - 'Class1' is from 'pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart'.
+Try correcting the name to the name of an existing method, or defining a method named 'foo'.
+ new Class1().foo();
+ ^^^";
+ invalid-expression "pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:35:17: Error: The method 'call' isn't defined for the class 'Class1'.
+ - 'Class1' is from 'pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart'.
+Try correcting the name to the name of an existing method, or defining a method named 'call'.
+ new Class1()();
+ ^";
+ invalid-expression "pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:37:23: Error: 'field' isn't a function or method and can't be invoked.
+ new Class1().field();
+ ^^^^...";
+ invalid-expression "pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:39:24: Error: 'getter' isn't a function or method and can't be invoked.
+ new Class1().getter();
+ ^^^^...";
+ let final self::Class2 #t1 = this.{self::Class2::_c2}{self::Class2} in let final self::Class1 #t2 = new self::Class1::_() in invalid-expression "pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:41:8: Error: 'call' isn't a function or method and can't be invoked.
+ _c2(new Class1());
+ ^^^^";
+ this.{self::Class2::method}(a: invalid-expression "pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:43:18: Error: Duplicated named argument 'a'.
+ method(a: 0, a: new Class1());
+ ^"){({a: dynamic}) → dynamic};
+ this.{self::Class2::method}(a: invalid-expression "pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart:45:24: Error: Duplicated named argument 'a'.
+ method(a: 0, a: 1, a: new Class1());
+ ^"){({a: dynamic}) → dynamic};
+ super.[](new self::Class1::_());
+ super.[]=(0, new self::Class1::_());
+ super.foo = new self::Class1::_();
+ super.foo(new self::Class1::_());
+ super.+(new self::Class1::_());
+ }
+ method method({dynamic a = #C1}) → dynamic {}
+ get call() → core::int
+ return 0;
+}
+static method main() → dynamic {}
+
+constants {
+ #C1 = null
+}
diff --git a/pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart.weak.outline.expect b/pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart.weak.outline.expect
new file mode 100644
index 0000000..83aea2e
--- /dev/null
+++ b/pkg/front_end/testcases/general/redirecting_factory_invocation_in_invalid.dart.weak.outline.expect
@@ -0,0 +1,25 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+ field core::int field;
+ static final field dynamic _redirecting# = <dynamic>[self::Class1::•]/*isLegacy*/;
+ constructor _() → self::Class1
+ ;
+ static factory •() → self::Class1
+ let dynamic #redirecting_factory = self::Class1::_ in invalid-expression;
+ get getter() → core::int
+ ;
+}
+class Class2 extends self::Class1 {
+ final field self::Class2 _c2;
+ constructor •(self::Class2 _c2) → self::Class2
+ ;
+ method method({dynamic a}) → dynamic
+ ;
+ get call() → core::int
+ ;
+}
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/general/redirecting_factory_metadata.dart b/pkg/front_end/testcases/general/redirecting_factory_metadata.dart
index da569e7..d25c571 100644
--- a/pkg/front_end/testcases/general/redirecting_factory_metadata.dart
+++ b/pkg/front_end/testcases/general/redirecting_factory_metadata.dart
@@ -1,7 +1,9 @@
// 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.
+
// @dart=2.9
+
// This test checks that annotations on redirecting factories and their formals
// aren't skipped by the compiler and are observable in its output.
diff --git a/pkg/front_end/testcases/general/redirecting_factory_metadata.dart.weak.outline.expect b/pkg/front_end/testcases/general/redirecting_factory_metadata.dart.weak.outline.expect
index 31008cf..a83d25d 100644
--- a/pkg/front_end/testcases/general/redirecting_factory_metadata.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/general/redirecting_factory_metadata.dart.weak.outline.expect
@@ -28,5 +28,5 @@
Extra constant evaluation status:
-Evaluated: StaticGet @ org-dartlang-testcase:///redirecting_factory_metadata.dart:13:4 -> IntConstant(2)
+Evaluated: StaticGet @ org-dartlang-testcase:///redirecting_factory_metadata.dart:15:4 -> IntConstant(2)
Extra constant evaluation: evaluated: 5, effectively constant: 1
diff --git a/pkg/front_end/testcases/general/redirection_chain_type_arguments.dart b/pkg/front_end/testcases/general/redirection_chain_type_arguments.dart
index 7b4cd53..7d7ffec 100644
--- a/pkg/front_end/testcases/general/redirection_chain_type_arguments.dart
+++ b/pkg/front_end/testcases/general/redirection_chain_type_arguments.dart
@@ -1,7 +1,9 @@
// 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.md file.
+
// @dart=2.9
+
// The test checks that type arguments of the target of redirection factory
// constructors are preserved throughout the chain of redirections.
diff --git a/pkg/front_end/testcases/general/regression_flutter51828.dart.weak.transformed.expect b/pkg/front_end/testcases/general/regression_flutter51828.dart.weak.transformed.expect
index 23aa402..3d879b8 100644
--- a/pkg/front_end/testcases/general/regression_flutter51828.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/regression_flutter51828.dart.weak.transformed.expect
@@ -91,7 +91,7 @@
core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
- dynamic :async_temporary_0;
+ self::B* :async_temporary_0;
dynamic :async_temporary_1;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
diff --git a/pkg/front_end/testcases/general/type_of_null.dart.weak.expect b/pkg/front_end/testcases/general/type_of_null.dart.weak.expect
index 5387e91..4f0b860 100644
--- a/pkg/front_end/testcases/general/type_of_null.dart.weak.expect
+++ b/pkg/front_end/testcases/general/type_of_null.dart.weak.expect
@@ -23,5 +23,5 @@
}
constants {
- #C1 = tearoff self::foo
+ #C1 = static-tearoff self::foo
}
diff --git a/pkg/front_end/testcases/general/type_of_null.dart.weak.transformed.expect b/pkg/front_end/testcases/general/type_of_null.dart.weak.transformed.expect
index 5387e91..4f0b860 100644
--- a/pkg/front_end/testcases/general/type_of_null.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/type_of_null.dart.weak.transformed.expect
@@ -23,5 +23,5 @@
}
constants {
- #C1 = tearoff self::foo
+ #C1 = static-tearoff self::foo
}
diff --git a/pkg/front_end/testcases/general/typedef.dart.weak.expect b/pkg/front_end/testcases/general/typedef.dart.weak.expect
index 979f6c8..77eee56 100644
--- a/pkg/front_end/testcases/general/typedef.dart.weak.expect
+++ b/pkg/front_end/testcases/general/typedef.dart.weak.expect
@@ -12,5 +12,5 @@
}
constants {
- #C1 = tearoff self::main
+ #C1 = static-tearoff self::main
}
diff --git a/pkg/front_end/testcases/general/typedef.dart.weak.transformed.expect b/pkg/front_end/testcases/general/typedef.dart.weak.transformed.expect
index c1747f2..2bbbce2 100644
--- a/pkg/front_end/testcases/general/typedef.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/typedef.dart.weak.transformed.expect
@@ -12,7 +12,7 @@
}
constants {
- #C1 = tearoff self::main
+ #C1 = static-tearoff self::main
}
Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.strong.expect b/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.strong.expect
index 1b6e2a9..86bb196 100644
--- a/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.strong.expect
+++ b/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.strong.expect
@@ -21,5 +21,5 @@
static method main() → dynamic {}
constants {
- #C1 = tearoff self::foo
+ #C1 = static-tearoff self::foo
}
diff --git a/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.strong.transformed.expect b/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.strong.transformed.expect
index 56b3959..4a42619 100644
--- a/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.strong.transformed.expect
@@ -21,5 +21,5 @@
static method main() → dynamic {}
constants {
- #C1 = tearoff self::foo
+ #C1 = static-tearoff self::foo
}
diff --git a/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.weak.expect b/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.weak.expect
index 1b6e2a9..86bb196 100644
--- a/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.weak.expect
+++ b/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.weak.expect
@@ -21,5 +21,5 @@
static method main() → dynamic {}
constants {
- #C1 = tearoff self::foo
+ #C1 = static-tearoff self::foo
}
diff --git a/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.weak.transformed.expect b/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.weak.transformed.expect
index 56b3959..4a42619 100644
--- a/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/generic_metadata/inferred_generic_types_in_arguments_and_bounds.dart.weak.transformed.expect
@@ -21,5 +21,5 @@
static method main() → dynamic {}
constants {
- #C1 = tearoff self::foo
+ #C1 = static-tearoff self::foo
}
diff --git a/pkg/front_end/testcases/implicit_getter_calls/getter_call.dart.weak.expect b/pkg/front_end/testcases/implicit_getter_calls/getter_call.dart.weak.expect
index b258f3f..90a2cad 100644
--- a/pkg/front_end/testcases/implicit_getter_calls/getter_call.dart.weak.expect
+++ b/pkg/front_end/testcases/implicit_getter_calls/getter_call.dart.weak.expect
@@ -176,12 +176,12 @@
}
constants {
- #C1 = tearoff self::method1
- #C2 = tearoff self::method2
- #C3 = tearoff self::method3
- #C4 = tearoff self::method4
- #C5 = tearoff self::method5
- #C6 = tearoff self::method6
- #C7 = tearoff self::method7
+ #C1 = static-tearoff self::method1
+ #C2 = static-tearoff self::method2
+ #C3 = static-tearoff self::method3
+ #C4 = static-tearoff self::method4
+ #C5 = static-tearoff self::method5
+ #C6 = static-tearoff self::method6
+ #C7 = static-tearoff self::method7
#C8 = 0
}
diff --git a/pkg/front_end/testcases/implicit_getter_calls/getter_call.dart.weak.transformed.expect b/pkg/front_end/testcases/implicit_getter_calls/getter_call.dart.weak.transformed.expect
index 384940b..19a91a7 100644
--- a/pkg/front_end/testcases/implicit_getter_calls/getter_call.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/implicit_getter_calls/getter_call.dart.weak.transformed.expect
@@ -176,13 +176,13 @@
}
constants {
- #C1 = tearoff self::method1
- #C2 = tearoff self::method2
- #C3 = tearoff self::method3
- #C4 = tearoff self::method4
- #C5 = tearoff self::method5
- #C6 = tearoff self::method6
- #C7 = tearoff self::method7
+ #C1 = static-tearoff self::method1
+ #C2 = static-tearoff self::method2
+ #C3 = static-tearoff self::method3
+ #C4 = static-tearoff self::method4
+ #C5 = static-tearoff self::method5
+ #C6 = static-tearoff self::method6
+ #C7 = static-tearoff self::method7
#C8 = 0
}
diff --git a/pkg/front_end/testcases/incremental.status b/pkg/front_end/testcases/incremental.status
index 7edb02b..afed71c 100644
--- a/pkg/front_end/testcases/incremental.status
+++ b/pkg/front_end/testcases/incremental.status
@@ -6,5 +6,3 @@
# http://dartbug.com/41812#issuecomment-684825703
strongmode_mixins_2: Crash
-
-crash_07: Crash
\ No newline at end of file
diff --git a/pkg/front_end/testcases/incremental/issue_46666.yaml b/pkg/front_end/testcases/incremental/issue_46666.yaml
new file mode 100644
index 0000000..0ac3970
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/issue_46666.yaml
@@ -0,0 +1,54 @@
+# 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.md file.
+
+# Reproduces https://dartbug.com/46666.
+
+type: newworld
+worlds:
+ - entry: b.dart
+ experiments: non-nullable
+ sources:
+ a.dart: |
+ import 'dart:ffi';
+
+ class StructA extends Struct {
+ external Pointer<Void> a1;
+ external Pointer<Void> a2;
+ external Pointer<Void> a3;
+ external NestedStruct blah;
+ }
+
+ class NestedStruct extends Struct {
+ external Pointer<Void> n1;
+ external Pointer<Void> n2;
+ external Pointer<Void> n3;
+ }
+ b.dart: |
+ import 'dart:ffi';
+ import 'dart:isolate';
+ import 'dart:async';
+
+ import 'a.dart';
+
+ class StructB extends Struct {
+ external StructA b1;
+ }
+
+ void periodic() {
+ print(sizeOf<StructB>());
+ }
+
+ void main() {
+ Timer.periodic(const Duration(seconds: 1), (_) => periodic());
+ }
+ expectedLibraryCount: 2
+
+ - entry: b.dart
+ experiments: non-nullable
+ worldType: updated
+ expectInitializeFromDill: false
+ invalidate:
+ - b.dart
+ expectedLibraryCount: 2
+ expectsRebuildBodiesOnly: false
diff --git a/pkg/front_end/testcases/incremental/issue_46666.yaml.world.1.expect b/pkg/front_end/testcases/incremental/issue_46666.yaml.world.1.expect
new file mode 100644
index 0000000..516a77e
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/issue_46666.yaml.world.1.expect
@@ -0,0 +1,126 @@
+main = b::main;
+library from "org-dartlang-test:///a.dart" as a {
+
+ import "dart:ffi";
+
+ @#C7
+ class StructA extends dart.ffi::Struct {
+ synthetic constructor •() → a::StructA
+ : super dart.ffi::Struct::•()
+ ;
+ constructor #fromTypedDataBase(dart.core::Object #typedDataBase) → a::StructA
+ : super dart.ffi::Struct::_fromTypedDataBase(#typedDataBase)
+ ;
+ get a1() → dart.ffi::Pointer<dart.ffi::Void>
+ return dart.ffi::_fromAddress<dart.ffi::Void>(dart.ffi::_loadIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, (#C9).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}));
+ set a1(dart.ffi::Pointer<dart.ffi::Void> #externalFieldValue) → void
+ return dart.ffi::_storeIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, (#C9).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #externalFieldValue.{dart.ffi::Pointer::address}{dart.core::int});
+ get a2() → dart.ffi::Pointer<dart.ffi::Void>
+ return dart.ffi::_fromAddress<dart.ffi::Void>(dart.ffi::_loadIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, (#C12).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}));
+ set a2(dart.ffi::Pointer<dart.ffi::Void> #externalFieldValue) → void
+ return dart.ffi::_storeIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, (#C12).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #externalFieldValue.{dart.ffi::Pointer::address}{dart.core::int});
+ get a3() → dart.ffi::Pointer<dart.ffi::Void>
+ return dart.ffi::_fromAddress<dart.ffi::Void>(dart.ffi::_loadIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, (#C14).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}));
+ set a3(dart.ffi::Pointer<dart.ffi::Void> #externalFieldValue) → void
+ return dart.ffi::_storeIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, (#C14).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #externalFieldValue.{dart.ffi::Pointer::address}{dart.core::int});
+ get blah() → a::NestedStruct
+ return new a::NestedStruct::#fromTypedDataBase( block {
+ dart.core::Object #typedDataBase = this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object};
+ dart.core::int #offset = (#C17).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*};
+ } =>#typedDataBase is dart.ffi::Pointer<dynamic> ?{dart.core::Object} dart.ffi::_fromAddress<a::NestedStruct>(#typedDataBase.{dart.ffi::Pointer::address}{dart.core::int}.{dart.core::num::+}(#offset){(dart.core::num) → dart.core::num}) : let dart.typed_data::TypedData #typedData = dart._internal::unsafeCast<dart.typed_data::TypedData>(#typedDataBase) in #typedData.{dart.typed_data::TypedData::buffer}{dart.typed_data::ByteBuffer}.{dart.typed_data::ByteBuffer::asUint8List}(#typedData.{dart.typed_data::TypedData::offsetInBytes}{dart.core::int}.{dart.core::num::+}(#offset){(dart.core::num) → dart.core::num}, (#C17).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}){([dart.core::int, dart.core::int?]) → dart.typed_data::Uint8List});
+ set blah(a::NestedStruct #externalFieldValue) → void
+ return dart.ffi::_memCopy(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, (#C17).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #externalFieldValue.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C8, (#C17).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*});
+ @#C19
+ static get #sizeOf() → dart.core::int*
+ return (#C21).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*};
+ }
+ @#C24
+ class NestedStruct extends dart.ffi::Struct {
+ synthetic constructor •() → a::NestedStruct
+ : super dart.ffi::Struct::•()
+ ;
+ constructor #fromTypedDataBase(dart.core::Object #typedDataBase) → a::NestedStruct
+ : super dart.ffi::Struct::_fromTypedDataBase(#typedDataBase)
+ ;
+ get n1() → dart.ffi::Pointer<dart.ffi::Void>
+ return dart.ffi::_fromAddress<dart.ffi::Void>(dart.ffi::_loadIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, (#C9).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}));
+ set n1(dart.ffi::Pointer<dart.ffi::Void> #externalFieldValue) → void
+ return dart.ffi::_storeIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, (#C9).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #externalFieldValue.{dart.ffi::Pointer::address}{dart.core::int});
+ get n2() → dart.ffi::Pointer<dart.ffi::Void>
+ return dart.ffi::_fromAddress<dart.ffi::Void>(dart.ffi::_loadIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, (#C12).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}));
+ set n2(dart.ffi::Pointer<dart.ffi::Void> #externalFieldValue) → void
+ return dart.ffi::_storeIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, (#C12).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #externalFieldValue.{dart.ffi::Pointer::address}{dart.core::int});
+ get n3() → dart.ffi::Pointer<dart.ffi::Void>
+ return dart.ffi::_fromAddress<dart.ffi::Void>(dart.ffi::_loadIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, (#C14).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}));
+ set n3(dart.ffi::Pointer<dart.ffi::Void> #externalFieldValue) → void
+ return dart.ffi::_storeIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, (#C14).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #externalFieldValue.{dart.ffi::Pointer::address}{dart.core::int});
+ @#C19
+ static get #sizeOf() → dart.core::int*
+ return (#C17).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*};
+ }
+}
+library from "org-dartlang-test:///b.dart" as b {
+
+ import "dart:ffi";
+ import "dart:isolate";
+ import "dart:async";
+ import "org-dartlang-test:///a.dart";
+
+ @#C28
+ class StructB extends dart.ffi::Struct {
+ synthetic constructor •() → b::StructB
+ : super dart.ffi::Struct::•()
+ ;
+ constructor #fromTypedDataBase(dart.core::Object #typedDataBase) → b::StructB
+ : super dart.ffi::Struct::_fromTypedDataBase(#typedDataBase)
+ ;
+ get b1() → a::StructA
+ return new a::StructA::#fromTypedDataBase( block {
+ dart.core::Object #typedDataBase = this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object};
+ dart.core::int #offset = (#C9).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*};
+ } =>#typedDataBase is dart.ffi::Pointer<dynamic> ?{dart.core::Object} dart.ffi::_fromAddress<a::StructA>(#typedDataBase.{dart.ffi::Pointer::address}{dart.core::int}.{dart.core::num::+}(#offset){(dart.core::num) → dart.core::num}) : let dart.typed_data::TypedData #typedData = dart._internal::unsafeCast<dart.typed_data::TypedData>(#typedDataBase) in #typedData.{dart.typed_data::TypedData::buffer}{dart.typed_data::ByteBuffer}.{dart.typed_data::ByteBuffer::asUint8List}(#typedData.{dart.typed_data::TypedData::offsetInBytes}{dart.core::int}.{dart.core::num::+}(#offset){(dart.core::num) → dart.core::num}, (#C21).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}){([dart.core::int, dart.core::int?]) → dart.typed_data::Uint8List});
+ set b1(a::StructA #externalFieldValue) → void
+ return dart.ffi::_memCopy(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, (#C9).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #externalFieldValue.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C8, (#C21).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*});
+ @#C19
+ static get #sizeOf() → dart.core::int*
+ return (#C21).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*};
+ }
+ static method periodic() → void {
+ dart.core::print(b::StructB::#sizeOf);
+ }
+ static method main() → void {
+ dart.async::Timer::periodic(#C30, (dart.async::Timer _) → void => b::periodic());
+ }
+}
+constants {
+ #C1 = "vm:ffi:struct-fields"
+ #C2 = TypeLiteralConstant(dart.ffi::Pointer<dart.ffi::NativeType>)
+ #C3 = TypeLiteralConstant(a::NestedStruct)
+ #C4 = <dart.core::Type>[#C2, #C2, #C2, #C3]
+ #C5 = null
+ #C6 = dart.ffi::_FfiStructLayout {fieldTypes:#C4, packing:#C5}
+ #C7 = dart.core::pragma {name:#C1, options:#C6}
+ #C8 = 0
+ #C9 = <dart.core::int*>[#C8, #C8, #C8]
+ #C10 = 8
+ #C11 = 4
+ #C12 = <dart.core::int*>[#C10, #C11, #C11]
+ #C13 = 16
+ #C14 = <dart.core::int*>[#C13, #C10, #C10]
+ #C15 = 24
+ #C16 = 12
+ #C17 = <dart.core::int*>[#C15, #C16, #C16]
+ #C18 = "vm:prefer-inline"
+ #C19 = dart.core::pragma {name:#C18, options:#C5}
+ #C20 = 48
+ #C21 = <dart.core::int*>[#C20, #C15, #C15]
+ #C22 = <dart.core::Type>[#C2, #C2, #C2]
+ #C23 = dart.ffi::_FfiStructLayout {fieldTypes:#C22, packing:#C5}
+ #C24 = dart.core::pragma {name:#C1, options:#C23}
+ #C25 = TypeLiteralConstant(a::StructA)
+ #C26 = <dart.core::Type>[#C25]
+ #C27 = dart.ffi::_FfiStructLayout {fieldTypes:#C26, packing:#C5}
+ #C28 = dart.core::pragma {name:#C1, options:#C27}
+ #C29 = 1000000
+ #C30 = dart.core::Duration {_duration:#C29}
+}
diff --git a/pkg/front_end/testcases/incremental/issue_46666.yaml.world.2.expect b/pkg/front_end/testcases/incremental/issue_46666.yaml.world.2.expect
new file mode 100644
index 0000000..516a77e
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/issue_46666.yaml.world.2.expect
@@ -0,0 +1,126 @@
+main = b::main;
+library from "org-dartlang-test:///a.dart" as a {
+
+ import "dart:ffi";
+
+ @#C7
+ class StructA extends dart.ffi::Struct {
+ synthetic constructor •() → a::StructA
+ : super dart.ffi::Struct::•()
+ ;
+ constructor #fromTypedDataBase(dart.core::Object #typedDataBase) → a::StructA
+ : super dart.ffi::Struct::_fromTypedDataBase(#typedDataBase)
+ ;
+ get a1() → dart.ffi::Pointer<dart.ffi::Void>
+ return dart.ffi::_fromAddress<dart.ffi::Void>(dart.ffi::_loadIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, (#C9).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}));
+ set a1(dart.ffi::Pointer<dart.ffi::Void> #externalFieldValue) → void
+ return dart.ffi::_storeIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, (#C9).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #externalFieldValue.{dart.ffi::Pointer::address}{dart.core::int});
+ get a2() → dart.ffi::Pointer<dart.ffi::Void>
+ return dart.ffi::_fromAddress<dart.ffi::Void>(dart.ffi::_loadIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, (#C12).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}));
+ set a2(dart.ffi::Pointer<dart.ffi::Void> #externalFieldValue) → void
+ return dart.ffi::_storeIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, (#C12).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #externalFieldValue.{dart.ffi::Pointer::address}{dart.core::int});
+ get a3() → dart.ffi::Pointer<dart.ffi::Void>
+ return dart.ffi::_fromAddress<dart.ffi::Void>(dart.ffi::_loadIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, (#C14).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}));
+ set a3(dart.ffi::Pointer<dart.ffi::Void> #externalFieldValue) → void
+ return dart.ffi::_storeIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, (#C14).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #externalFieldValue.{dart.ffi::Pointer::address}{dart.core::int});
+ get blah() → a::NestedStruct
+ return new a::NestedStruct::#fromTypedDataBase( block {
+ dart.core::Object #typedDataBase = this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object};
+ dart.core::int #offset = (#C17).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*};
+ } =>#typedDataBase is dart.ffi::Pointer<dynamic> ?{dart.core::Object} dart.ffi::_fromAddress<a::NestedStruct>(#typedDataBase.{dart.ffi::Pointer::address}{dart.core::int}.{dart.core::num::+}(#offset){(dart.core::num) → dart.core::num}) : let dart.typed_data::TypedData #typedData = dart._internal::unsafeCast<dart.typed_data::TypedData>(#typedDataBase) in #typedData.{dart.typed_data::TypedData::buffer}{dart.typed_data::ByteBuffer}.{dart.typed_data::ByteBuffer::asUint8List}(#typedData.{dart.typed_data::TypedData::offsetInBytes}{dart.core::int}.{dart.core::num::+}(#offset){(dart.core::num) → dart.core::num}, (#C17).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}){([dart.core::int, dart.core::int?]) → dart.typed_data::Uint8List});
+ set blah(a::NestedStruct #externalFieldValue) → void
+ return dart.ffi::_memCopy(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, (#C17).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #externalFieldValue.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C8, (#C17).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*});
+ @#C19
+ static get #sizeOf() → dart.core::int*
+ return (#C21).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*};
+ }
+ @#C24
+ class NestedStruct extends dart.ffi::Struct {
+ synthetic constructor •() → a::NestedStruct
+ : super dart.ffi::Struct::•()
+ ;
+ constructor #fromTypedDataBase(dart.core::Object #typedDataBase) → a::NestedStruct
+ : super dart.ffi::Struct::_fromTypedDataBase(#typedDataBase)
+ ;
+ get n1() → dart.ffi::Pointer<dart.ffi::Void>
+ return dart.ffi::_fromAddress<dart.ffi::Void>(dart.ffi::_loadIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, (#C9).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}));
+ set n1(dart.ffi::Pointer<dart.ffi::Void> #externalFieldValue) → void
+ return dart.ffi::_storeIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, (#C9).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #externalFieldValue.{dart.ffi::Pointer::address}{dart.core::int});
+ get n2() → dart.ffi::Pointer<dart.ffi::Void>
+ return dart.ffi::_fromAddress<dart.ffi::Void>(dart.ffi::_loadIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, (#C12).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}));
+ set n2(dart.ffi::Pointer<dart.ffi::Void> #externalFieldValue) → void
+ return dart.ffi::_storeIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, (#C12).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #externalFieldValue.{dart.ffi::Pointer::address}{dart.core::int});
+ get n3() → dart.ffi::Pointer<dart.ffi::Void>
+ return dart.ffi::_fromAddress<dart.ffi::Void>(dart.ffi::_loadIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, (#C14).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}));
+ set n3(dart.ffi::Pointer<dart.ffi::Void> #externalFieldValue) → void
+ return dart.ffi::_storeIntPtr(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, (#C14).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #externalFieldValue.{dart.ffi::Pointer::address}{dart.core::int});
+ @#C19
+ static get #sizeOf() → dart.core::int*
+ return (#C17).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*};
+ }
+}
+library from "org-dartlang-test:///b.dart" as b {
+
+ import "dart:ffi";
+ import "dart:isolate";
+ import "dart:async";
+ import "org-dartlang-test:///a.dart";
+
+ @#C28
+ class StructB extends dart.ffi::Struct {
+ synthetic constructor •() → b::StructB
+ : super dart.ffi::Struct::•()
+ ;
+ constructor #fromTypedDataBase(dart.core::Object #typedDataBase) → b::StructB
+ : super dart.ffi::Struct::_fromTypedDataBase(#typedDataBase)
+ ;
+ get b1() → a::StructA
+ return new a::StructA::#fromTypedDataBase( block {
+ dart.core::Object #typedDataBase = this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object};
+ dart.core::int #offset = (#C9).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*};
+ } =>#typedDataBase is dart.ffi::Pointer<dynamic> ?{dart.core::Object} dart.ffi::_fromAddress<a::StructA>(#typedDataBase.{dart.ffi::Pointer::address}{dart.core::int}.{dart.core::num::+}(#offset){(dart.core::num) → dart.core::num}) : let dart.typed_data::TypedData #typedData = dart._internal::unsafeCast<dart.typed_data::TypedData>(#typedDataBase) in #typedData.{dart.typed_data::TypedData::buffer}{dart.typed_data::ByteBuffer}.{dart.typed_data::ByteBuffer::asUint8List}(#typedData.{dart.typed_data::TypedData::offsetInBytes}{dart.core::int}.{dart.core::num::+}(#offset){(dart.core::num) → dart.core::num}, (#C21).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}){([dart.core::int, dart.core::int?]) → dart.typed_data::Uint8List});
+ set b1(a::StructA #externalFieldValue) → void
+ return dart.ffi::_memCopy(this.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, (#C9).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*}, #externalFieldValue.{dart.ffi::_Compound::_typedDataBase}{dart.core::Object}, #C8, (#C21).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*});
+ @#C19
+ static get #sizeOf() → dart.core::int*
+ return (#C21).{dart.core::List::[]}(dart.ffi::_abi()){(dart.core::int) → dart.core::int*};
+ }
+ static method periodic() → void {
+ dart.core::print(b::StructB::#sizeOf);
+ }
+ static method main() → void {
+ dart.async::Timer::periodic(#C30, (dart.async::Timer _) → void => b::periodic());
+ }
+}
+constants {
+ #C1 = "vm:ffi:struct-fields"
+ #C2 = TypeLiteralConstant(dart.ffi::Pointer<dart.ffi::NativeType>)
+ #C3 = TypeLiteralConstant(a::NestedStruct)
+ #C4 = <dart.core::Type>[#C2, #C2, #C2, #C3]
+ #C5 = null
+ #C6 = dart.ffi::_FfiStructLayout {fieldTypes:#C4, packing:#C5}
+ #C7 = dart.core::pragma {name:#C1, options:#C6}
+ #C8 = 0
+ #C9 = <dart.core::int*>[#C8, #C8, #C8]
+ #C10 = 8
+ #C11 = 4
+ #C12 = <dart.core::int*>[#C10, #C11, #C11]
+ #C13 = 16
+ #C14 = <dart.core::int*>[#C13, #C10, #C10]
+ #C15 = 24
+ #C16 = 12
+ #C17 = <dart.core::int*>[#C15, #C16, #C16]
+ #C18 = "vm:prefer-inline"
+ #C19 = dart.core::pragma {name:#C18, options:#C5}
+ #C20 = 48
+ #C21 = <dart.core::int*>[#C20, #C15, #C15]
+ #C22 = <dart.core::Type>[#C2, #C2, #C2]
+ #C23 = dart.ffi::_FfiStructLayout {fieldTypes:#C22, packing:#C5}
+ #C24 = dart.core::pragma {name:#C1, options:#C23}
+ #C25 = TypeLiteralConstant(a::StructA)
+ #C26 = <dart.core::Type>[#C25]
+ #C27 = dart.ffi::_FfiStructLayout {fieldTypes:#C26, packing:#C5}
+ #C28 = dart.core::pragma {name:#C1, options:#C27}
+ #C29 = 1000000
+ #C30 = dart.core::Duration {_duration:#C29}
+}
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_17.yaml.world.1.expect b/pkg/front_end/testcases/incremental/no_outline_change_17.yaml.world.1.expect
index 88cc8e1..1c3c19c 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_17.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_17.yaml.world.1.expect
@@ -17,5 +17,5 @@
return LoadLibrary(foo);
}
constants {
- #C1 = tearoff main::_#loadLibrary_foo
+ #C1 = static-tearoff main::_#loadLibrary_foo
}
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_17.yaml.world.2.expect b/pkg/front_end/testcases/incremental/no_outline_change_17.yaml.world.2.expect
index 8edd69c..e3b1ce9 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_17.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_17.yaml.world.2.expect
@@ -18,5 +18,5 @@
return LoadLibrary(foo);
}
constants {
- #C1 = tearoff main::_#loadLibrary_foo
+ #C1 = static-tearoff main::_#loadLibrary_foo
}
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_22.yaml.world.1.expect b/pkg/front_end/testcases/incremental/no_outline_change_22.yaml.world.1.expect
index 22e37ea..d6a452a 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_22.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_22.yaml.world.1.expect
@@ -543,6 +543,6 @@
#C3 = dart.core::pragma {name:#C1, options:#C2}
#C4 = ""
#C5 = true
- #C6 = tearoff dart.collection::ListMixin::_compareAny
+ #C6 = static-tearoff dart.collection::ListMixin::_compareAny
#C7 = 0
}
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_22.yaml.world.2.expect b/pkg/front_end/testcases/incremental/no_outline_change_22.yaml.world.2.expect
index 22e37ea..d6a452a 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_22.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_22.yaml.world.2.expect
@@ -543,6 +543,6 @@
#C3 = dart.core::pragma {name:#C1, options:#C2}
#C4 = ""
#C5 = true
- #C6 = tearoff dart.collection::ListMixin::_compareAny
+ #C6 = static-tearoff dart.collection::ListMixin::_compareAny
#C7 = 0
}
diff --git a/pkg/front_end/testcases/incremental/type_change_on_recompile.yaml.world.1.expect b/pkg/front_end/testcases/incremental/type_change_on_recompile.yaml.world.1.expect
index 5938335..38493c4 100644
--- a/pkg/front_end/testcases/incremental/type_change_on_recompile.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental/type_change_on_recompile.yaml.world.1.expect
@@ -43,7 +43,7 @@
;
}
abstract class _A&B&C&D extends main::_A&B&C implements main::D /*isAnonymousMixin,isEliminatedMixin*/ {
- synthetic constructor named(dynamic _field) → main::_A&B&C&D*
+ synthetic constructor named(lib::E* _field) → main::_A&B&C&D*
: super main::_A&B&C::named(_field)
;
}
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_downwards_incompatible_with_upwards_inference_top_level.dart.weak.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_downwards_incompatible_with_upwards_inference_top_level.dart.weak.expect
index a91da56..f1a6a23 100644
--- a/pkg/front_end/testcases/inference/block_bodied_lambdas_downwards_incompatible_with_upwards_inference_top_level.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/block_bodied_lambdas_downwards_incompatible_with_upwards_inference_top_level.dart.weak.expect
@@ -10,5 +10,5 @@
}
constants {
- #C1 = tearoff self::f
+ #C1 = static-tearoff self::f
}
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_downwards_incompatible_with_upwards_inference_top_level.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_downwards_incompatible_with_upwards_inference_top_level.dart.weak.transformed.expect
index a91da56..f1a6a23 100644
--- a/pkg/front_end/testcases/inference/block_bodied_lambdas_downwards_incompatible_with_upwards_inference_top_level.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/block_bodied_lambdas_downwards_incompatible_with_upwards_inference_top_level.dart.weak.transformed.expect
@@ -10,5 +10,5 @@
}
constants {
- #C1 = tearoff self::f
+ #C1 = static-tearoff self::f
}
diff --git a/pkg/front_end/testcases/inference/bug30624.dart.weak.expect b/pkg/front_end/testcases/inference/bug30624.dart.weak.expect
index 679fdf5..d66aab0b 100644
--- a/pkg/front_end/testcases/inference/bug30624.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/bug30624.dart.weak.expect
@@ -44,5 +44,5 @@
constants {
#C1 = null
- #C2 = tearoff self::C::_default
+ #C2 = static-tearoff self::C::_default
}
diff --git a/pkg/front_end/testcases/inference/bug30624.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/bug30624.dart.weak.transformed.expect
index 9449aa55..02a85fc 100644
--- a/pkg/front_end/testcases/inference/bug30624.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/bug30624.dart.weak.transformed.expect
@@ -44,7 +44,7 @@
constants {
#C1 = null
- #C2 = tearoff self::C::_default
+ #C2 = static-tearoff self::C::_default
}
Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_argument_not_assignable.dart.weak.expect b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_argument_not_assignable.dart.weak.expect
index 706d512..3ed0854 100644
--- a/pkg/front_end/testcases/inference/constructors_infer_from_arguments_argument_not_assignable.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/constructors_infer_from_arguments_argument_not_assignable.dart.weak.expect
@@ -78,5 +78,5 @@
}
constants {
- #C1 = tearoff self::myF
+ #C1 = static-tearoff self::myF
}
diff --git a/pkg/front_end/testcases/inference/future_or_subtyping.dart.weak.expect b/pkg/front_end/testcases/inference/future_or_subtyping.dart.weak.expect
index 656a85c..36d60ee 100644
--- a/pkg/front_end/testcases/inference/future_or_subtyping.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/future_or_subtyping.dart.weak.expect
@@ -15,6 +15,6 @@
static method main() → dynamic {}
constants {
- #C1 = tearoff self::add
- #C2 = tearoff self::add2
+ #C1 = static-tearoff self::add
+ #C2 = static-tearoff self::add2
}
diff --git a/pkg/front_end/testcases/inference/future_or_subtyping.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_or_subtyping.dart.weak.transformed.expect
index 656a85c..36d60ee 100644
--- a/pkg/front_end/testcases/inference/future_or_subtyping.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_or_subtyping.dart.weak.transformed.expect
@@ -15,6 +15,6 @@
static method main() → dynamic {}
constants {
- #C1 = tearoff self::add
- #C2 = tearoff self::add2
+ #C1 = static-tearoff self::add
+ #C2 = static-tearoff self::add2
}
diff --git a/pkg/front_end/testcases/inference/future_then_conditional.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional.dart.weak.transformed.expect
index 6efd0ab..2c0fd45 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional.dart.weak.transformed.expect
@@ -56,7 +56,7 @@
[yield] let dynamic #t1 = asy::_awaitHelper(asy::Future::value<core::int*>(3), :async_op_then, :async_op_error, :async_op) in null;
:async_temporary_0 = _in::unsafeCast<core::int*>(:result);
}
- :return_value = :async_temporary_0;
+ :return_value = _in::unsafeCast<core::int*>(:async_temporary_0);
break #L1;
}
asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_2.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_2.dart.weak.transformed.expect
index 29a38cc..ada0903 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_2.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_2.dart.weak.transformed.expect
@@ -56,7 +56,7 @@
[yield] let dynamic #t1 = asy::_awaitHelper(new self::MyFuture::value<core::int*>(3), :async_op_then, :async_op_error, :async_op) in null;
:async_temporary_0 = _in::unsafeCast<core::int*>(:result);
}
- :return_value = :async_temporary_0;
+ :return_value = _in::unsafeCast<core::int*>(:async_temporary_0);
break #L1;
}
asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_3.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_3.dart.weak.transformed.expect
index 9ac9e7e..057adde 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_3.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_3.dart.weak.transformed.expect
@@ -56,7 +56,7 @@
[yield] let dynamic #t1 = asy::_awaitHelper(asy::Future::value<core::int*>(3), :async_op_then, :async_op_error, :async_op) in null;
:async_temporary_0 = _in::unsafeCast<core::int*>(:result);
}
- :return_value = :async_temporary_0;
+ :return_value = _in::unsafeCast<core::int*>(:async_temporary_0);
break #L1;
}
asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_4.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_4.dart.weak.transformed.expect
index 768aaeb..fd4b819 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_4.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_4.dart.weak.transformed.expect
@@ -56,7 +56,7 @@
[yield] let dynamic #t1 = asy::_awaitHelper(new self::MyFuture::value<core::int*>(3), :async_op_then, :async_op_error, :async_op) in null;
:async_temporary_0 = _in::unsafeCast<core::int*>(:result);
}
- :return_value = :async_temporary_0;
+ :return_value = _in::unsafeCast<core::int*>(:async_temporary_0);
break #L1;
}
asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_5.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_5.dart.weak.transformed.expect
index 6fc6957..6e05707 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_5.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_5.dart.weak.transformed.expect
@@ -56,7 +56,7 @@
[yield] let dynamic #t1 = asy::_awaitHelper(new self::MyFuture::value<core::int*>(3), :async_op_then, :async_op_error, :async_op) in null;
:async_temporary_0 = _in::unsafeCast<core::int*>(:result);
}
- :return_value = :async_temporary_0;
+ :return_value = _in::unsafeCast<core::int*>(:async_temporary_0);
break #L1;
}
asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_6.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_6.dart.weak.transformed.expect
index 4bf5a96..1968cbf 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_6.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_6.dart.weak.transformed.expect
@@ -56,7 +56,7 @@
[yield] let dynamic #t1 = asy::_awaitHelper(asy::Future::value<core::int*>(3), :async_op_then, :async_op_error, :async_op) in null;
:async_temporary_0 = _in::unsafeCast<core::int*>(:result);
}
- :return_value = :async_temporary_0;
+ :return_value = _in::unsafeCast<core::int*>(:async_temporary_0);
break #L1;
}
asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
diff --git a/pkg/front_end/testcases/inference/future_then_ifNull.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/future_then_ifNull.dart.weak.transformed.expect
index d6e68fc..077bfa1 100644
--- a/pkg/front_end/testcases/inference/future_then_ifNull.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_ifNull.dart.weak.transformed.expect
@@ -57,7 +57,7 @@
else {
:async_temporary_0 = #t1;
}
- :return_value = :async_temporary_0;
+ :return_value = _in::unsafeCast<core::int*>(:async_temporary_0);
break #L1;
}
asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
diff --git a/pkg/front_end/testcases/inference/generic_methods_basic_downward_inference.dart.weak.expect b/pkg/front_end/testcases/inference/generic_methods_basic_downward_inference.dart.weak.expect
index 19380c0..94fc7a3 100644
--- a/pkg/front_end/testcases/inference/generic_methods_basic_downward_inference.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/generic_methods_basic_downward_inference.dart.weak.expect
@@ -10,5 +10,5 @@
}
constants {
- #C1 = tearoff self::f
+ #C1 = static-tearoff self::f
}
diff --git a/pkg/front_end/testcases/inference/generic_methods_basic_downward_inference.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/generic_methods_basic_downward_inference.dart.weak.transformed.expect
index 19380c0..94fc7a3 100644
--- a/pkg/front_end/testcases/inference/generic_methods_basic_downward_inference.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/generic_methods_basic_downward_inference.dart.weak.transformed.expect
@@ -10,5 +10,5 @@
}
constants {
- #C1 = tearoff self::f
+ #C1 = static-tearoff self::f
}
diff --git a/pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart.weak.expect b/pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart.weak.expect
index 2c7b116..e8a716a 100644
--- a/pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart.weak.expect
@@ -176,6 +176,6 @@
static method main() → dynamic {}
constants {
- #C1 = tearoff math::max
- #C2 = tearoff math::min
+ #C1 = static-tearoff math::max
+ #C2 = static-tearoff math::min
}
diff --git a/pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart.weak.transformed.expect
index 9dc6b9b..1ee8bea 100644
--- a/pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart.weak.transformed.expect
@@ -176,8 +176,8 @@
static method main() → dynamic {}
constants {
- #C1 = tearoff math::max
- #C2 = tearoff math::min
+ #C1 = static-tearoff math::max
+ #C2 = static-tearoff math::min
}
Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/inference/generic_methods_iterable_and_future.dart.weak.expect b/pkg/front_end/testcases/inference/generic_methods_iterable_and_future.dart.weak.expect
index 860faf4..fe91228 100644
--- a/pkg/front_end/testcases/inference/generic_methods_iterable_and_future.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/generic_methods_iterable_and_future.dart.weak.expect
@@ -34,5 +34,5 @@
static method main() → dynamic {}
constants {
- #C1 = tearoff self::make
+ #C1 = static-tearoff self::make
}
diff --git a/pkg/front_end/testcases/inference/generic_methods_iterable_and_future.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/generic_methods_iterable_and_future.dart.weak.transformed.expect
index 99dc822..393b79d 100644
--- a/pkg/front_end/testcases/inference/generic_methods_iterable_and_future.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/generic_methods_iterable_and_future.dart.weak.transformed.expect
@@ -34,5 +34,5 @@
static method main() → dynamic {}
constants {
- #C1 = tearoff self::make
+ #C1 = static-tearoff self::make
}
diff --git a/pkg/front_end/testcases/inference/generic_methods_nested_generic_instantiation.dart.weak.expect b/pkg/front_end/testcases/inference/generic_methods_nested_generic_instantiation.dart.weak.expect
index 34108a8..3d04d1f 100644
--- a/pkg/front_end/testcases/inference/generic_methods_nested_generic_instantiation.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/generic_methods_nested_generic_instantiation.dart.weak.expect
@@ -44,5 +44,5 @@
}
constants {
- #C1 = tearoff math::max
+ #C1 = static-tearoff math::max
}
diff --git a/pkg/front_end/testcases/inference/generic_methods_nested_generic_instantiation.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/generic_methods_nested_generic_instantiation.dart.weak.transformed.expect
index 8af73b0..b46e8a6 100644
--- a/pkg/front_end/testcases/inference/generic_methods_nested_generic_instantiation.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/generic_methods_nested_generic_instantiation.dart.weak.transformed.expect
@@ -44,7 +44,7 @@
}
constants {
- #C1 = tearoff math::max
+ #C1 = static-tearoff math::max
}
Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/inference/greatest_closure_multiple_params.dart.weak.expect b/pkg/front_end/testcases/inference/greatest_closure_multiple_params.dart.weak.expect
index 5f6e2e6..d6bd505 100644
--- a/pkg/front_end/testcases/inference/greatest_closure_multiple_params.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/greatest_closure_multiple_params.dart.weak.expect
@@ -30,5 +30,5 @@
constants {
#C1 = null
- #C2 = tearoff self::C::_compareAny
+ #C2 = static-tearoff self::C::_compareAny
}
diff --git a/pkg/front_end/testcases/inference/greatest_closure_multiple_params.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/greatest_closure_multiple_params.dart.weak.transformed.expect
index 5f6e2e6..d6bd505 100644
--- a/pkg/front_end/testcases/inference/greatest_closure_multiple_params.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/greatest_closure_multiple_params.dart.weak.transformed.expect
@@ -30,5 +30,5 @@
constants {
#C1 = null
- #C2 = tearoff self::C::_compareAny
+ #C2 = static-tearoff self::C::_compareAny
}
diff --git a/pkg/front_end/testcases/inference/inferred_type_from_top_level_executable_tear_off.dart.weak.expect b/pkg/front_end/testcases/inference/inferred_type_from_top_level_executable_tear_off.dart.weak.expect
index b95e93b..6eef7cc 100644
--- a/pkg/front_end/testcases/inference/inferred_type_from_top_level_executable_tear_off.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_from_top_level_executable_tear_off.dart.weak.expect
@@ -8,5 +8,5 @@
}
constants {
- #C1 = tearoff core::print
+ #C1 = static-tearoff core::print
}
diff --git a/pkg/front_end/testcases/inference/inferred_type_from_top_level_executable_tear_off.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_from_top_level_executable_tear_off.dart.weak.transformed.expect
index b95e93b..6eef7cc 100644
--- a/pkg/front_end/testcases/inference/inferred_type_from_top_level_executable_tear_off.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_from_top_level_executable_tear_off.dart.weak.transformed.expect
@@ -8,5 +8,5 @@
}
constants {
- #C1 = tearoff core::print
+ #C1 = static-tearoff core::print
}
diff --git a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type.dart.weak.expect b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type.dart.weak.expect
index 5fbc81e..21d3b06 100644
--- a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type.dart.weak.expect
@@ -12,6 +12,6 @@
}
constants {
- #C1 = tearoff self::f
- #C2 = tearoff self::g
+ #C1 = static-tearoff self::f
+ #C2 = static-tearoff self::g
}
diff --git a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type.dart.weak.transformed.expect
index 468a854..2e71da8 100644
--- a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type.dart.weak.transformed.expect
@@ -12,6 +12,6 @@
}
constants {
- #C1 = tearoff self::f
- #C2 = tearoff self::g
+ #C1 = static-tearoff self::f
+ #C2 = static-tearoff self::g
}
diff --git a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_function_typed_param.dart.weak.expect b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_function_typed_param.dart.weak.expect
index 5db9025..9be942f 100644
--- a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_function_typed_param.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_function_typed_param.dart.weak.expect
@@ -12,6 +12,6 @@
}
constants {
- #C1 = tearoff self::f
- #C2 = tearoff self::g
+ #C1 = static-tearoff self::f
+ #C2 = static-tearoff self::g
}
diff --git a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_function_typed_param.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_function_typed_param.dart.weak.transformed.expect
index 302d4f1..126d190 100644
--- a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_function_typed_param.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_function_typed_param.dart.weak.transformed.expect
@@ -12,6 +12,6 @@
}
constants {
- #C1 = tearoff self::f
- #C2 = tearoff self::g
+ #C1 = static-tearoff self::f
+ #C2 = static-tearoff self::g
}
diff --git a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_named_param.dart.weak.expect b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_named_param.dart.weak.expect
index 7d05c01..0b7d047 100644
--- a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_named_param.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_named_param.dart.weak.expect
@@ -12,7 +12,7 @@
}
constants {
- #C1 = tearoff self::f
- #C2 = tearoff self::g
+ #C1 = static-tearoff self::f
+ #C2 = static-tearoff self::g
#C3 = null
}
diff --git a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_named_param.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_named_param.dart.weak.transformed.expect
index d3dbe88..ee21ab4 100644
--- a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_named_param.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_named_param.dart.weak.transformed.expect
@@ -12,7 +12,7 @@
}
constants {
- #C1 = tearoff self::f
- #C2 = tearoff self::g
+ #C1 = static-tearoff self::f
+ #C2 = static-tearoff self::g
#C3 = null
}
diff --git a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_positional_param.dart.weak.expect b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_positional_param.dart.weak.expect
index 2eb4e4d..704ff597 100644
--- a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_positional_param.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_positional_param.dart.weak.expect
@@ -12,7 +12,7 @@
}
constants {
- #C1 = tearoff self::f
- #C2 = tearoff self::g
+ #C1 = static-tearoff self::f
+ #C2 = static-tearoff self::g
#C3 = null
}
diff --git a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_positional_param.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_positional_param.dart.weak.transformed.expect
index d9781ac..2e47f05 100644
--- a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_positional_param.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_positional_param.dart.weak.transformed.expect
@@ -12,7 +12,7 @@
}
constants {
- #C1 = tearoff self::f
- #C2 = tearoff self::g
+ #C1 = static-tearoff self::f
+ #C2 = static-tearoff self::g
#C3 = null
}
diff --git a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_required_param.dart.weak.expect b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_required_param.dart.weak.expect
index 5a739ef..b495253 100644
--- a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_required_param.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_required_param.dart.weak.expect
@@ -12,6 +12,6 @@
}
constants {
- #C1 = tearoff self::f
- #C2 = tearoff self::g
+ #C1 = static-tearoff self::f
+ #C2 = static-tearoff self::g
}
diff --git a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_required_param.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_required_param.dart.weak.transformed.expect
index a8897a0..805ab2c 100644
--- a/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_required_param.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_uses_synthetic_function_type_required_param.dart.weak.transformed.expect
@@ -12,6 +12,6 @@
}
constants {
- #C1 = tearoff self::f
- #C2 = tearoff self::g
+ #C1 = static-tearoff self::f
+ #C2 = static-tearoff self::g
}
diff --git a/pkg/front_end/testcases/inference/instantiate_tearoff.dart.weak.expect b/pkg/front_end/testcases/inference/instantiate_tearoff.dart.weak.expect
index 41e2e41..5d83e0a 100644
--- a/pkg/front_end/testcases/inference/instantiate_tearoff.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/instantiate_tearoff.dart.weak.expect
@@ -44,6 +44,6 @@
static method main() → dynamic {}
constants {
- #C1 = tearoff self::f
- #C2 = tearoff self::C::g
+ #C1 = static-tearoff self::f
+ #C2 = static-tearoff self::C::g
}
diff --git a/pkg/front_end/testcases/inference/instantiate_tearoff.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/instantiate_tearoff.dart.weak.transformed.expect
index 4c5080b..87decf1 100644
--- a/pkg/front_end/testcases/inference/instantiate_tearoff.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/instantiate_tearoff.dart.weak.transformed.expect
@@ -44,8 +44,8 @@
static method main() → dynamic {}
constants {
- #C1 = tearoff self::f
- #C2 = tearoff self::C::g
+ #C1 = static-tearoff self::f
+ #C2 = static-tearoff self::C::g
}
Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/inference/parameter_defaults_upwards.dart.weak.expect b/pkg/front_end/testcases/inference/parameter_defaults_upwards.dart.weak.expect
index af395c5..d6fb1da 100644
--- a/pkg/front_end/testcases/inference/parameter_defaults_upwards.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/parameter_defaults_upwards.dart.weak.expect
@@ -34,6 +34,6 @@
constants {
#C1 = 0
#C2 = <core::int*>[#C1]
- #C3 = tearoff self::optional_toplevel
- #C4 = tearoff self::named_toplevel
+ #C3 = static-tearoff self::optional_toplevel
+ #C4 = static-tearoff self::named_toplevel
}
diff --git a/pkg/front_end/testcases/inference/parameter_defaults_upwards.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/parameter_defaults_upwards.dart.weak.transformed.expect
index af395c5..d6fb1da 100644
--- a/pkg/front_end/testcases/inference/parameter_defaults_upwards.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/parameter_defaults_upwards.dart.weak.transformed.expect
@@ -34,6 +34,6 @@
constants {
#C1 = 0
#C2 = <core::int*>[#C1]
- #C3 = tearoff self::optional_toplevel
- #C4 = tearoff self::named_toplevel
+ #C3 = static-tearoff self::optional_toplevel
+ #C4 = static-tearoff self::named_toplevel
}
diff --git a/pkg/front_end/testcases/inference/static_method_tear_off.dart.weak.expect b/pkg/front_end/testcases/inference/static_method_tear_off.dart.weak.expect
index 3a80563..b89fa7d 100644
--- a/pkg/front_end/testcases/inference/static_method_tear_off.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/static_method_tear_off.dart.weak.expect
@@ -25,5 +25,5 @@
}
constants {
- #C1 = tearoff self::C::f
+ #C1 = static-tearoff self::C::f
}
diff --git a/pkg/front_end/testcases/inference/static_method_tear_off.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/static_method_tear_off.dart.weak.transformed.expect
index 3a80563..b89fa7d 100644
--- a/pkg/front_end/testcases/inference/static_method_tear_off.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/static_method_tear_off.dart.weak.transformed.expect
@@ -25,5 +25,5 @@
}
constants {
- #C1 = tearoff self::C::f
+ #C1 = static-tearoff self::C::f
}
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1.dart.weak.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1.dart.weak.expect
index c90ed22..1307281 100644
--- a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1.dart.weak.expect
@@ -18,5 +18,5 @@
static method main() → dynamic {}
constants {
- #C1 = tearoff self::f
+ #C1 = static-tearoff self::f
}
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1.dart.weak.transformed.expect
index 2c7a1d7..56348a9 100644
--- a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1.dart.weak.transformed.expect
@@ -18,5 +18,5 @@
static method main() → dynamic {}
constants {
- #C1 = tearoff self::f
+ #C1 = static-tearoff self::f
}
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.weak.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.weak.expect
index ca3de8b..a621378 100644
--- a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.weak.expect
@@ -12,5 +12,5 @@
}
constants {
- #C1 = tearoff self::f
+ #C1 = static-tearoff self::f
}
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.weak.transformed.expect
index 1124860..1da0ab0 100644
--- a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.weak.transformed.expect
@@ -12,5 +12,5 @@
}
constants {
- #C1 = tearoff self::f
+ #C1 = static-tearoff self::f
}
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1.dart.weak.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1.dart.weak.expect
index d25a131..f64ec974 100644
--- a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1.dart.weak.expect
@@ -18,5 +18,5 @@
static method main() → dynamic {}
constants {
- #C1 = tearoff self::f
+ #C1 = static-tearoff self::f
}
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1.dart.weak.transformed.expect
index 6d9032c..a98e49b 100644
--- a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1.dart.weak.transformed.expect
@@ -18,5 +18,5 @@
static method main() → dynamic {}
constants {
- #C1 = tearoff self::f
+ #C1 = static-tearoff self::f
}
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.weak.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.weak.expect
index 169486b..ccba70a 100644
--- a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.weak.expect
@@ -12,5 +12,5 @@
}
constants {
- #C1 = tearoff self::f
+ #C1 = static-tearoff self::f
}
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.weak.transformed.expect
index 633c890..e9a5c4e 100644
--- a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.weak.transformed.expect
@@ -12,5 +12,5 @@
}
constants {
- #C1 = tearoff self::f
+ #C1 = static-tearoff self::f
}
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_implicit_type_param_via_expr.dart.weak.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_implicit_type_param_via_expr.dart.weak.expect
index bce5804..fc22443 100644
--- a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_implicit_type_param_via_expr.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_implicit_type_param_via_expr.dart.weak.expect
@@ -11,5 +11,5 @@
return <self::f::T*>[g(){() →* self::f::T*}];
constants {
- #C1 = tearoff self::f
+ #C1 = static-tearoff self::f
}
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_implicit_type_param_via_expr.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_implicit_type_param_via_expr.dart.weak.transformed.expect
index cb153d8..e7778dd 100644
--- a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_implicit_type_param_via_expr.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_implicit_type_param_via_expr.dart.weak.transformed.expect
@@ -11,5 +11,5 @@
return core::_GrowableList::_literal1<self::f::T*>(g(){() →* self::f::T*});
constants {
- #C1 = tearoff self::f
+ #C1 = static-tearoff self::f
}
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_no_type_param_via_expr.dart.weak.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_no_type_param_via_expr.dart.weak.expect
index 742f60c..432c8a0a 100644
--- a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_no_type_param_via_expr.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_no_type_param_via_expr.dart.weak.expect
@@ -11,5 +11,5 @@
return 1.0;
constants {
- #C1 = tearoff self::f
+ #C1 = static-tearoff self::f
}
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_no_type_param_via_expr.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_no_type_param_via_expr.dart.weak.transformed.expect
index 742f60c..432c8a0a 100644
--- a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_no_type_param_via_expr.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_no_type_param_via_expr.dart.weak.transformed.expect
@@ -11,5 +11,5 @@
return 1.0;
constants {
- #C1 = tearoff self::f
+ #C1 = static-tearoff self::f
}
diff --git a/pkg/front_end/testcases/inference/void_return_type_subtypes_dynamic.dart.weak.expect b/pkg/front_end/testcases/inference/void_return_type_subtypes_dynamic.dart.weak.expect
index f86a055..751e547 100644
--- a/pkg/front_end/testcases/inference/void_return_type_subtypes_dynamic.dart.weak.expect
+++ b/pkg/front_end/testcases/inference/void_return_type_subtypes_dynamic.dart.weak.expect
@@ -25,5 +25,5 @@
}
constants {
- #C1 = tearoff self::printRunning
+ #C1 = static-tearoff self::printRunning
}
diff --git a/pkg/front_end/testcases/inference/void_return_type_subtypes_dynamic.dart.weak.transformed.expect b/pkg/front_end/testcases/inference/void_return_type_subtypes_dynamic.dart.weak.transformed.expect
index f86a055..751e547 100644
--- a/pkg/front_end/testcases/inference/void_return_type_subtypes_dynamic.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference/void_return_type_subtypes_dynamic.dart.weak.transformed.expect
@@ -25,5 +25,5 @@
}
constants {
- #C1 = tearoff self::printRunning
+ #C1 = static-tearoff self::printRunning
}
diff --git a/pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.weak.expect b/pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.weak.expect
index 169486b..ccba70a 100644
--- a/pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.weak.expect
+++ b/pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.weak.expect
@@ -12,5 +12,5 @@
}
constants {
- #C1 = tearoff self::f
+ #C1 = static-tearoff self::f
}
diff --git a/pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.weak.transformed.expect b/pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.weak.transformed.expect
index 633c890..e9a5c4e 100644
--- a/pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr2.dart.weak.transformed.expect
@@ -12,5 +12,5 @@
}
constants {
- #C1 = tearoff self::f
+ #C1 = static-tearoff self::f
}
diff --git a/pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.weak.expect b/pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.weak.expect
index 169486b..ccba70a 100644
--- a/pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.weak.expect
+++ b/pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.weak.expect
@@ -12,5 +12,5 @@
}
constants {
- #C1 = tearoff self::f
+ #C1 = static-tearoff self::f
}
diff --git a/pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.weak.transformed.expect b/pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.weak.transformed.expect
index 633c890..e9a5c4e 100644
--- a/pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr2.dart.weak.transformed.expect
@@ -12,5 +12,5 @@
}
constants {
- #C1 = tearoff self::f
+ #C1 = static-tearoff self::f
}
diff --git a/pkg/front_end/testcases/inference_new/void_return_type_subtypes_dynamic.dart.weak.expect b/pkg/front_end/testcases/inference_new/void_return_type_subtypes_dynamic.dart.weak.expect
index 7e0013f..96e59b9 100644
--- a/pkg/front_end/testcases/inference_new/void_return_type_subtypes_dynamic.dart.weak.expect
+++ b/pkg/front_end/testcases/inference_new/void_return_type_subtypes_dynamic.dart.weak.expect
@@ -15,5 +15,5 @@
static method main() → dynamic {}
constants {
- #C1 = tearoff self::printRunning
+ #C1 = static-tearoff self::printRunning
}
diff --git a/pkg/front_end/testcases/inference_new/void_return_type_subtypes_dynamic.dart.weak.transformed.expect b/pkg/front_end/testcases/inference_new/void_return_type_subtypes_dynamic.dart.weak.transformed.expect
index 7e0013f..96e59b9 100644
--- a/pkg/front_end/testcases/inference_new/void_return_type_subtypes_dynamic.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/void_return_type_subtypes_dynamic.dart.weak.transformed.expect
@@ -15,5 +15,5 @@
static method main() → dynamic {}
constants {
- #C1 = tearoff self::printRunning
+ #C1 = static-tearoff self::printRunning
}
diff --git a/pkg/front_end/testcases/late_lowering/later.dart.strong.expect b/pkg/front_end/testcases/late_lowering/later.dart.strong.expect
index d5af00b..d80fa11 100644
--- a/pkg/front_end/testcases/late_lowering/later.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/later.dart.strong.expect
@@ -160,5 +160,5 @@
static method main() → dynamic {}
constants {
- #C1 = tearoff self::fisk
+ #C1 = static-tearoff self::fisk
}
diff --git a/pkg/front_end/testcases/late_lowering/later.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/later.dart.strong.transformed.expect
index 95d50a9..d009196 100644
--- a/pkg/front_end/testcases/late_lowering/later.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/later.dart.strong.transformed.expect
@@ -265,7 +265,7 @@
static method main() → dynamic {}
constants {
- #C1 = tearoff self::fisk
+ #C1 = static-tearoff self::fisk
}
Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/late_lowering/later.dart.weak.expect b/pkg/front_end/testcases/late_lowering/later.dart.weak.expect
index 00a9a68..0026c6b 100644
--- a/pkg/front_end/testcases/late_lowering/later.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/later.dart.weak.expect
@@ -204,5 +204,5 @@
static method main() → dynamic {}
constants {
- #C1 = tearoff self::fisk
+ #C1 = static-tearoff self::fisk
}
diff --git a/pkg/front_end/testcases/late_lowering/later.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/later.dart.weak.transformed.expect
index 7c57520..a808b23 100644
--- a/pkg/front_end/testcases/late_lowering/later.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/later.dart.weak.transformed.expect
@@ -309,5 +309,5 @@
static method main() → dynamic {}
constants {
- #C1 = tearoff self::fisk
+ #C1 = static-tearoff self::fisk
}
diff --git a/pkg/front_end/testcases/nnbd/const_is.dart.strong.expect b/pkg/front_end/testcases/nnbd/const_is.dart.strong.expect
index ee9ce9b..1cece20 100644
--- a/pkg/front_end/testcases/nnbd/const_is.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/const_is.dart.strong.expect
@@ -96,11 +96,11 @@
#C2 = false
#C3 = null
#C4 = 1
- #C5 = tearoff self::f
- #C6 = tearoff self::g
- #C7 = tearoff self::f1
- #C8 = tearoff self::f2
- #C9 = tearoff self::f3
- #C10 = tearoff self::f4
- #C11 = tearoff self::f5
+ #C5 = static-tearoff self::f
+ #C6 = static-tearoff self::g
+ #C7 = static-tearoff self::f1
+ #C8 = static-tearoff self::f2
+ #C9 = static-tearoff self::f3
+ #C10 = static-tearoff self::f4
+ #C11 = static-tearoff self::f5
}
diff --git a/pkg/front_end/testcases/nnbd/const_is.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/const_is.dart.strong.transformed.expect
index 2eda141..55a7036 100644
--- a/pkg/front_end/testcases/nnbd/const_is.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/const_is.dart.strong.transformed.expect
@@ -96,13 +96,13 @@
#C2 = false
#C3 = null
#C4 = 1
- #C5 = tearoff self::f
- #C6 = tearoff self::g
- #C7 = tearoff self::f1
- #C8 = tearoff self::f2
- #C9 = tearoff self::f3
- #C10 = tearoff self::f4
- #C11 = tearoff self::f5
+ #C5 = static-tearoff self::f
+ #C6 = static-tearoff self::g
+ #C7 = static-tearoff self::f1
+ #C8 = static-tearoff self::f2
+ #C9 = static-tearoff self::f3
+ #C10 = static-tearoff self::f4
+ #C11 = static-tearoff self::f5
}
Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/nnbd/const_is.dart.weak.expect b/pkg/front_end/testcases/nnbd/const_is.dart.weak.expect
index 7da3b8f..dcba0f8 100644
--- a/pkg/front_end/testcases/nnbd/const_is.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/const_is.dart.weak.expect
@@ -96,11 +96,11 @@
#C2 = false
#C3 = null
#C4 = 1
- #C5 = tearoff self::f
- #C6 = tearoff self::g
- #C7 = tearoff self::f1
- #C8 = tearoff self::f2
- #C9 = tearoff self::f3
- #C10 = tearoff self::f4
- #C11 = tearoff self::f5
+ #C5 = static-tearoff self::f
+ #C6 = static-tearoff self::g
+ #C7 = static-tearoff self::f1
+ #C8 = static-tearoff self::f2
+ #C9 = static-tearoff self::f3
+ #C10 = static-tearoff self::f4
+ #C11 = static-tearoff self::f5
}
diff --git a/pkg/front_end/testcases/nnbd/const_is.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/const_is.dart.weak.transformed.expect
index 67362a6..eda5d9f 100644
--- a/pkg/front_end/testcases/nnbd/const_is.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/const_is.dart.weak.transformed.expect
@@ -96,13 +96,13 @@
#C2 = false
#C3 = null
#C4 = 1
- #C5 = tearoff self::f
- #C6 = tearoff self::g
- #C7 = tearoff self::f1
- #C8 = tearoff self::f2
- #C9 = tearoff self::f3
- #C10 = tearoff self::f4
- #C11 = tearoff self::f5
+ #C5 = static-tearoff self::f
+ #C6 = static-tearoff self::g
+ #C7 = static-tearoff self::f1
+ #C8 = static-tearoff self::f2
+ #C9 = static-tearoff self::f3
+ #C10 = static-tearoff self::f4
+ #C11 = static-tearoff self::f5
}
Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/nnbd/constants.dart.strong.expect b/pkg/front_end/testcases/nnbd/constants.dart.strong.expect
index d1fd5fe..70ed240 100644
--- a/pkg/front_end/testcases/nnbd/constants.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/constants.dart.strong.expect
@@ -89,8 +89,8 @@
constants {
#C1 = TypeLiteralConstant(core::Object)
- #C2 = tearoff con::id
- #C3 = partial-instantiation con::id <core::int>
+ #C2 = static-tearoff con::id
+ #C3 = instantiation con::id <core::int>
#C4 = 0
#C5 = con::Class<core::int> {field:#C4}
#C6 = TypeLiteralConstant((dynamic) → dynamic)
@@ -104,7 +104,7 @@
#C14 = <dynamic>[#C4, #C13]
#C15 = core::_ImmutableMap<core::int, core::String> {_kvPairs:#C14}
#C16 = true
- #C17 = tearoff core::identical
+ #C17 = static-tearoff core::identical
}
diff --git a/pkg/front_end/testcases/nnbd/constants.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/constants.dart.strong.transformed.expect
index d1fd5fe..70ed240 100644
--- a/pkg/front_end/testcases/nnbd/constants.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/constants.dart.strong.transformed.expect
@@ -89,8 +89,8 @@
constants {
#C1 = TypeLiteralConstant(core::Object)
- #C2 = tearoff con::id
- #C3 = partial-instantiation con::id <core::int>
+ #C2 = static-tearoff con::id
+ #C3 = instantiation con::id <core::int>
#C4 = 0
#C5 = con::Class<core::int> {field:#C4}
#C6 = TypeLiteralConstant((dynamic) → dynamic)
@@ -104,7 +104,7 @@
#C14 = <dynamic>[#C4, #C13]
#C15 = core::_ImmutableMap<core::int, core::String> {_kvPairs:#C14}
#C16 = true
- #C17 = tearoff core::identical
+ #C17 = static-tearoff core::identical
}
diff --git a/pkg/front_end/testcases/nnbd/constants.dart.weak.expect b/pkg/front_end/testcases/nnbd/constants.dart.weak.expect
index 3adb498..b26ca6d 100644
--- a/pkg/front_end/testcases/nnbd/constants.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/constants.dart.weak.expect
@@ -89,8 +89,8 @@
constants {
#C1 = TypeLiteralConstant(core::Object*)
- #C2 = tearoff con::id
- #C3 = partial-instantiation con::id <core::int*>
+ #C2 = static-tearoff con::id
+ #C3 = instantiation con::id <core::int*>
#C4 = 0
#C5 = con::Class<core::int*> {field:#C4}
#C6 = TypeLiteralConstant((dynamic) →* dynamic)
@@ -104,7 +104,7 @@
#C14 = <dynamic>[#C4, #C13]
#C15 = core::_ImmutableMap<core::int*, core::String*> {_kvPairs:#C14}
#C16 = true
- #C17 = tearoff core::identical
+ #C17 = static-tearoff core::identical
}
diff --git a/pkg/front_end/testcases/nnbd/constants.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/constants.dart.weak.transformed.expect
index 3adb498..b26ca6d 100644
--- a/pkg/front_end/testcases/nnbd/constants.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/constants.dart.weak.transformed.expect
@@ -89,8 +89,8 @@
constants {
#C1 = TypeLiteralConstant(core::Object*)
- #C2 = tearoff con::id
- #C3 = partial-instantiation con::id <core::int*>
+ #C2 = static-tearoff con::id
+ #C3 = instantiation con::id <core::int*>
#C4 = 0
#C5 = con::Class<core::int*> {field:#C4}
#C6 = TypeLiteralConstant((dynamic) →* dynamic)
@@ -104,7 +104,7 @@
#C14 = <dynamic>[#C4, #C13]
#C15 = core::_ImmutableMap<core::int*, core::String*> {_kvPairs:#C14}
#C16 = true
- #C17 = tearoff core::identical
+ #C17 = static-tearoff core::identical
}
diff --git a/pkg/front_end/testcases/nnbd/function_types.dart.strong.expect b/pkg/front_end/testcases/nnbd/function_types.dart.strong.expect
index 26e67a7..57a3b98 100644
--- a/pkg/front_end/testcases/nnbd/function_types.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/function_types.dart.strong.expect
@@ -36,5 +36,5 @@
}
constants {
- #C1 = tearoff self::foo
+ #C1 = static-tearoff self::foo
}
diff --git a/pkg/front_end/testcases/nnbd/function_types.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/function_types.dart.strong.transformed.expect
index 26e67a7..57a3b98 100644
--- a/pkg/front_end/testcases/nnbd/function_types.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/function_types.dart.strong.transformed.expect
@@ -36,5 +36,5 @@
}
constants {
- #C1 = tearoff self::foo
+ #C1 = static-tearoff self::foo
}
diff --git a/pkg/front_end/testcases/nnbd/function_types.dart.weak.expect b/pkg/front_end/testcases/nnbd/function_types.dart.weak.expect
index 26e67a7..57a3b98 100644
--- a/pkg/front_end/testcases/nnbd/function_types.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/function_types.dart.weak.expect
@@ -36,5 +36,5 @@
}
constants {
- #C1 = tearoff self::foo
+ #C1 = static-tearoff self::foo
}
diff --git a/pkg/front_end/testcases/nnbd/function_types.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/function_types.dart.weak.transformed.expect
index 26e67a7..57a3b98 100644
--- a/pkg/front_end/testcases/nnbd/function_types.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/function_types.dart.weak.transformed.expect
@@ -36,5 +36,5 @@
}
constants {
- #C1 = tearoff self::foo
+ #C1 = static-tearoff self::foo
}
diff --git a/pkg/front_end/testcases/nnbd/issue42433.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue42433.dart.strong.expect
index 2d7f2f7..81da4f2 100644
--- a/pkg/front_end/testcases/nnbd/issue42433.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/issue42433.dart.strong.expect
@@ -14,5 +14,5 @@
}
constants {
- #C1 = tearoff self::checkme
+ #C1 = static-tearoff self::checkme
}
diff --git a/pkg/front_end/testcases/nnbd/issue42433.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue42433.dart.strong.transformed.expect
index 62a035b..d4ca87d 100644
--- a/pkg/front_end/testcases/nnbd/issue42433.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue42433.dart.strong.transformed.expect
@@ -14,7 +14,7 @@
}
constants {
- #C1 = tearoff self::checkme
+ #C1 = static-tearoff self::checkme
}
Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/nnbd/issue42433.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue42433.dart.weak.expect
index 2d7f2f7..81da4f2 100644
--- a/pkg/front_end/testcases/nnbd/issue42433.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/issue42433.dart.weak.expect
@@ -14,5 +14,5 @@
}
constants {
- #C1 = tearoff self::checkme
+ #C1 = static-tearoff self::checkme
}
diff --git a/pkg/front_end/testcases/nnbd/issue42433.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue42433.dart.weak.transformed.expect
index 0fd30a8..005edee 100644
--- a/pkg/front_end/testcases/nnbd/issue42433.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue42433.dart.weak.transformed.expect
@@ -14,7 +14,7 @@
}
constants {
- #C1 = tearoff self::checkme
+ #C1 = static-tearoff self::checkme
}
Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/nnbd/issue43716b.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue43716b.dart.strong.expect
index 0bba0ad..5f9dc45 100644
--- a/pkg/front_end/testcases/nnbd/issue43716b.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/issue43716b.dart.strong.expect
@@ -28,5 +28,5 @@
static method main() → dynamic {}
constants {
- #C1 = tearoff self::f
+ #C1 = static-tearoff self::f
}
diff --git a/pkg/front_end/testcases/nnbd/issue43716b.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue43716b.dart.strong.transformed.expect
index 0bba0ad..5f9dc45 100644
--- a/pkg/front_end/testcases/nnbd/issue43716b.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue43716b.dart.strong.transformed.expect
@@ -28,5 +28,5 @@
static method main() → dynamic {}
constants {
- #C1 = tearoff self::f
+ #C1 = static-tearoff self::f
}
diff --git a/pkg/front_end/testcases/nnbd/issue43716b.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue43716b.dart.weak.expect
index 0bba0ad..5f9dc45 100644
--- a/pkg/front_end/testcases/nnbd/issue43716b.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/issue43716b.dart.weak.expect
@@ -28,5 +28,5 @@
static method main() → dynamic {}
constants {
- #C1 = tearoff self::f
+ #C1 = static-tearoff self::f
}
diff --git a/pkg/front_end/testcases/nnbd/issue43716b.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue43716b.dart.weak.transformed.expect
index 0bba0ad..5f9dc45 100644
--- a/pkg/front_end/testcases/nnbd/issue43716b.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue43716b.dart.weak.transformed.expect
@@ -28,5 +28,5 @@
static method main() → dynamic {}
constants {
- #C1 = tearoff self::f
+ #C1 = static-tearoff self::f
}
diff --git a/pkg/front_end/testcases/nnbd/later.dart.strong.expect b/pkg/front_end/testcases/nnbd/later.dart.strong.expect
index 076e56c..d9880ad 100644
--- a/pkg/front_end/testcases/nnbd/later.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/later.dart.strong.expect
@@ -134,5 +134,5 @@
static method main() → dynamic {}
constants {
- #C1 = tearoff self::fisk
+ #C1 = static-tearoff self::fisk
}
diff --git a/pkg/front_end/testcases/nnbd/later.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/later.dart.strong.transformed.expect
index 90b2c25..2885cb8 100644
--- a/pkg/front_end/testcases/nnbd/later.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/later.dart.strong.transformed.expect
@@ -246,5 +246,5 @@
static method main() → dynamic {}
constants {
- #C1 = tearoff self::fisk
+ #C1 = static-tearoff self::fisk
}
diff --git a/pkg/front_end/testcases/nnbd/later.dart.weak.expect b/pkg/front_end/testcases/nnbd/later.dart.weak.expect
index 076e56c..d9880ad 100644
--- a/pkg/front_end/testcases/nnbd/later.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/later.dart.weak.expect
@@ -134,5 +134,5 @@
static method main() → dynamic {}
constants {
- #C1 = tearoff self::fisk
+ #C1 = static-tearoff self::fisk
}
diff --git a/pkg/front_end/testcases/nnbd/later.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/later.dart.weak.transformed.expect
index 90b2c25..2885cb8 100644
--- a/pkg/front_end/testcases/nnbd/later.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/later.dart.weak.transformed.expect
@@ -246,5 +246,5 @@
static method main() → dynamic {}
constants {
- #C1 = tearoff self::fisk
+ #C1 = static-tearoff self::fisk
}
diff --git a/pkg/front_end/testcases/nnbd/load_library.dart.strong.expect b/pkg/front_end/testcases/nnbd/load_library.dart.strong.expect
index 9513601..885e631 100644
--- a/pkg/front_end/testcases/nnbd/load_library.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/load_library.dart.strong.expect
@@ -15,5 +15,5 @@
return LoadLibrary(math);
constants {
- #C1 = tearoff self::_#loadLibrary_math
+ #C1 = static-tearoff self::_#loadLibrary_math
}
diff --git a/pkg/front_end/testcases/nnbd/load_library.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/load_library.dart.strong.transformed.expect
index 9513601..885e631 100644
--- a/pkg/front_end/testcases/nnbd/load_library.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/load_library.dart.strong.transformed.expect
@@ -15,5 +15,5 @@
return LoadLibrary(math);
constants {
- #C1 = tearoff self::_#loadLibrary_math
+ #C1 = static-tearoff self::_#loadLibrary_math
}
diff --git a/pkg/front_end/testcases/nnbd/load_library.dart.weak.expect b/pkg/front_end/testcases/nnbd/load_library.dart.weak.expect
index 9513601..885e631 100644
--- a/pkg/front_end/testcases/nnbd/load_library.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/load_library.dart.weak.expect
@@ -15,5 +15,5 @@
return LoadLibrary(math);
constants {
- #C1 = tearoff self::_#loadLibrary_math
+ #C1 = static-tearoff self::_#loadLibrary_math
}
diff --git a/pkg/front_end/testcases/nnbd/load_library.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/load_library.dart.weak.transformed.expect
index 9513601..885e631 100644
--- a/pkg/front_end/testcases/nnbd/load_library.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/load_library.dart.weak.transformed.expect
@@ -15,5 +15,5 @@
return LoadLibrary(math);
constants {
- #C1 = tearoff self::_#loadLibrary_math
+ #C1 = static-tearoff self::_#loadLibrary_math
}
diff --git a/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.strong.expect b/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.strong.expect
index 5612a60..e4d23f5 100644
--- a/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.strong.expect
@@ -225,8 +225,8 @@
constants {
#C1 = 3
- #C2 = tearoff self::idFunction
- #C3 = partial-instantiation self::idFunction <core::int>
+ #C2 = static-tearoff self::idFunction
+ #C3 = instantiation self::idFunction <core::int>
#C4 = 0
#C5 = self::Class<dynamic> {field:#C4}
#C6 = self::Class<core::num> {field:#C4}
@@ -244,13 +244,13 @@
#C18 = self::ClassWithList<core::int> {field:#C16}
#C19 = <core::String>[#C8]
#C20 = self::ClassWithList<core::String> {field:#C19}
- #C21 = tearoff self::dynamicFunction
+ #C21 = static-tearoff self::dynamicFunction
#C22 = self::ClassWithFunction<dynamic> {field:#C21}
#C23 = self::ClassWithFunction<core::Object?> {field:#C21}
- #C24 = tearoff self::objectFunction
+ #C24 = static-tearoff self::objectFunction
#C25 = self::ClassWithFunction<dynamic> {field:#C24}
#C26 = self::ClassWithFunction<void> {field:#C24}
- #C27 = tearoff self::intFunction
+ #C27 = static-tearoff self::intFunction
#C28 = self::ClassWithFunction<core::int> {field:#C27}
#C29 = self::ClassWithFunction<core::int> {field:#C3}
}
diff --git a/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.strong.transformed.expect
index 5612a60..e4d23f5 100644
--- a/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.strong.transformed.expect
@@ -225,8 +225,8 @@
constants {
#C1 = 3
- #C2 = tearoff self::idFunction
- #C3 = partial-instantiation self::idFunction <core::int>
+ #C2 = static-tearoff self::idFunction
+ #C3 = instantiation self::idFunction <core::int>
#C4 = 0
#C5 = self::Class<dynamic> {field:#C4}
#C6 = self::Class<core::num> {field:#C4}
@@ -244,13 +244,13 @@
#C18 = self::ClassWithList<core::int> {field:#C16}
#C19 = <core::String>[#C8]
#C20 = self::ClassWithList<core::String> {field:#C19}
- #C21 = tearoff self::dynamicFunction
+ #C21 = static-tearoff self::dynamicFunction
#C22 = self::ClassWithFunction<dynamic> {field:#C21}
#C23 = self::ClassWithFunction<core::Object?> {field:#C21}
- #C24 = tearoff self::objectFunction
+ #C24 = static-tearoff self::objectFunction
#C25 = self::ClassWithFunction<dynamic> {field:#C24}
#C26 = self::ClassWithFunction<void> {field:#C24}
- #C27 = tearoff self::intFunction
+ #C27 = static-tearoff self::intFunction
#C28 = self::ClassWithFunction<core::int> {field:#C27}
#C29 = self::ClassWithFunction<core::int> {field:#C3}
}
diff --git a/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.weak.expect b/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.weak.expect
index ff4ef6e..8c2aa2a 100644
--- a/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.weak.expect
@@ -216,8 +216,8 @@
constants {
#C1 = 3
- #C2 = tearoff self::idFunction
- #C3 = partial-instantiation self::idFunction <core::int*>
+ #C2 = static-tearoff self::idFunction
+ #C3 = instantiation self::idFunction <core::int*>
#C4 = 0
#C5 = self::Class<dynamic> {field:#C4}
#C6 = self::Class<core::num*> {field:#C4}
@@ -235,13 +235,13 @@
#C18 = self::ClassWithList<core::int*> {field:#C16}
#C19 = <core::String*>[#C8]
#C20 = self::ClassWithList<core::String*> {field:#C19}
- #C21 = tearoff self::dynamicFunction
+ #C21 = static-tearoff self::dynamicFunction
#C22 = self::ClassWithFunction<dynamic> {field:#C21}
#C23 = self::ClassWithFunction<core::Object?> {field:#C21}
- #C24 = tearoff self::objectFunction
+ #C24 = static-tearoff self::objectFunction
#C25 = self::ClassWithFunction<dynamic> {field:#C24}
#C26 = self::ClassWithFunction<void> {field:#C24}
- #C27 = tearoff self::intFunction
+ #C27 = static-tearoff self::intFunction
#C28 = self::ClassWithFunction<core::int*> {field:#C27}
#C29 = self::ClassWithFunction<core::int*> {field:#C3}
#C30 = self::ClassWithFunction<core::Object*> {field:#C24}
diff --git a/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.weak.transformed.expect
index ff4ef6e..8c2aa2a 100644
--- a/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.weak.transformed.expect
@@ -216,8 +216,8 @@
constants {
#C1 = 3
- #C2 = tearoff self::idFunction
- #C3 = partial-instantiation self::idFunction <core::int*>
+ #C2 = static-tearoff self::idFunction
+ #C3 = instantiation self::idFunction <core::int*>
#C4 = 0
#C5 = self::Class<dynamic> {field:#C4}
#C6 = self::Class<core::num*> {field:#C4}
@@ -235,13 +235,13 @@
#C18 = self::ClassWithList<core::int*> {field:#C16}
#C19 = <core::String*>[#C8]
#C20 = self::ClassWithList<core::String*> {field:#C19}
- #C21 = tearoff self::dynamicFunction
+ #C21 = static-tearoff self::dynamicFunction
#C22 = self::ClassWithFunction<dynamic> {field:#C21}
#C23 = self::ClassWithFunction<core::Object?> {field:#C21}
- #C24 = tearoff self::objectFunction
+ #C24 = static-tearoff self::objectFunction
#C25 = self::ClassWithFunction<dynamic> {field:#C24}
#C26 = self::ClassWithFunction<void> {field:#C24}
- #C27 = tearoff self::intFunction
+ #C27 = static-tearoff self::intFunction
#C28 = self::ClassWithFunction<core::int*> {field:#C27}
#C29 = self::ClassWithFunction<core::int*> {field:#C3}
#C30 = self::ClassWithFunction<core::Object*> {field:#C24}
diff --git a/pkg/front_end/testcases/nnbd/potentially_constant_type_is.dart.strong.expect b/pkg/front_end/testcases/nnbd/potentially_constant_type_is.dart.strong.expect
index c131260..f4b8262 100644
--- a/pkg/front_end/testcases/nnbd/potentially_constant_type_is.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/potentially_constant_type_is.dart.strong.expect
@@ -80,8 +80,8 @@
constants {
#C1 = 3
- #C2 = tearoff self::idFunction
- #C3 = partial-instantiation self::idFunction <core::int>
+ #C2 = static-tearoff self::idFunction
+ #C3 = instantiation self::idFunction <core::int>
#C4 = true
#C5 = self::Class<dynamic> {field:#C4}
#C6 = self::Class<core::num> {field:#C4}
diff --git a/pkg/front_end/testcases/nnbd/potentially_constant_type_is.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/potentially_constant_type_is.dart.strong.transformed.expect
index c131260..f4b8262 100644
--- a/pkg/front_end/testcases/nnbd/potentially_constant_type_is.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/potentially_constant_type_is.dart.strong.transformed.expect
@@ -80,8 +80,8 @@
constants {
#C1 = 3
- #C2 = tearoff self::idFunction
- #C3 = partial-instantiation self::idFunction <core::int>
+ #C2 = static-tearoff self::idFunction
+ #C3 = instantiation self::idFunction <core::int>
#C4 = true
#C5 = self::Class<dynamic> {field:#C4}
#C6 = self::Class<core::num> {field:#C4}
diff --git a/pkg/front_end/testcases/nnbd/potentially_constant_type_is.dart.weak.expect b/pkg/front_end/testcases/nnbd/potentially_constant_type_is.dart.weak.expect
index d959fa2..3391fa7 100644
--- a/pkg/front_end/testcases/nnbd/potentially_constant_type_is.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/potentially_constant_type_is.dart.weak.expect
@@ -80,8 +80,8 @@
constants {
#C1 = 3
- #C2 = tearoff self::idFunction
- #C3 = partial-instantiation self::idFunction <core::int*>
+ #C2 = static-tearoff self::idFunction
+ #C3 = instantiation self::idFunction <core::int*>
#C4 = true
#C5 = self::Class<dynamic> {field:#C4}
#C6 = self::Class<core::num*> {field:#C4}
diff --git a/pkg/front_end/testcases/nnbd/potentially_constant_type_is.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/potentially_constant_type_is.dart.weak.transformed.expect
index d959fa2..3391fa7 100644
--- a/pkg/front_end/testcases/nnbd/potentially_constant_type_is.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/potentially_constant_type_is.dart.weak.transformed.expect
@@ -80,8 +80,8 @@
constants {
#C1 = 3
- #C2 = tearoff self::idFunction
- #C3 = partial-instantiation self::idFunction <core::int*>
+ #C2 = static-tearoff self::idFunction
+ #C3 = instantiation self::idFunction <core::int*>
#C4 = true
#C5 = self::Class<dynamic> {field:#C4}
#C6 = self::Class<core::num*> {field:#C4}
diff --git a/pkg/front_end/testcases/nnbd_mixed/call_opt_in_through_opt_out.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/call_opt_in_through_opt_out.dart.weak.expect
index 496eb80..524b85c 100644
--- a/pkg/front_end/testcases/nnbd_mixed/call_opt_in_through_opt_out.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/call_opt_in_through_opt_out.dart.weak.expect
@@ -43,9 +43,9 @@
static method applyTakesNonNullableNamed({required (core::int) → void f = #C5}) → dynamic {}
constants {
- #C1 = tearoff cal::takesNever
- #C2 = tearoff cal::takesNull
- #C3 = tearoff cal::takesNonNullable
- #C4 = tearoff cal::takesNullable
+ #C1 = static-tearoff cal::takesNever
+ #C2 = static-tearoff cal::takesNull
+ #C3 = static-tearoff cal::takesNonNullable
+ #C4 = static-tearoff cal::takesNullable
#C5 = null
}
diff --git a/pkg/front_end/testcases/nnbd_mixed/call_opt_in_through_opt_out.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/call_opt_in_through_opt_out.dart.weak.transformed.expect
index 496eb80..524b85c 100644
--- a/pkg/front_end/testcases/nnbd_mixed/call_opt_in_through_opt_out.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/call_opt_in_through_opt_out.dart.weak.transformed.expect
@@ -43,9 +43,9 @@
static method applyTakesNonNullableNamed({required (core::int) → void f = #C5}) → dynamic {}
constants {
- #C1 = tearoff cal::takesNever
- #C2 = tearoff cal::takesNull
- #C3 = tearoff cal::takesNonNullable
- #C4 = tearoff cal::takesNullable
+ #C1 = static-tearoff cal::takesNever
+ #C2 = static-tearoff cal::takesNull
+ #C3 = static-tearoff cal::takesNonNullable
+ #C4 = static-tearoff cal::takesNullable
#C5 = null
}
diff --git a/pkg/front_end/testcases/nnbd_mixed/const_is.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/const_is.dart.weak.expect
index ce1ca58..b684e03a 100644
--- a/pkg/front_end/testcases/nnbd_mixed/const_is.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/const_is.dart.weak.expect
@@ -27,7 +27,7 @@
return null;
constants {
- #C1 = tearoff self2::fnWithNonNullObjectBound
+ #C1 = static-tearoff self2::fnWithNonNullObjectBound
#C2 = true
- #C3 = tearoff self2::fnWithNullBound
+ #C3 = static-tearoff self2::fnWithNullBound
}
diff --git a/pkg/front_end/testcases/nnbd_mixed/const_is.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/const_is.dart.weak.transformed.expect
index 806f867..37ae0a7 100644
--- a/pkg/front_end/testcases/nnbd_mixed/const_is.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/const_is.dart.weak.transformed.expect
@@ -27,9 +27,9 @@
return null;
constants {
- #C1 = tearoff self2::fnWithNonNullObjectBound
+ #C1 = static-tearoff self2::fnWithNonNullObjectBound
#C2 = true
- #C3 = tearoff self2::fnWithNullBound
+ #C3 = static-tearoff self2::fnWithNullBound
}
Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/nnbd_mixed/constants.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/constants.dart.weak.expect
index 22db152..fc18272 100644
--- a/pkg/front_end/testcases/nnbd_mixed/constants.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/constants.dart.weak.expect
@@ -81,8 +81,8 @@
return t;
constants {
- #C1 = tearoff con::id
- #C2 = partial-instantiation con::id <core::int*>
+ #C1 = static-tearoff con::id
+ #C2 = instantiation con::id <core::int*>
#C3 = 0
#C4 = con::Class<core::int*> {field:#C3}
#C5 = <core::int*>[#C3]
@@ -94,7 +94,7 @@
#C11 = <dynamic>[#C3, #C10]
#C12 = core::_ImmutableMap<core::int*, core::String*> {_kvPairs:#C11}
#C13 = true
- #C14 = tearoff core::identical
+ #C14 = static-tearoff core::identical
}
diff --git a/pkg/front_end/testcases/nnbd_mixed/constants.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/constants.dart.weak.transformed.expect
index 22db152..fc18272 100644
--- a/pkg/front_end/testcases/nnbd_mixed/constants.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/constants.dart.weak.transformed.expect
@@ -81,8 +81,8 @@
return t;
constants {
- #C1 = tearoff con::id
- #C2 = partial-instantiation con::id <core::int*>
+ #C1 = static-tearoff con::id
+ #C2 = instantiation con::id <core::int*>
#C3 = 0
#C4 = con::Class<core::int*> {field:#C3}
#C5 = <core::int*>[#C3]
@@ -94,7 +94,7 @@
#C11 = <dynamic>[#C3, #C10]
#C12 = core::_ImmutableMap<core::int*, core::String*> {_kvPairs:#C11}
#C13 = true
- #C14 = tearoff core::identical
+ #C14 = static-tearoff core::identical
}
diff --git a/pkg/front_end/testcases/nnbd_mixed/issue41435.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/issue41435.dart.weak.expect
index bcfdbf4..5d1e11f 100644
--- a/pkg/front_end/testcases/nnbd_mixed/issue41435.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/issue41435.dart.weak.expect
@@ -24,5 +24,5 @@
static method takesTakesNull((Null) → void f) → void {}
constants {
- #C1 = tearoff iss::takesNever
+ #C1 = static-tearoff iss::takesNever
}
diff --git a/pkg/front_end/testcases/nnbd_mixed/issue41435.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/issue41435.dart.weak.transformed.expect
index bcfdbf4..5d1e11f 100644
--- a/pkg/front_end/testcases/nnbd_mixed/issue41435.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/issue41435.dart.weak.transformed.expect
@@ -24,5 +24,5 @@
static method takesTakesNull((Null) → void f) → void {}
constants {
- #C1 = tearoff iss::takesNever
+ #C1 = static-tearoff iss::takesNever
}
diff --git a/pkg/front_end/testcases/nnbd_mixed/issue42181.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/issue42181.dart.weak.expect
index 8d0b35b..9f64aae 100644
--- a/pkg/front_end/testcases/nnbd_mixed/issue42181.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/issue42181.dart.weak.expect
@@ -28,5 +28,5 @@
typedef F = (core::int*) →* core::int*;
constants {
- #C1 = tearoff self::f1
+ #C1 = static-tearoff self::f1
}
diff --git a/pkg/front_end/testcases/nnbd_mixed/issue42181.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/issue42181.dart.weak.transformed.expect
index c100d45..c2af5e9 100644
--- a/pkg/front_end/testcases/nnbd_mixed/issue42181.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/issue42181.dart.weak.transformed.expect
@@ -28,5 +28,5 @@
typedef F = (core::int*) →* core::int*;
constants {
- #C1 = tearoff self::f1
+ #C1 = static-tearoff self::f1
}
diff --git a/pkg/front_end/testcases/nnbd_mixed/issue42660.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/issue42660.dart.weak.expect
index 10c6848..3376fa8 100644
--- a/pkg/front_end/testcases/nnbd_mixed/issue42660.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/issue42660.dart.weak.expect
@@ -61,5 +61,5 @@
return 4;
constants {
- #C1 = tearoff iss::f
+ #C1 = static-tearoff iss::f
}
diff --git a/pkg/front_end/testcases/nnbd_mixed/issue42660.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/issue42660.dart.weak.transformed.expect
index 10c6848..3376fa8 100644
--- a/pkg/front_end/testcases/nnbd_mixed/issue42660.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/issue42660.dart.weak.transformed.expect
@@ -61,5 +61,5 @@
return 4;
constants {
- #C1 = tearoff iss::f
+ #C1 = static-tearoff iss::f
}
diff --git a/pkg/front_end/testcases/none/property_get.dart.strong.expect b/pkg/front_end/testcases/none/property_get.dart.strong.expect
index 4163115..e7de58d 100644
--- a/pkg/front_end/testcases/none/property_get.dart.strong.expect
+++ b/pkg/front_end/testcases/none/property_get.dart.strong.expect
@@ -144,6 +144,6 @@
constants {
#C1 = "foo"
#C2 = 3
- #C3 = tearoff self::Class1::staticMethod
- #C4 = tearoff self::topLevelMethod
+ #C3 = static-tearoff self::Class1::staticMethod
+ #C4 = static-tearoff self::topLevelMethod
}
diff --git a/pkg/front_end/testcases/none/property_get.dart.weak.expect b/pkg/front_end/testcases/none/property_get.dart.weak.expect
index fcb468d..83e1366 100644
--- a/pkg/front_end/testcases/none/property_get.dart.weak.expect
+++ b/pkg/front_end/testcases/none/property_get.dart.weak.expect
@@ -145,6 +145,6 @@
constants {
#C1 = "foo"
#C2 = 3
- #C3 = tearoff self::Class1::staticMethod
- #C4 = tearoff self::topLevelMethod
+ #C3 = static-tearoff self::Class1::staticMethod
+ #C4 = static-tearoff self::topLevelMethod
}
diff --git a/pkg/front_end/testcases/outline.status b/pkg/front_end/testcases/outline.status
index b866349..a59e9fd 100644
--- a/pkg/front_end/testcases/outline.status
+++ b/pkg/front_end/testcases/outline.status
@@ -9,11 +9,11 @@
extension_types/simple_method_resolution: ExpectationFileMismatchSerialized
extension_types/simple_operator_resolution: ExpectationFileMismatchSerialized
extension_types/simple_setter_resolution: ExpectationFileMismatchSerialized
+extension_types/simple_show_hide: ExpectationFileMismatchSerialized # Expected.
general/abstract_members: TypeCheckError
general/bug30695: TypeCheckError
general/covariant_field: TypeCheckError
general/crashes/crash_02/main: Crash
-general/crashes/crash_04/main: Crash
general/crashes/crash_06/main: Crash
general/getter_vs_setter_type: TypeCheckError
general/infer_field_from_multiple: TypeCheckError
diff --git a/pkg/front_end/testcases/rasta/deferred_load.dart.weak.expect b/pkg/front_end/testcases/rasta/deferred_load.dart.weak.expect
index 0c092f0..d01ac3d 100644
--- a/pkg/front_end/testcases/rasta/deferred_load.dart.weak.expect
+++ b/pkg/front_end/testcases/rasta/deferred_load.dart.weak.expect
@@ -18,5 +18,5 @@
return null;
constants {
- #C1 = tearoff self::_#loadLibrary_lib
+ #C1 = static-tearoff self::_#loadLibrary_lib
}
diff --git a/pkg/front_end/testcases/rasta/deferred_load.dart.weak.transformed.expect b/pkg/front_end/testcases/rasta/deferred_load.dart.weak.transformed.expect
index 0c092f0..d01ac3d 100644
--- a/pkg/front_end/testcases/rasta/deferred_load.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/rasta/deferred_load.dart.weak.transformed.expect
@@ -18,5 +18,5 @@
return null;
constants {
- #C1 = tearoff self::_#loadLibrary_lib
+ #C1 = static-tearoff self::_#loadLibrary_lib
}
diff --git a/pkg/front_end/testcases/rasta/static.dart.weak.expect b/pkg/front_end/testcases/rasta/static.dart.weak.expect
index 79e268c..e32deba4 100644
--- a/pkg/front_end/testcases/rasta/static.dart.weak.expect
+++ b/pkg/front_end/testcases/rasta/static.dart.weak.expect
@@ -335,5 +335,5 @@
constants {
#C1 = 42
- #C2 = tearoff self::Foo::staticFunction
+ #C2 = static-tearoff self::Foo::staticFunction
}
diff --git a/pkg/front_end/testcases/rasta/static.dart.weak.transformed.expect b/pkg/front_end/testcases/rasta/static.dart.weak.transformed.expect
index f510042..6e667ff 100644
--- a/pkg/front_end/testcases/rasta/static.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/rasta/static.dart.weak.transformed.expect
@@ -335,7 +335,7 @@
constants {
#C1 = 42
- #C2 = tearoff self::Foo::staticFunction
+ #C2 = static-tearoff self::Foo::staticFunction
}
Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/regress/issue_30838.dart.weak.expect b/pkg/front_end/testcases/regress/issue_30838.dart.weak.expect
index a71fae5..f1431a1 100644
--- a/pkg/front_end/testcases/regress/issue_30838.dart.weak.expect
+++ b/pkg/front_end/testcases/regress/issue_30838.dart.weak.expect
@@ -32,5 +32,5 @@
static method main() → dynamic {}
constants {
- #C1 = tearoff self::foo
+ #C1 = static-tearoff self::foo
}
diff --git a/pkg/front_end/testcases/regress/issue_30838.dart.weak.transformed.expect b/pkg/front_end/testcases/regress/issue_30838.dart.weak.transformed.expect
index acb1618..d1bd2c9 100644
--- a/pkg/front_end/testcases/regress/issue_30838.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_30838.dart.weak.transformed.expect
@@ -32,7 +32,7 @@
static method main() → dynamic {}
constants {
- #C1 = tearoff self::foo
+ #C1 = static-tearoff self::foo
}
Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/regress/issue_31846.dart.weak.expect b/pkg/front_end/testcases/regress/issue_31846.dart.weak.expect
index 0966591..450ca19 100644
--- a/pkg/front_end/testcases/regress/issue_31846.dart.weak.expect
+++ b/pkg/front_end/testcases/regress/issue_31846.dart.weak.expect
@@ -13,5 +13,5 @@
}
constants {
- #C1 = tearoff self::main
+ #C1 = static-tearoff self::main
}
diff --git a/pkg/front_end/testcases/regress/issue_31846.dart.weak.transformed.expect b/pkg/front_end/testcases/regress/issue_31846.dart.weak.transformed.expect
index 1a1cf76..34ce0c6 100644
--- a/pkg/front_end/testcases/regress/issue_31846.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_31846.dart.weak.transformed.expect
@@ -13,7 +13,7 @@
}
constants {
- #C1 = tearoff self::main
+ #C1 = static-tearoff self::main
}
Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/regress/issue_39682.dart.weak.expect b/pkg/front_end/testcases/regress/issue_39682.dart.weak.expect
index 9ab919a..9866587 100644
--- a/pkg/front_end/testcases/regress/issue_39682.dart.weak.expect
+++ b/pkg/front_end/testcases/regress/issue_39682.dart.weak.expect
@@ -25,5 +25,5 @@
}
constants {
- #C1 = tearoff self::_#loadLibrary_foo
+ #C1 = static-tearoff self::_#loadLibrary_foo
}
diff --git a/pkg/front_end/testcases/regress/issue_39682.dart.weak.transformed.expect b/pkg/front_end/testcases/regress/issue_39682.dart.weak.transformed.expect
index 9ab919a..9866587 100644
--- a/pkg/front_end/testcases/regress/issue_39682.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_39682.dart.weak.transformed.expect
@@ -25,5 +25,5 @@
}
constants {
- #C1 = tearoff self::_#loadLibrary_foo
+ #C1 = static-tearoff self::_#loadLibrary_foo
}
diff --git a/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_tear_off.dart.weak.expect b/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_tear_off.dart.weak.expect
index 28fb659..3f796f1 100644
--- a/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_tear_off.dart.weak.expect
+++ b/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_tear_off.dart.weak.expect
@@ -34,5 +34,5 @@
static method main() → void {}
constants {
- #C1 = tearoff self::h
+ #C1 = static-tearoff self::h
}
diff --git a/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_tear_off.dart.weak.transformed.expect b/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_tear_off.dart.weak.transformed.expect
index 28fb659..3f796f1 100644
--- a/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_tear_off.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_tear_off.dart.weak.transformed.expect
@@ -34,5 +34,5 @@
static method main() → void {}
constants {
- #C1 = tearoff self::h
+ #C1 = static-tearoff self::h
}
diff --git a/pkg/front_end/testcases/runtime_checks/dynamic_invocation_of_getter.dart.weak.expect b/pkg/front_end/testcases/runtime_checks/dynamic_invocation_of_getter.dart.weak.expect
index 14294a1..204effc 100644
--- a/pkg/front_end/testcases/runtime_checks/dynamic_invocation_of_getter.dart.weak.expect
+++ b/pkg/front_end/testcases/runtime_checks/dynamic_invocation_of_getter.dart.weak.expect
@@ -28,5 +28,5 @@
static method main() → dynamic {}
constants {
- #C1 = tearoff self::h
+ #C1 = static-tearoff self::h
}
diff --git a/pkg/front_end/testcases/runtime_checks/dynamic_invocation_of_getter.dart.weak.transformed.expect b/pkg/front_end/testcases/runtime_checks/dynamic_invocation_of_getter.dart.weak.transformed.expect
index bde2247..14d1ec2 100644
--- a/pkg/front_end/testcases/runtime_checks/dynamic_invocation_of_getter.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/runtime_checks/dynamic_invocation_of_getter.dart.weak.transformed.expect
@@ -28,7 +28,7 @@
static method main() → dynamic {}
constants {
- #C1 = tearoff self::h
+ #C1 = static-tearoff self::h
}
Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart.weak.expect b/pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart.weak.expect
index 889de80..378a300 100644
--- a/pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart.weak.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart.weak.expect
@@ -94,6 +94,6 @@
}
constants {
- #C1 = tearoff self::numToInt
- #C2 = tearoff self::numToNum
+ #C1 = static-tearoff self::numToInt
+ #C2 = static-tearoff self::numToNum
}
diff --git a/pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart.weak.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart.weak.transformed.expect
index 4fec92e..92acd28 100644
--- a/pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart.weak.transformed.expect
@@ -94,8 +94,8 @@
}
constants {
- #C1 = tearoff self::numToInt
- #C2 = tearoff self::numToNum
+ #C1 = static-tearoff self::numToInt
+ #C2 = static-tearoff self::numToNum
}
Extra constant evaluation status:
diff --git a/pkg/front_end/testcases/strong.status b/pkg/front_end/testcases/strong.status
index 6b4d01c..2518fb5 100644
--- a/pkg/front_end/testcases/strong.status
+++ b/pkg/front_end/testcases/strong.status
@@ -8,8 +8,10 @@
dart2js/late_statics: SemiFuzzFailure # dartbug.com/45854
-constructor_tearoffs/instantiation: TypeCheckError
+constructor_tearoffs/call_instantiation: TypeCheckError
+constructor_tearoffs/const_tear_off: RuntimeError
constructor_tearoffs/redirecting_constructors: RuntimeError
+constructor_tearoffs/redirecting_factory_tear_off: RuntimeError
extension_types/extension_on_nullable: ExpectationFileMismatchSerialized # Expected.
extension_types/issue45775: ExpectationFileMismatchSerialized # Expected.
extension_types/simple: ExpectationFileMismatchSerialized # Expected.
@@ -17,6 +19,7 @@
extension_types/simple_method_resolution: ExpectationFileMismatchSerialized # Expected.
extension_types/simple_operator_resolution: ExpectationFileMismatchSerialized # Expected.
extension_types/simple_setter_resolution: ExpectationFileMismatchSerialized # Expected.
+extension_types/simple_show_hide: ExpectationFileMismatchSerialized # Expected.
late_lowering/covariant_late_field: TypeCheckError
nnbd/covariant_late_field: TypeCheckError
nnbd/getter_vs_setter_type: TypeCheckError
diff --git a/pkg/front_end/testcases/text_serialization.status b/pkg/front_end/testcases/text_serialization.status
index b1e611f..7ea4ce0 100644
--- a/pkg/front_end/testcases/text_serialization.status
+++ b/pkg/front_end/testcases/text_serialization.status
@@ -6,15 +6,10 @@
# the round trip for Kernel textual serialization where the initial binary
# Kernel files are produced by compiling Dart code via Fasta.
-constructor_tearoffs/abstract_class_constructor_tear_off: TextSerializationFailure
-constructor_tearoffs/generic_tearoff_with_context: TextSerializationFailure
-constructor_tearoffs/generic_tearoff_without_context: TextSerializationFailure
-constructor_tearoffs/instantiation: TypeCheckError
-constructor_tearoffs/nongeneric_tearoff_with_context: TextSerializationFailure
-constructor_tearoffs/nongeneric_tearoff_without_context: TextSerializationFailure
+constructor_tearoffs/call_instantiation: TypeCheckError
+constructor_tearoffs/const_tear_off: RuntimeError
constructor_tearoffs/redirecting_constructors: RuntimeError
-constructor_tearoffs/typedef_tearoffs: TextSerializationFailure
-constructor_tearoffs/unnamed_constructor: TextSerializationFailure
+constructor_tearoffs/redirecting_factory_tear_off: RuntimeError
extension_types/extension_on_nullable: ExpectationFileMismatchSerialized # Expected.
extension_types/issue45775: ExpectationFileMismatchSerialized # Expected.
extension_types/simple: ExpectationFileMismatchSerialized # Expected.
@@ -22,6 +17,7 @@
extension_types/simple_method_resolution: ExpectationFileMismatchSerialized # Expected.
extension_types/simple_operator_resolution: ExpectationFileMismatchSerialized # Expected.
extension_types/simple_setter_resolution: ExpectationFileMismatchSerialized # Expected.
+extension_types/simple_show_hide: ExpectationFileMismatchSerialized # Expected.
extensions/extension_setter_error: TypeCheckError
extensions/instance_access_of_static: RuntimeError
extensions/invalid_explicit_access: RuntimeError
@@ -40,7 +36,6 @@
general/covariant_field: TypeCheckError
general/covariant_generic: RuntimeError
general/crashes/crash_02/main: Crash
-general/crashes/crash_04/main: Crash
general/crashes/crash_06/main: Crash
general/duplicated_declarations: TypeCheckError
general/duplicated_field_initializer: RuntimeError
@@ -91,6 +86,7 @@
general/issue41210a: TypeCheckError
general/issue41210b/issue41210.no_link: TypeCheckError
general/issue41210b/issue41210: TypeCheckError
+general/issue44733: TypeCheckError
general/issue45204: TypeCheckError
general/micro: RuntimeError
general/mixin_application_override: TypeCheckError
@@ -105,6 +101,7 @@
general/override_check_basic: TypeCheckError # Issue #31620
general/override_check_with_covariant_modifier: TypeCheckError # Issue #31620
general/override_setter_with_field: TypeCheckError
+general/redirecting_factory_invocation_in_invalid: TypeCheckError
general/spread_collection: RuntimeError # Should be fixed as part of implementing spread collection support
general/type_parameter_type_named_int: RuntimeError
general/type_variable_as_super: RuntimeError
diff --git a/pkg/front_end/testcases/textual_outline.status b/pkg/front_end/testcases/textual_outline.status
index a8a4fb3..ed0e7e4 100644
--- a/pkg/front_end/testcases/textual_outline.status
+++ b/pkg/front_end/testcases/textual_outline.status
@@ -23,15 +23,27 @@
const_functions/const_functions_const_ctor: FormatterCrash
const_functions/const_functions_const_ctor_error: FormatterCrash
const_functions/const_functions_const_factory: FormatterCrash
+constructor_tearoffs/call_instantiation: FormatterCrash
+constructor_tearoffs/const_tear_off: FormatterCrash
+constructor_tearoffs/dynamic_explicit_instantiation: FormatterCrash
constructor_tearoffs/explicit_instantiation_errors: FormatterCrash
+constructor_tearoffs/explicit_new_as_unnamed: FormatterCrash
constructor_tearoffs/generic_tearoff_with_context: FormatterCrash
constructor_tearoffs/generic_tearoff_without_context: FormatterCrash
constructor_tearoffs/identical_instantiated_function_tearoffs: FormatterCrash
+constructor_tearoffs/inferred_constructor_tear_off: FormatterCrash
+constructor_tearoffs/inferred_non_proper_rename: FormatterCrash
constructor_tearoffs/instantiation: FormatterCrash
+constructor_tearoffs/lowering/inferred_constructor_tear_off: FormatterCrash
+constructor_tearoffs/lowering/inferred_non_proper_rename: FormatterCrash
+constructor_tearoffs/lowering/inferred_tear_off: FormatterCrash
+constructor_tearoffs/lowering/typedef_from_dill/main: FormatterCrash
+constructor_tearoffs/lowering/typedef_identical: FormatterCrash
constructor_tearoffs/nongeneric_tearoff_with_context: FormatterCrash
constructor_tearoffs/nongeneric_tearoff_without_context: FormatterCrash
constructor_tearoffs/redirecting_constructors: FormatterCrash
constructor_tearoffs/simple_instantiated_type_literals: FormatterCrash
+constructor_tearoffs/simple_proper_rename_identity: FormatterCrash
constructor_tearoffs/typedef_tearoffs: FormatterCrash
constructor_tearoffs/unnamed_constructor: FormatterCrash
dart2js/late_fields: FormatterCrash
@@ -40,6 +52,7 @@
extension_types/simple_method_resolution: FormatterCrash
extension_types/simple_operator_resolution: FormatterCrash
extension_types/simple_setter_resolution: FormatterCrash
+extension_types/simple_show_hide: FormatterCrash
extensions/extension_constructor: FormatterCrash
extensions/extension_field_with_type_parameter_usage: FormatterCrash
extensions/issue38600: FormatterCrash
@@ -78,6 +91,7 @@
general/incomplete_field_formal_parameter: FormatterCrash
general/invalid_operator2: FormatterCrash
general/invalid_operator: FormatterCrash
+general/invalid_super_initializer: FormatterCrash
general/issue42997: FormatterCrash
general/issue43363: FormatterCrash
general/issue45490: FormatterCrash
diff --git a/pkg/front_end/testcases/weak.status b/pkg/front_end/testcases/weak.status
index d2ea6a0..8256003 100644
--- a/pkg/front_end/testcases/weak.status
+++ b/pkg/front_end/testcases/weak.status
@@ -11,8 +11,10 @@
regress/utf_16_le_content.crash: SemiFuzzCrash
dart2js/late_statics: SemiFuzzFailure # dartbug.com/45854
-constructor_tearoffs/instantiation: TypeCheckError
+constructor_tearoffs/call_instantiation: TypeCheckError
+constructor_tearoffs/const_tear_off: RuntimeError
constructor_tearoffs/redirecting_constructors: RuntimeError
+constructor_tearoffs/redirecting_factory_tear_off: RuntimeError
extension_types/extension_on_nullable: ExpectationFileMismatchSerialized # Expected.
extension_types/issue45775: ExpectationFileMismatchSerialized # Expected.
extension_types/simple: ExpectationFileMismatchSerialized # Expected.
@@ -20,6 +22,7 @@
extension_types/simple_method_resolution: ExpectationFileMismatchSerialized # Expected.
extension_types/simple_operator_resolution: ExpectationFileMismatchSerialized # Expected.
extension_types/simple_setter_resolution: ExpectationFileMismatchSerialized # Expected.
+extension_types/simple_show_hide: ExpectationFileMismatchSerialized # Expected.
extensions/extension_setter_error: TypeCheckError
extensions/instance_access_of_static: RuntimeError
extensions/invalid_explicit_access: RuntimeError
@@ -38,7 +41,6 @@
general/covariant_field: TypeCheckError
general/covariant_generic: RuntimeError
general/crashes/crash_02/main: Crash
-general/crashes/crash_04/main: Crash
general/crashes/crash_06/main: Crash
general/duplicated_declarations: TypeCheckError
general/duplicated_field_initializer: RuntimeError
@@ -89,6 +91,7 @@
general/issue41210a: TypeCheckError
general/issue41210b/issue41210.no_link: TypeCheckError
general/issue41210b/issue41210: TypeCheckError
+general/issue44733: TypeCheckError
general/issue45204: TypeCheckError
general/micro: RuntimeError
general/mixin_application_override: ExpectationFileMismatch # Too many errors.
@@ -104,6 +107,7 @@
general/override_check_basic: TypeCheckError # Issue #31620
general/override_check_with_covariant_modifier: TypeCheckError # Issue #31620
general/override_setter_with_field: TypeCheckError
+general/redirecting_factory_invocation_in_invalid: TypeCheckError
general/spread_collection: RuntimeError
general/type_parameter_type_named_int: RuntimeError # Expected
general/type_variable_as_super: RuntimeError
diff --git a/pkg/front_end/tool/_fasta/abcompile.dart b/pkg/front_end/tool/_fasta/abcompile.dart
index 26f815a..a9e3125 100644
--- a/pkg/front_end/tool/_fasta/abcompile.dart
+++ b/pkg/front_end/tool/_fasta/abcompile.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart=2.9
-
import 'dart:async';
import 'dart:convert';
import 'dart:math';
@@ -11,7 +9,7 @@
import 'standard_deviation.dart';
-const String bRootPath =
+const String? bRootPath =
bool.hasEnvironment("bRoot") ? String.fromEnvironment("bRoot") : null;
const int abIterations = int.fromEnvironment("abIterations", defaultValue: 15);
const int iterations = int.fromEnvironment("iterations", defaultValue: 15);
@@ -31,7 +29,7 @@
Uri aRoot = Platform.script.resolve('../../../..');
// The root of the other Dart SDK repo "B"
- Uri bRoot = new Uri.directory(bRootPath);
+ Uri bRoot = new Uri.directory(bRootPath!);
// Sanity check
String relPath = 'pkg/front_end/tool/_fasta/compile.dart';
@@ -183,15 +181,15 @@
workingDirectory: workingDirPath);
// ignore: unawaited_futures
stderr.addStream(process.stderr);
- StreamSubscription<String> stdOutSubscription;
+ StreamSubscription<String>? stdOutSubscription;
stdOutSubscription = process.stdout
.transform(utf8.decoder)
.transform(new LineSplitter())
.listen(processLine, onDone: () {
- stdOutSubscription.cancel();
+ stdOutSubscription!.cancel();
}, onError: (e) {
print('Error: $e');
- stdOutSubscription.cancel();
+ stdOutSubscription!.cancel();
});
int code = await process.exitCode;
if (code != 0) {
diff --git a/pkg/front_end/tool/_fasta/bench_maker.dart b/pkg/front_end/tool/_fasta/bench_maker.dart
index 22732a7..4e95837 100644
--- a/pkg/front_end/tool/_fasta/bench_maker.dart
+++ b/pkg/front_end/tool/_fasta/bench_maker.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart=2.9
-
library fasta.tool.entry_points;
import "dart:convert" show JsonEncoder;
@@ -49,8 +47,10 @@
final List<TypeParameter> usedTypeParameters = <TypeParameter>[];
String serializeTypeChecks(List<Object> typeChecks) {
- for (List<Object> list in typeChecks) {
- writeTypeCheck(list[0], list[1], list[2]);
+ for (Object list in typeChecks) {
+ List<Object> typeCheck = list as List<Object>;
+ writeTypeCheck(typeCheck[0] as DartType, typeCheck[1] as DartType,
+ typeCheck[2] as bool);
}
writeClasses();
return jsonEncode(this);
@@ -133,11 +133,11 @@
}
}
- void writeClass(Class cls, Set<Class> writtenClasses) {
+ void writeClass(Class? cls, Set<Class> writtenClasses) {
if (cls == null || !writtenClasses.add(cls)) return;
- Supertype supertype = cls.supertype;
+ Supertype? supertype = cls.supertype;
writeClass(supertype?.classNode, writtenClasses);
- Supertype mixedInType = cls.mixedInType;
+ Supertype? mixedInType = cls.mixedInType;
writeClass(mixedInType?.classNode, writtenClasses);
for (Supertype implementedType in cls.implementedTypes) {
writeClass(implementedType.classNode, writtenClasses);
@@ -164,7 +164,7 @@
implementedType.asInterfaceType.accept1(this, sb);
first = false;
}
- Procedure callOperator;
+ Procedure? callOperator;
for (Procedure procedure in cls.procedures) {
if (procedure.name.text == "call") {
callOperator = procedure;
@@ -183,11 +183,11 @@
}
String computeName(TreeNode node) {
- String name = nodeNames[node];
+ String? name = nodeNames[node];
if (name != null) return name;
if (node is Class) {
Library library = node.enclosingLibrary;
- String uriString = "${library?.importUri}";
+ String uriString = "${library.importUri}";
if (uriString == "dart:core" || uriString == "dart:async") {
if (!usedNames.add(node.name)) {
throw "Class name conflict for $node";
@@ -336,7 +336,7 @@
sb.write(name);
if (node.promotedBound != null) {
sb.write(" & ");
- node.promotedBound.accept1(this, sb);
+ node.promotedBound!.accept1(this, sb);
}
}
diff --git a/pkg/front_end/tool/_fasta/command_line.dart b/pkg/front_end/tool/_fasta/command_line.dart
index d4b5b05..6ab0e47 100644
--- a/pkg/front_end/tool/_fasta/command_line.dart
+++ b/pkg/front_end/tool/_fasta/command_line.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart=2.9
-
library fasta.tool.command_line;
import 'dart:io' show exit;
@@ -110,7 +108,7 @@
/// All other options require an option value, either on the form `--option
/// value` or `--option=value`.
static ParsedArguments parse(
- List<String> arguments, Map<String, ValueSpecification> specification) {
+ List<String> arguments, Map<String, ValueSpecification>? specification) {
specification ??= const <String, ValueSpecification>{};
ParsedArguments result = new ParsedArguments();
int index = arguments.indexOf("--");
@@ -123,7 +121,7 @@
while (iterator.moveNext()) {
String argument = iterator.current;
if (argument.startsWith("-") || argument == "/?" || argument == "/h") {
- String value;
+ String? value;
if (argument.startsWith("-D")) {
value = argument.substring("-D".length);
argument = "-D";
@@ -134,14 +132,14 @@
argument = argument.substring(0, index);
}
}
- ValueSpecification valueSpecification = specification[argument];
+ ValueSpecification? valueSpecification = specification[argument];
if (valueSpecification == null) {
throw new CommandLineProblem.deprecated(
"Unknown option '$argument'.");
}
String canonicalArgument = argument;
if (valueSpecification.alias != null) {
- canonicalArgument = valueSpecification.alias;
+ canonicalArgument = valueSpecification.alias as String;
valueSpecification = specification[valueSpecification.alias];
}
if (valueSpecification == null) {
@@ -268,7 +266,7 @@
enableNullSafety: isExperimentEnabled(ExperimentalFlag.nonNullable,
explicitExperimentalFlags: explicitExperimentalFlags));
- final Target target = getTarget(targetName, flags);
+ final Target? target = getTarget(targetName, flags);
if (target == null) {
return throw new CommandLineProblem.deprecated(
"Target '${targetName}' not recognized. "
@@ -302,7 +300,7 @@
final bool compileSdk = options.containsKey(Flags.compileSdk);
- final String singleRootScheme = options[Flags.singleRootScheme];
+ final String? singleRootScheme = options[Flags.singleRootScheme];
final Uri singleRootBase = options[Flags.singleRootBase];
final bool nnbdStrongMode = options[Flags.nnbdStrongMode];
@@ -418,7 +416,7 @@
throwCommandLineProblem(
"Target '${target.name}' requires an explicit "
"'${Flags.platform}' option.");
- })));
+ })!));
compilerOptions
..sdkRoot = sdk
..sdkSummary = platform
@@ -439,9 +437,9 @@
List<String> arguments,
bool areRestArgumentsInputs,
Future<T> f(CompilerContext context, List<String> restArguments)) {
- ParsedArguments parsedArguments;
+ ParsedArguments? parsedArguments;
ProcessedOptions options;
- CommandLineProblem problem;
+ CommandLineProblem? problem;
try {
parsedArguments = ParsedArguments.parse(arguments, optionSpecification);
options = analyzeCommandLine(
@@ -466,13 +464,13 @@
exit(1);
}
- return f(c, parsedArguments.arguments);
+ return f(c, parsedArguments!.arguments);
}, errorOnMissingInput: problem == null);
}
Message computeUsage(String programName, bool verbose) {
String basicUsage = "Usage: $programName [options] dartfile\n";
- String summary;
+ String? summary;
String options =
(verbose ? messageFastaUsageLong.message : messageFastaUsageShort.message)
.trim();
@@ -508,7 +506,7 @@
}
Future<T> runProtectedFromAbort<T>(Future<T> Function() action,
- [T failingValue]) async {
+ [T? failingValue]) async {
if (CompilerContext.isActive) {
throw "runProtectedFromAbort should be called from 'main',"
" that is, outside a compiler context.";
@@ -527,14 +525,14 @@
abstract class ValueSpecification {
const ValueSpecification();
- String get alias => null;
+ String? get alias => null;
dynamic get defaultValue => null;
bool get requiresValue => true;
void processValue(ParsedArguments result, String canonicalArgument,
- String argument, String value);
+ String argument, String? value);
}
class AliasValue extends ValueSpecification {
@@ -546,7 +544,7 @@
throw new UnsupportedError("AliasValue.requiresValue");
void processValue(ParsedArguments result, String canonicalArgument,
- String argument, String value) {
+ String argument, String? value) {
throw new UnsupportedError("AliasValue.processValue");
}
}
@@ -555,7 +553,7 @@
const UriValue();
void processValue(ParsedArguments result, String canonicalArgument,
- String argument, String value) {
+ String argument, String? value) {
if (result.options.containsKey(canonicalArgument)) {
throw new CommandLineProblem.deprecated(
"Multiple values for '$argument': "
@@ -563,7 +561,7 @@
}
// TODO(ahe): resolve Uris lazily, so that schemes provided by
// other flags can be used for parsed command-line arguments too.
- result.options[canonicalArgument] = resolveInputUri(value);
+ result.options[canonicalArgument] = resolveInputUri(value!);
}
}
@@ -571,13 +569,13 @@
const StringValue();
void processValue(ParsedArguments result, String canonicalArgument,
- String argument, String value) {
+ String argument, String? value) {
if (result.options.containsKey(canonicalArgument)) {
throw new CommandLineProblem.deprecated(
"Multiple values for '$argument': "
"'${result.options[canonicalArgument]}' and '$value'.");
}
- result.options[canonicalArgument] = value;
+ result.options[canonicalArgument] = value!;
}
}
@@ -589,7 +587,7 @@
bool get requiresValue => false;
void processValue(ParsedArguments result, String canonicalArgument,
- String argument, String value) {
+ String argument, String? value) {
if (result.options.containsKey(canonicalArgument)) {
throw new CommandLineProblem.deprecated(
"Multiple values for '$argument': "
@@ -613,13 +611,13 @@
const IntValue();
void processValue(ParsedArguments result, String canonicalArgument,
- String argument, String value) {
+ String argument, String? value) {
if (result.options.containsKey(canonicalArgument)) {
throw new CommandLineProblem.deprecated(
"Multiple values for '$argument': "
"'${result.options[canonicalArgument]}' and '$value'.");
}
- int parsedValue = int.tryParse(value);
+ int? parsedValue = int.tryParse(value!);
if (parsedValue == null) {
throw new CommandLineProblem.deprecated(
"Value for '$argument', '$value', isn't an int.");
@@ -632,8 +630,8 @@
const DefineValue();
void processValue(ParsedArguments result, String canonicalArgument,
- String argument, String value) {
- int index = value.indexOf('=');
+ String argument, String? value) {
+ int index = value!.indexOf('=');
String name;
String expression;
if (index != -1) {
@@ -651,10 +649,10 @@
const StringListValue();
void processValue(ParsedArguments result, String canonicalArgument,
- String argument, String value) {
+ String argument, String? value) {
result.options
.putIfAbsent(canonicalArgument, () => <String>[])
- .addAll(value.split(","));
+ .addAll(value!.split(","));
}
}
@@ -662,9 +660,9 @@
const UriListValue();
void processValue(ParsedArguments result, String canonicalArgument,
- String argument, String value) {
+ String argument, String? value) {
result.options
.putIfAbsent(canonicalArgument, () => <Uri>[])
- .addAll(value.split(",").map(resolveInputUri));
+ .addAll(value!.split(",").map(resolveInputUri));
}
}
diff --git a/pkg/front_end/tool/_fasta/compile_platform_legacy_test.dart b/pkg/front_end/tool/_fasta/compile_platform_legacy_test.dart
index 1f624d3..985026c 100644
--- a/pkg/front_end/tool/_fasta/compile_platform_legacy_test.dart
+++ b/pkg/front_end/tool/_fasta/compile_platform_legacy_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE.md file.
-// @dart=2.9
-
library fasta.test.compile_platform_test;
import 'dart:io';
diff --git a/pkg/front_end/tool/_fasta/compile_platform_test.dart b/pkg/front_end/tool/_fasta/compile_platform_test.dart
index 1f624d3..985026c 100644
--- a/pkg/front_end/tool/_fasta/compile_platform_test.dart
+++ b/pkg/front_end/tool/_fasta/compile_platform_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE.md file.
-// @dart=2.9
-
library fasta.test.compile_platform_test;
import 'dart:io';
diff --git a/pkg/front_end/tool/_fasta/generate_experimental_flags.dart b/pkg/front_end/tool/_fasta/generate_experimental_flags.dart
index f52aee6..a452b9f 100644
--- a/pkg/front_end/tool/_fasta/generate_experimental_flags.dart
+++ b/pkg/front_end/tool/_fasta/generate_experimental_flags.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart=2.9
-
import 'dart:io' show File;
import 'package:_fe_analyzer_shared/src/scanner/characters.dart'
@@ -50,7 +48,7 @@
int currentVersionMajor;
int currentVersionMinor;
{
- String currentVersion = getAsVersionNumberString(yaml['current-version']);
+ String currentVersion = getAsVersionNumberString(yaml['current-version'])!;
List<String> split = currentVersion.split(".");
currentVersionMajor = int.parse(split[0]);
currentVersionMinor = int.parse(split[1]);
@@ -84,7 +82,7 @@
int currentVersionMajor;
int currentVersionMinor;
{
- String currentVersion = getAsVersionNumberString(yaml['current-version']);
+ String currentVersion = getAsVersionNumberString(yaml['current-version'])!;
List<String> split = currentVersion.split(".");
currentVersionMajor = int.parse(split[0]);
currentVersionMinor = int.parse(split[1]);
@@ -135,7 +133,7 @@
for (String key in keys) {
int major;
int minor;
- String enabledIn =
+ String? enabledIn =
getAsVersionNumberString((features[key] as YamlMap)['enabledIn']);
if (enabledIn == null) {
major = currentVersionMajor;
@@ -192,7 +190,7 @@
for (String key in keys) {
int major;
int minor;
- String enabledIn =
+ String? enabledIn =
getAsVersionNumberString((features[key] as YamlMap)['enabledIn']);
if (enabledIn != null) {
List<String> split = enabledIn.split(".");
@@ -213,9 +211,9 @@
for (String key in keys) {
int major;
int minor;
- String enabledIn =
+ String? enabledIn =
getAsVersionNumberString((features[key] as YamlMap)['enabledIn']);
- String experimentalReleaseVersion = getAsVersionNumberString(
+ String? experimentalReleaseVersion = getAsVersionNumberString(
(features[key] as YamlMap)['experimentalReleaseVersion']);
if (experimentalReleaseVersion != null) {
List<String> split = experimentalReleaseVersion.split(".");
@@ -296,7 +294,7 @@
return identifier.toString();
}
-String getAsVersionNumberString(dynamic value) {
+String? getAsVersionNumberString(dynamic value) {
if (value == null) return null;
if (value is String) return value;
if (value is double) return "$value";
diff --git a/pkg/front_end/tool/_fasta/generate_messages.dart b/pkg/front_end/tool/_fasta/generate_messages.dart
index 8ddafe5..3a971c3 100644
--- a/pkg/front_end/tool/_fasta/generate_messages.dart
+++ b/pkg/front_end/tool/_fasta/generate_messages.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart=2.9
-
import 'dart:io' show File, exitCode;
import "package:_fe_analyzer_shared/src/messages/severity.dart"
@@ -96,7 +94,7 @@
while (description is String) {
description = yaml[description];
}
- Map<dynamic, dynamic> map = description;
+ Map<dynamic, dynamic>? map = description;
if (map == null) {
throw "No 'template:' in key $name.";
}
@@ -109,7 +107,7 @@
index = -1;
// Continue looking for other problems.
} else {
- String otherName = indexNameMap[index];
+ String? otherName = indexNameMap[index];
if (otherName != null) {
print('Error: The "index:" field must be unique, '
'but is the same for $otherName and $name');
@@ -166,8 +164,8 @@
Template(this.text, {this.isShared}) : assert(isShared != null);
}
-Template compileTemplate(String name, int index, String template, String tip,
- Object analyzerCode, String severity) {
+Template compileTemplate(String name, int? index, String? template, String? tip,
+ Object? analyzerCode, String? severity) {
if (template == null) {
print('Error: missing template for message: $name');
exitCode = 1;
@@ -194,9 +192,9 @@
for (Match match
in placeholderPattern.allMatches("$template\n${tip ?? ''}")) {
- String name = match[1];
- String padding = match[2];
- String fractionDigits = match[3];
+ String name = match[1]!;
+ String? padding = match[2];
+ String? fractionDigits = match[3];
String format(String name) {
String conversion;
@@ -205,7 +203,7 @@
} else {
conversion = "$name.toStringAsFixed($fractionDigits)";
}
- if (padding.isNotEmpty) {
+ if (padding!.isNotEmpty) {
if (padding.startsWith("0")) {
conversion += ".padLeft(${int.parse(padding)}, '0')";
} else {
@@ -416,13 +414,13 @@
if (analyzerCode is String) {
analyzerCode = <String>[analyzerCode];
}
- List<Object> codes = analyzerCode;
+ List<Object> codes = analyzerCode as List<Object>;
// If "index:" is defined, then "analyzerCode:" should not be generated
// in the front end. See comment in messages.yaml
codeArguments.add('analyzerCodes: <String>["${codes.join('", "')}"]');
}
if (severity != null) {
- String severityEnumName = severityEnumNames[severity];
+ String? severityEnumName = severityEnumNames[severity];
if (severityEnumName == null) {
throw "Unknown severity '$severity'";
}
@@ -430,6 +428,7 @@
}
if (parameters.isEmpty && conversions.isEmpty && arguments.isEmpty) {
+ // ignore: unnecessary_null_comparison
if (template != null) {
codeArguments.add('message: r"""$template"""');
}
@@ -448,6 +447,7 @@
}
List<String> templateArguments = <String>[];
+ // ignore: unnecessary_null_comparison
if (template != null) {
templateArguments.add('messageTemplate: r"""$template"""');
}
diff --git a/pkg/front_end/tool/_fasta/log_analyzer.dart b/pkg/front_end/tool/_fasta/log_analyzer.dart
index 1a794a0..c93e916 100644
--- a/pkg/front_end/tool/_fasta/log_analyzer.dart
+++ b/pkg/front_end/tool/_fasta/log_analyzer.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart=2.9
-
import 'dart:convert' show jsonDecode, jsonEncode;
import 'dart:io';
diff --git a/pkg/front_end/tool/_fasta/log_collector.dart b/pkg/front_end/tool/_fasta/log_collector.dart
index 95dc56f..01fac75 100644
--- a/pkg/front_end/tool/_fasta/log_collector.dart
+++ b/pkg/front_end/tool/_fasta/log_collector.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart=2.9
-
import 'dart:convert' show jsonDecode, utf8;
import 'dart:isolate' show RawReceivePort;
@@ -55,7 +53,7 @@
String month = "${time.month}".padLeft(2, "0");
String day = "${time.day}".padLeft(2, "0");
String us = "${time.microsecondsSinceEpoch}".padLeft(19, '0');
- Uri uri = Uri.base
+ Uri? uri = Uri.base
.resolve("crash_logs/${data['client']}/$year-$month-$day/$us.log");
File file = new File.fromUri(uri);
await file.parent.create(recursive: true);
@@ -63,12 +61,12 @@
print("Wrote ${uri.toFilePath()}");
String type = data["type"];
- String text = data["uri"];
+ String? text = data["uri"];
uri = text == null ? null : Uri.parse(text);
int charOffset = data["offset"];
var error = data["error"];
text = data["trace"];
- StackTrace trace = text == null ? null : new StackTrace.fromString(text);
+ StackTrace? trace = text == null ? null : new StackTrace.fromString(text);
String client = data["client"];
print("""
date: ${time}
diff --git a/pkg/front_end/tool/ast_model.dart b/pkg/front_end/tool/ast_model.dart
new file mode 100644
index 0000000..14f981f
--- /dev/null
+++ b/pkg/front_end/tool/ast_model.dart
@@ -0,0 +1,771 @@
+// 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.
+
+// @dart = 2.9
+
+import 'package:_fe_analyzer_shared/src/messages/diagnostic_message.dart';
+import 'package:front_end/src/api_prototype/front_end.dart';
+import 'package:front_end/src/api_prototype/kernel_generator.dart';
+import 'package:front_end/src/api_prototype/terminal_color_support.dart';
+import 'package:front_end/src/api_unstable/ddc.dart';
+import 'package:front_end/src/compute_platform_binaries_location.dart';
+import 'package:front_end/src/fasta/kernel/kernel_api.dart';
+import 'package:front_end/src/kernel_generator_impl.dart';
+import 'package:kernel/ast.dart';
+import 'package:kernel/class_hierarchy.dart';
+import 'package:kernel/core_types.dart';
+import 'package:kernel/src/printer.dart';
+import 'package:kernel/type_environment.dart';
+
+final Uri astLibraryUri = Uri.parse('package:kernel/ast.dart');
+final Uri canonicalNameLibraryUri =
+ Uri.parse('package:kernel/canonical_name.dart');
+Uri computePackageConfig(Uri repoDir) =>
+ repoDir.resolve('.dart_tool/package_config.json');
+
+/// Map from names of node classes that declares nominal entities that are _not_
+/// referenced through a [Reference] to their identifying name, if any.
+///
+/// For these classes, [_fieldRuleMap] must defined whether fields of these
+/// types should be consider declarations or references to the declarations.
+///
+/// If the identifying name is non-null, this is used to determine the
+/// nominality. For instance the name of a variable declaration is taking as
+/// defining its identity.
+const Map<String, String> _declarativeClassesNames = const {
+ 'VariableDeclaration': 'name',
+ 'TypeParameter': 'name',
+ 'LabeledStatement': null,
+ 'SwitchCase': null,
+};
+
+/// Names of non-node, non-enum classes that should be treated as atomic
+/// values.
+const Set<String> _utilityClassesAsValues = const {
+ 'Version',
+};
+
+/// Names of subclasses of [Node] that do _not_ have `visitX` or `defaultX`
+/// methods.
+const Set<String> _classesWithoutVisitMethods = const {
+ 'InvocationExpression',
+ 'InstanceInvocationExpression',
+ 'NamedNode',
+ 'PrimitiveConstant',
+};
+
+/// Names of subclasses of [NamedNode] that do _not_ have `visitXReference` or
+/// `defaultXReference` methods.
+const Set<String> _classesWithoutVisitReference = const {
+ 'NamedNode',
+ 'Library',
+ 'PrimitiveConstant',
+};
+
+/// Map of [FieldRule]s. These consist of a map for each class name, with
+/// `null` used for "any class". For each class, a map from field names to
+/// [FieldRule] define exceptions to how a field should be treated.
+///
+/// If a field name maps to `null`, the field is not included in the [AstModel].
+const Map<String /*?*/, Map<String, FieldRule /*?*/ >> _fieldRuleMap = {
+ null: {
+ 'hashCode': null,
+ 'parent': null,
+ },
+ 'Component': {
+ 'root': null,
+ '_mainMethodName': FieldRule(name: 'mainMethodName'),
+ '_mode': FieldRule(name: 'mode'),
+ },
+ 'Library': {
+ '_languageVersion': FieldRule(name: 'languageVersion'),
+ '_libraryId': null,
+ '_classes': FieldRule(name: 'classes'),
+ '_typedefs': FieldRule(name: 'typedefs'),
+ '_extensions': FieldRule(name: 'extensions'),
+ '_fields': FieldRule(name: 'fields'),
+ '_procedures': FieldRule(name: 'procedures'),
+ },
+ 'Class': {
+ 'typeParameters': FieldRule(isDeclaration: true),
+ '_constructorsView': null,
+ '_constructorsInternal': FieldRule(name: 'constructors'),
+ '_fieldsView': null,
+ '_fieldsInternal': FieldRule(name: 'fields'),
+ '_proceduresView': null,
+ '_proceduresInternal': FieldRule(name: 'procedures'),
+ '_redirectingFactoriesView': null,
+ '_redirectingFactoriesInternal':
+ FieldRule(name: 'redirectingFactories'),
+ 'lazyBuilder': null,
+ 'dirty': null,
+ },
+ 'Extension': {
+ 'typeParameters': FieldRule(isDeclaration: true),
+ },
+ 'Field': {
+ 'reference': FieldRule(name: 'getterReference'),
+ },
+ 'TypeParameter': {
+ '_variance': FieldRule(name: 'variance'),
+ },
+ 'FunctionNode': {
+ '_body': FieldRule(name: 'body'),
+ 'typeParameters': FieldRule(isDeclaration: true),
+ 'positionalParameters': FieldRule(isDeclaration: true),
+ 'namedParameters': FieldRule(isDeclaration: true),
+ },
+ 'Typedef': {
+ 'typeParameters': FieldRule(isDeclaration: true),
+ 'typeParametersOfFunctionType': FieldRule(isDeclaration: false),
+ 'positionalParameters': FieldRule(isDeclaration: false),
+ 'namedParameters': FieldRule(isDeclaration: false),
+ },
+ 'TypedefTearOff': {
+ 'typeParameters': FieldRule(isDeclaration: true),
+ },
+ 'TypedefTearOffConstant': {
+ 'parameters': FieldRule(isDeclaration: true),
+ },
+ 'LocalInitializer': {
+ 'variable': FieldRule(isDeclaration: true),
+ },
+ 'Let': {
+ 'variable': FieldRule(isDeclaration: true),
+ },
+ 'VariableGet': {
+ 'variable': FieldRule(isDeclaration: false),
+ },
+ 'VariableSet': {
+ 'variable': FieldRule(isDeclaration: false),
+ },
+ 'LocalFunctionInvocation': {
+ 'variable': FieldRule(isDeclaration: false),
+ },
+ 'BreakStatement': {
+ 'target': FieldRule(isDeclaration: false),
+ },
+ 'ForStatement': {
+ 'variables': FieldRule(isDeclaration: true),
+ },
+ 'ForInStatement': {
+ 'variable': FieldRule(isDeclaration: true),
+ },
+ 'SwitchStatement': {
+ 'cases': FieldRule(isDeclaration: true),
+ },
+ 'ContinueSwitchStatement': {
+ 'target': FieldRule(isDeclaration: false),
+ },
+ 'Catch': {
+ 'exception': FieldRule(isDeclaration: true),
+ 'stackTrace': FieldRule(isDeclaration: true),
+ },
+ 'FunctionDeclaration': {
+ 'variable': FieldRule(isDeclaration: true),
+ },
+ 'FunctionType': {
+ 'typeParameters': FieldRule(isDeclaration: true),
+ },
+ 'TypeParameterType': {
+ 'parameter': FieldRule(isDeclaration: false),
+ },
+};
+
+/// Data that determines exceptions to how fields are used.
+class FieldRule {
+ /// If non-null, the field should be accessed by this name.
+ ///
+ /// This is for instance used for private fields accessed through a public
+ /// getter.
+ final String name;
+
+ /// For fields contain ast class of kind `AstClassKind.declarative`, this
+ /// value defines whether the field should be treated as a declaration or
+ /// a reference to the declaration.
+ final bool isDeclaration;
+
+ const FieldRule({this.name, this.isDeclaration});
+}
+
+/// Return the [FieldRule] to use for the [field] in [AstClass].
+FieldRule getFieldRule(AstClass astClass, Field field) {
+ String name = field.name.text;
+ Map<String, FieldRule> leafClassMap = _fieldRuleMap[astClass.name];
+ if (leafClassMap != null && leafClassMap.containsKey(name)) {
+ return leafClassMap[name];
+ }
+ Map<String, FieldRule> enclosingClassMap =
+ _fieldRuleMap[field.enclosingClass.name];
+ if (enclosingClassMap != null && enclosingClassMap.containsKey(name)) {
+ return enclosingClassMap[name];
+ }
+ Map<String, FieldRule> defaultClassMap = _fieldRuleMap[null];
+ if (defaultClassMap != null && defaultClassMap.containsKey(name)) {
+ return defaultClassMap[name];
+ }
+ return new FieldRule(name: name);
+}
+
+/// Categorization of classes declared in 'package:kernel/ast.dart'.
+enum AstClassKind {
+ /// The root [Node] class.
+ root,
+
+ /// An abstract node class that is a superclass of a public class. Most of
+ /// these have a corresponding `defaultX` visitor method.
+ ///
+ /// For instance [Statement] and [Expression].
+ inner,
+
+ /// A concrete node class. These are the classes for which we have `visitX`
+ /// methods.
+ ///
+ /// For instance [Procedure] and [VariableGet].
+ public,
+
+ /// A concrete node class that serves only as an implementation of public
+ /// node class.
+ ///
+ /// For instance [PrivateName] and [PublicName] that implements the public
+ /// node [Name].
+ implementation,
+
+ /// A node class that serves as an interface.
+ ///
+ /// For instance `FileUriNode`.
+ interface,
+
+ /// A named node class that declares a nominal entity that is used with a
+ /// reference.
+ named,
+
+ /// A node class that declares a nominal entity but used without reference.
+ ///
+ /// For instance [VariableDeclaration] which introduces a new entity when it
+ /// occurs in a [Block] but is used as a reference when it occurs in a
+ /// [VariableGet].
+ declarative,
+
+ /// A none-node class that should be treated as a composite structure.
+ ///
+ /// For instance [ConstantMapEntry] which is a tuple of a [Constant] key and
+ /// a [Constant] value.
+ utilityAsStructure,
+
+ /// A none-node class that should be treated as an atomic value.
+ ///
+ /// For instance enum classes.
+ utilityAsValue,
+}
+
+class AstClass {
+ final Class node;
+ AstClassKind _kind;
+ final String declarativeName;
+
+ AstClass superclass;
+ List<AstClass> interfaces = [];
+ List<AstClass> subclasses = [];
+ List<AstClass> subtypes = [];
+
+ List<AstField> fields = [];
+
+ AstClass(this.node,
+ {this.superclass, AstClassKind kind, this.declarativeName})
+ : _kind = kind {
+ if (superclass != null) {
+ superclass.subclasses.add(this);
+ }
+ }
+
+ String get name => node.name;
+
+ AstClassKind get kind {
+ if (_kind == null) {
+ if (node.isAbstract) {
+ if (subclasses.isNotEmpty) {
+ if (subclasses.every(
+ (element) => element.kind == AstClassKind.implementation)) {
+ _kind = AstClassKind.public;
+ } else {
+ _kind = AstClassKind.inner;
+ }
+ } else {
+ _kind = AstClassKind.interface;
+ }
+ } else {
+ if (node.name.startsWith('_')) {
+ _kind = AstClassKind.implementation;
+ } else {
+ _kind = AstClassKind.public;
+ }
+ }
+ }
+ return _kind;
+ }
+
+ /// Returns `true` if this class has a `visitX` or `defaultX` method.
+ ///
+ /// This is only valid for subclass of [Node].
+ bool get hasVisitMethod {
+ switch (kind) {
+ case AstClassKind.root:
+ case AstClassKind.inner:
+ case AstClassKind.public:
+ case AstClassKind.named:
+ case AstClassKind.declarative:
+ return !_classesWithoutVisitMethods.contains(name);
+ case AstClassKind.implementation:
+ case AstClassKind.interface:
+ case AstClassKind.utilityAsStructure:
+ case AstClassKind.utilityAsValue:
+ return false;
+ }
+ throw new UnsupportedError("Unexpected $kind");
+ }
+
+ /// Returns `true` if this class has a `visitXReference` or
+ /// `defaultXReference` method.
+ ///
+ /// This is only valid for subclass of [NamedNode] or [Constant].
+ bool get hasVisitReferenceMethod {
+ switch (kind) {
+ case AstClassKind.root:
+ case AstClassKind.inner:
+ case AstClassKind.public:
+ case AstClassKind.named:
+ case AstClassKind.declarative:
+ return !_classesWithoutVisitReference.contains(name);
+ case AstClassKind.implementation:
+ case AstClassKind.interface:
+ case AstClassKind.utilityAsStructure:
+ case AstClassKind.utilityAsValue:
+ return false;
+ }
+ throw new UnsupportedError("Unexpected $kind");
+ }
+
+ String dump([String indent = ""]) {
+ StringBuffer sb = new StringBuffer();
+ sb.writeln('${indent}${node.name} ($kind)');
+ for (AstField field in fields) {
+ sb.write(field.dump('${indent} '));
+ }
+ for (AstClass subclass in subclasses) {
+ sb.write(subclass.dump('${indent} '));
+ }
+ return sb.toString();
+ }
+
+ String toString() => '${runtimeType}(${name})';
+}
+
+/// Categorization of field types.
+enum AstFieldKind {
+ /// An atomic non-node value.
+ ///
+ /// For instance an [int] value.
+ value,
+
+ /// A [Node] value that is part of the tree.
+ ///
+ /// For instance an [Expression] value.
+ node,
+
+ /// A [Reference] value.
+ reference,
+
+ /// A reference to a declarative [Node].
+ ///
+ /// For instance the reference to [VariableDeclaration] in [VariableGet].
+ use,
+
+ /// A list of values.
+ list,
+
+ /// A set of values.
+ set,
+
+ /// A map of values.
+ map,
+
+ /// A non-node composite value.
+ ///
+ /// For instance a [ConstantMapEntry] that must be treat as a tuple of
+ /// a [Constant] key and a [Constant] value.
+ utility,
+}
+
+/// Structural description of a field type.
+class FieldType {
+ final DartType type;
+ final AstFieldKind kind;
+
+ FieldType(this.type, this.kind);
+
+ String toString() => 'FieldType($type,$kind)';
+}
+
+class ListFieldType extends FieldType {
+ final FieldType elementType;
+
+ ListFieldType(DartType type, this.elementType)
+ : super(type, AstFieldKind.list);
+
+ String toString() => 'ListFieldType($type,$elementType)';
+}
+
+class SetFieldType extends FieldType {
+ final FieldType elementType;
+
+ SetFieldType(DartType type, this.elementType) : super(type, AstFieldKind.set);
+
+ String toString() => 'SetFieldType($type,$elementType)';
+}
+
+class MapFieldType extends FieldType {
+ final FieldType keyType;
+ final FieldType valueType;
+
+ MapFieldType(DartType type, this.keyType, this.valueType)
+ : super(type, AstFieldKind.map);
+
+ String toString() => 'MapFieldType($type,$keyType,$valueType)';
+}
+
+class UtilityFieldType extends FieldType {
+ final AstClass astClass;
+
+ UtilityFieldType(DartType type, this.astClass)
+ : super(type, AstFieldKind.utility);
+
+ String toString() => 'UtilityFieldType($type,$astClass)';
+}
+
+class AstField {
+ final Field node;
+ final String name;
+ final FieldType type;
+
+ AstField(this.node, this.name, this.type);
+
+ String dump([String indent = ""]) {
+ StringBuffer sb = new StringBuffer();
+ sb.writeln('$indent$name $type');
+ return sb.toString();
+ }
+
+ String toString() => '${runtimeType}(${name})';
+}
+
+class AstModel {
+ final AstClass nodeClass;
+ final AstClass namedNodeClass;
+ final AstClass constantClass;
+
+ AstModel(this.nodeClass, this.namedNodeClass, this.constantClass);
+
+ /// Returns an [Iterable] for all declarative [Node] classes in the AST model.
+ Iterable<AstClass> get declarativeClasses {
+ return classes.where((cls) => cls.kind == AstClassKind.declarative);
+ }
+
+ /// Returns an [Iterable] for all [Node] (sub)classes in the AST model.
+ Iterable<AstClass> get classes sync* {
+ Iterable<AstClass> visitClass(AstClass cls) sync* {
+ yield cls;
+ for (AstClass subclass in cls.subclasses) {
+ yield* visitClass(subclass);
+ }
+ }
+
+ yield* visitClass(nodeClass);
+ }
+}
+
+/// Computes the [AstModel] from 'package:kernel/ast' using [repoDir] to locate
+/// the package config file.
+///
+/// If [printDump] is `true`, a dump of the model printed to stdout.
+Future<AstModel> deriveAstModel(Uri repoDir, {bool printDump: false}) async {
+ CompilerOptions options = new CompilerOptions();
+ options.sdkRoot = computePlatformBinariesLocation(forceBuildDir: true);
+ options.packagesFileUri = computePackageConfig(repoDir);
+ options.onDiagnostic = (DiagnosticMessage message) {
+ printDiagnosticMessage(message, print);
+ };
+
+ InternalCompilerResult compilerResult = await kernelForProgramInternal(
+ astLibraryUri, options,
+ retainDataForTesting: true, requireMain: false);
+ ClassHierarchy classHierarchy = compilerResult.classHierarchy;
+ CoreTypes coreTypes = compilerResult.coreTypes;
+ TypeEnvironment typeEnvironment =
+ new TypeEnvironment(coreTypes, classHierarchy);
+
+ Library astLibrary = compilerResult.component.libraries
+ .singleWhere((library) => library.importUri == astLibraryUri);
+
+ bool errorsFound = false;
+ void reportError(String message) {
+ print(message);
+ errorsFound = true;
+ }
+
+ Map<String, String> declarativeClassesNames = {..._declarativeClassesNames};
+ Set<String> classesWithoutVisitMethods = _classesWithoutVisitMethods.toSet();
+ Set<String> classesWithoutVisitReference =
+ _classesWithoutVisitReference.toSet();
+ Map<String, Map<String, FieldRule>> fieldRuleMap = {..._fieldRuleMap};
+ Map<String, FieldRule> nullFieldRules = {...?fieldRuleMap.remove(null)};
+ for (Class cls in astLibrary.classes) {
+ declarativeClassesNames.remove(cls.name);
+ classesWithoutVisitMethods.remove(cls.name);
+ classesWithoutVisitReference.remove(cls.name);
+ Map<String, FieldRule> fieldRules = {...?fieldRuleMap.remove(cls.name)};
+ Set<String> renames = {};
+ Class parent = cls;
+ while (parent != null && parent.enclosingLibrary == astLibrary) {
+ for (Field field in parent.fields) {
+ bool hasFieldRule = fieldRules.containsKey(field.name.text);
+ FieldRule fieldRule = fieldRules.remove(field.name.text);
+ if (fieldRule != null) {
+ if (fieldRule.name != null) {
+ renames.add(fieldRule.name);
+ }
+ }
+ if (!hasFieldRule) {
+ if (!cls.isEnum && !field.isStatic && field.name.isPrivate) {
+ reportError(
+ 'Private field `${field.name.text}` in ${parent.name} must '
+ 'have a field rule.');
+ }
+ }
+ if (nullFieldRules.containsKey(field.name.text)) {
+ FieldRule nullFieldRule = nullFieldRules.remove(field.name.text);
+ if (nullFieldRule != null) {
+ reportError('Only `null` is allowed for class `null`.');
+ }
+ }
+ }
+ parent = parent.superclass;
+ }
+ for (Procedure procedure in cls.procedures) {
+ renames.remove(procedure.name.text);
+ }
+ if (renames.isNotEmpty) {
+ reportError('Unknown procedure(s) for field redirections in '
+ '${cls.name}: ${renames}');
+ }
+ if (fieldRules.isNotEmpty) {
+ reportError(
+ 'Unknown field(s) for rules in ${cls.name}: ${fieldRules.keys}');
+ }
+ }
+ if (declarativeClassesNames.isNotEmpty) {
+ reportError('Unknown declarative classes: ${declarativeClassesNames}');
+ }
+ if (classesWithoutVisitMethods.isNotEmpty) {
+ reportError('Unknown classes without visit methods: '
+ '${classesWithoutVisitMethods}');
+ }
+ if (classesWithoutVisitReference.isNotEmpty) {
+ reportError('Unknown classes without visit reference methods: '
+ '${classesWithoutVisitReference}');
+ }
+ if (fieldRuleMap.isNotEmpty) {
+ reportError('Unknown classes with field rules: ${fieldRuleMap.keys}');
+ }
+
+ Class classNode = astLibrary.classes.singleWhere((cls) => cls.name == 'Node');
+ DartType nullableNodeType =
+ classNode.getThisType(coreTypes, Nullability.nullable);
+
+ Class classNamedNode =
+ astLibrary.classes.singleWhere((cls) => cls.name == 'NamedNode');
+
+ Class classConstant =
+ astLibrary.classes.singleWhere((cls) => cls.name == 'Constant');
+
+ Library canonicalNameLibrary = compilerResult.component.libraries
+ .singleWhere((library) => library.importUri == canonicalNameLibraryUri);
+
+ Class referenceClass = canonicalNameLibrary.classes
+ .singleWhere((cls) => cls.name == 'Reference');
+ DartType nullableReferenceType =
+ referenceClass.getThisType(coreTypes, Nullability.nullable);
+
+ Set<Class> declarativeClasses = {};
+ Set<DartType> declarativeTypes = {};
+ for (String name in _declarativeClassesNames.keys) {
+ Class cls = astLibrary.classes.singleWhere((cls) => cls.name == name);
+ declarativeClasses.add(cls);
+ declarativeTypes.add(cls.getThisType(coreTypes, Nullability.nullable));
+ }
+
+ Map<Class, AstClass> classMap = {};
+
+ /// Computes the [AstClass] corresponding to [node] if [node] is declared in
+ /// 'package:kernel/ast.dart'.
+ AstClass computeAstClass(Class node) {
+ if (node == null) return null;
+ if (node.enclosingLibrary != astLibrary) return null;
+
+ AstClass astClass = classMap[node];
+ if (astClass == null) {
+ if (node == classNode) {
+ astClass = new AstClass(node, kind: AstClassKind.root);
+ } else if (classHierarchy.isSubtypeOf(node, classNode)) {
+ AstClass superclass = computeAstClass(node.superclass);
+ AstClassKind kind;
+ String declarativeName;
+ if (!node.isAbstract &&
+ classHierarchy.isSubtypeOf(node, classNamedNode)) {
+ kind = AstClassKind.named;
+ } else if (declarativeClasses.contains(node)) {
+ kind = AstClassKind.declarative;
+ declarativeName = _declarativeClassesNames[node.name];
+ }
+ astClass = new AstClass(node,
+ superclass: superclass,
+ kind: kind,
+ declarativeName: declarativeName);
+ for (Supertype supertype in node.implementedTypes) {
+ AstClass astSupertype = computeAstClass(supertype.classNode);
+ if (astSupertype != null) {
+ astClass.interfaces.add(astSupertype);
+ astSupertype.subtypes.add(astClass);
+ }
+ }
+ } else if (node.isEnum || _utilityClassesAsValues.contains(node.name)) {
+ astClass = new AstClass(node, kind: AstClassKind.utilityAsValue);
+ } else {
+ AstClass superclass = computeAstClass(node.superclass);
+ astClass = new AstClass(node,
+ superclass: superclass, kind: AstClassKind.utilityAsStructure);
+ }
+ if (astClass != null) {
+ classMap[node] = astClass;
+ }
+ }
+ return astClass;
+ }
+
+ for (Class cls in astLibrary.classes) {
+ computeAstClass(cls);
+ }
+
+ for (AstClass astClass in classMap.values) {
+ void computeAstField(Field field, Substitution substitution) {
+ if (field.isStatic) {
+ return;
+ }
+ FieldRule rule = getFieldRule(astClass, field);
+ if (rule == null) {
+ return;
+ }
+ DartType type = substitution.substituteType(field.type);
+
+ FieldType computeFieldType(DartType type) {
+ bool isDeclarativeType = false;
+ for (InterfaceType declarativeType in declarativeTypes) {
+ if (type is InterfaceType &&
+ typeEnvironment.isSubtypeOf(
+ type, declarativeType, SubtypeCheckMode.withNullabilities)) {
+ isDeclarativeType = true;
+ break;
+ }
+ }
+ if (isDeclarativeType) {
+ if (rule.isDeclaration == null) {
+ reportError(
+ "No field rule for '${field.name}' in ${astClass.name}.\n"
+ "The field type contains the declarative type "
+ "'${type.toText(defaultAstTextStrategy)}' "
+ "and a rule must therefore specify "
+ "whether this constitutes declarative or referential use.");
+ }
+ if (!rule.isDeclaration) {
+ return new FieldType(type, AstFieldKind.use);
+ }
+ }
+ if (type is InterfaceType &&
+ typeEnvironment.isSubtypeOf(type, coreTypes.listNullableRawType,
+ SubtypeCheckMode.withNullabilities)) {
+ DartType elementType = typeEnvironment
+ .getTypeArgumentsAsInstanceOf(type, coreTypes.listClass)
+ .single;
+ return new ListFieldType(type, computeFieldType(elementType));
+ } else if (type is InterfaceType &&
+ typeEnvironment.isSubtypeOf(type, coreTypes.setNullableRawType,
+ SubtypeCheckMode.withNullabilities)) {
+ DartType elementType = typeEnvironment
+ .getTypeArgumentsAsInstanceOf(type, coreTypes.setClass)
+ .single;
+ return new SetFieldType(type, computeFieldType(elementType));
+ } else if (type is InterfaceType &&
+ typeEnvironment.isSubtypeOf(type, coreTypes.mapNullableRawType,
+ SubtypeCheckMode.withNullabilities)) {
+ List<DartType> typeArguments = typeEnvironment
+ .getTypeArgumentsAsInstanceOf(type, coreTypes.mapClass);
+ return new MapFieldType(type, computeFieldType(typeArguments[0]),
+ computeFieldType(typeArguments[1]));
+ } else if (type is InterfaceType &&
+ typeEnvironment.isSubtypeOf(
+ type, nullableNodeType, SubtypeCheckMode.withNullabilities)) {
+ return new FieldType(type, AstFieldKind.node);
+ } else if (type is InterfaceType &&
+ typeEnvironment.isSubtypeOf(type, nullableReferenceType,
+ SubtypeCheckMode.withNullabilities)) {
+ return new FieldType(type, AstFieldKind.reference);
+ } else {
+ if (type is InterfaceType) {
+ AstClass astClass = classMap[type.classNode];
+ if (astClass != null &&
+ astClass.kind == AstClassKind.utilityAsStructure) {
+ return new UtilityFieldType(type, astClass);
+ }
+ }
+ return new FieldType(type, AstFieldKind.value);
+ }
+ }
+
+ FieldType fieldType;
+ fieldType ??= computeFieldType(type);
+ astClass.fields
+ .add(new AstField(field, rule.name ?? field.name.text, fieldType));
+ }
+
+ AstClass parent = astClass;
+ Substitution substitution = Substitution.empty;
+ while (parent != null) {
+ for (Field field in parent.node.fields) {
+ computeAstField(field, substitution);
+ }
+ parent = parent.superclass;
+ if (parent != null) {
+ substitution = Substitution.fromSupertype(
+ classHierarchy.getClassAsInstanceOf(astClass.node, parent.node));
+ }
+ }
+ }
+
+ AstClass astClassNode = classMap[classNode];
+ AstClass astClassNamedNode = classMap[classNamedNode];
+ AstClass astClassConstant = classMap[classConstant];
+
+ if (printDump) {
+ print(classMap[classNode].dump());
+ for (AstClass astClass in classMap.values) {
+ if (astClass != astClassNode && astClass.superclass == null) {
+ print(astClass.dump());
+ }
+ }
+ }
+ if (errorsFound) {
+ throw 'Errors found';
+ }
+ return new AstModel(astClassNode, astClassNamedNode, astClassConstant);
+}
diff --git a/pkg/front_end/tool/dart_doctest_impl.dart b/pkg/front_end/tool/dart_doctest_impl.dart
index 3051c00e..38e9a55 100644
--- a/pkg/front_end/tool/dart_doctest_impl.dart
+++ b/pkg/front_end/tool/dart_doctest_impl.dart
@@ -789,7 +789,7 @@
LibraryBuilder libraryBuilder = userCode!.loader
.read(libraryUri, -1, accessor: userCode!.loader.first);
- userCode!.loader.seenMessages.clear();
+ userCode!.loader.resetSeenMessages();
_dartDocTestLibraryBuilder = libraryBuilder;
_dartDocTestCode = dartDocTestCode;
diff --git a/pkg/front_end/tool/fasta.dart b/pkg/front_end/tool/fasta.dart
index b2b8d26..af6094b 100644
--- a/pkg/front_end/tool/fasta.dart
+++ b/pkg/front_end/tool/fasta.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart=2.9
-
import 'dart:io';
import '../test/utils/io_utils.dart' show computeRepoDir;
@@ -95,7 +93,7 @@
exitCode = await process.exitCode;
}
-void stop(String message) {
+Never stop(String message) {
stderr.write(message);
exit(2);
}
diff --git a/pkg/front_end/tool/generate_ast_equivalence.dart b/pkg/front_end/tool/generate_ast_equivalence.dart
new file mode 100644
index 0000000..87349d6
--- /dev/null
+++ b/pkg/front_end/tool/generate_ast_equivalence.dart
@@ -0,0 +1,956 @@
+// 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.
+
+// @dart = 2.9
+
+import 'dart:io';
+
+import 'ast_model.dart';
+import 'visitor_generator.dart';
+
+Uri computeEquivalenceUri(Uri repoDir) {
+ return repoDir.resolve('pkg/kernel/lib/src/equivalence.dart');
+}
+
+main(List<String> args) async {
+ Uri output = args.isEmpty
+ ? computeEquivalenceUri(Uri.base)
+ : new File(args[0]).absolute.uri;
+ String result = await generateAstEquivalence(Uri.base);
+ new File.fromUri(output).writeAsStringSync(result);
+}
+
+Future<String> generateAstEquivalence(Uri repoDir) async {
+ AstModel astModel = await deriveAstModel(repoDir);
+ return generateVisitor(astModel, new EquivalenceVisitorStrategy());
+}
+
+class EquivalenceVisitorStrategy extends Visitor1Strategy {
+ Map<AstClass, String> _classStrategyMembers = {};
+ Map<AstField, String> _fieldStrategyMembers = {};
+
+ EquivalenceVisitorStrategy();
+
+ @override
+ String get argumentType => 'Node';
+
+ @override
+ String get argumentName => 'other';
+
+ @override
+ String get returnType => 'bool';
+
+ @override
+ String get visitorName => 'EquivalenceVisitor';
+
+ String get strategyName => 'EquivalenceStrategy';
+
+ String get internalCheckValues => '_checkValues';
+
+ String get checkValues => 'checkValues';
+
+ String get matchValues => 'matchValues';
+
+ String get internalCheckNodes => '_checkNodes';
+
+ String get checkNodes => 'checkNodes';
+
+ String get shallowMatchNodes => 'shallowMatchNodes';
+
+ String get deepMatchNodes => 'deepMatchNodes';
+
+ String get internalCheckReferences => '_checkReferences';
+
+ String get checkReferences => 'checkReferences';
+
+ String get matchReferences => 'matchReferences';
+
+ String get deepMatchReferences => 'deeplyMatchReferences';
+
+ String get matchNamedNodes => 'matchNamedNodes';
+
+ String get assumeReferences => 'assumeReferences';
+
+ String get checkAssumedReferences => 'checkAssumedReferences';
+
+ String get checkDeclarations => 'checkDeclarations';
+
+ String get internalCheckDeclarations => '_checkDeclarations';
+
+ String get shallowMatchDeclarations => 'matchDeclarations';
+
+ String get deepMatchDeclarations => 'deepMatchDeclarations';
+
+ String get assumeDeclarations => 'assumeDeclarations';
+
+ String get checkAssumedDeclarations => 'checkAssumedDeclarations';
+
+ String get checkLists => 'checkLists';
+
+ String get matchLists => 'matchLists';
+
+ String get checkSets => 'checkSets';
+
+ String get matchSets => 'matchSets';
+
+ String get checkMaps => 'checkMaps';
+
+ String get matchMaps => 'matchMaps';
+
+ String get checkingState => '_checkingState';
+
+ String get resultOnInequivalence => 'resultOnInequivalence';
+
+ String get registerInequivalence => 'registerInequivalence';
+
+ String classCheckName(AstClass astClass) => 'check${astClass.name}';
+
+ String fieldCheckName(AstClass astClass, AstField field) =>
+ 'check${astClass.name}_${field.name}';
+
+ @override
+ void handleDefaultVisit(AstClass astClass, StringBuffer sb) {
+ sb.writeln('''
+ return false;''');
+ }
+
+ /// Compute the expression code for shallow matching two values of type
+ /// [fieldType].
+ ///
+ /// Shallow matching is used to pair value when checking sets and maps. The
+ /// checking doesn't traverse the AST deeply and inequivalences are not
+ /// registered.
+ ///
+ /// [prefix] is used as the receiver of the invocation.
+ String computeMatchingHelper(FieldType fieldType, [String prefix = '']) {
+ String thisName = 'a';
+ String otherName = 'b';
+ switch (fieldType.kind) {
+ case AstFieldKind.value:
+ return '$prefix$matchValues';
+ case AstFieldKind.node:
+ return '$prefix$shallowMatchNodes';
+ case AstFieldKind.reference:
+ return '$prefix$matchReferences';
+ case AstFieldKind.use:
+ return '$prefix$shallowMatchDeclarations';
+ case AstFieldKind.list:
+ ListFieldType listFieldType = fieldType;
+ String elementEquivalence =
+ computeMatchingHelper(listFieldType.elementType);
+ return '($thisName, $otherName) => $prefix$matchLists('
+ '$thisName, $otherName, $elementEquivalence)';
+ case AstFieldKind.set:
+ SetFieldType setFieldType = fieldType;
+ String elementMatching =
+ computeMatchingHelper(setFieldType.elementType);
+ String elementEquivalence =
+ computeEquivalenceHelper(setFieldType.elementType);
+ return '($thisName, $otherName) => $prefix$checkSets('
+ '$thisName, $otherName, $elementMatching, $elementEquivalence)';
+ case AstFieldKind.map:
+ MapFieldType mapFieldType = fieldType;
+ String keyMatching = computeMatchingHelper(mapFieldType.keyType);
+ String keyEquivalence = computeEquivalenceHelper(mapFieldType.keyType);
+ String valueEquivalence =
+ computeEquivalenceHelper(mapFieldType.valueType);
+ return '($thisName, $otherName) => $prefix$checkMaps('
+ '$thisName, $otherName, $keyMatching, '
+ '$keyEquivalence, $valueEquivalence)';
+ case AstFieldKind.utility:
+ StringBuffer sb = new StringBuffer();
+ UtilityFieldType utilityFieldType = fieldType;
+ registerAstClassEquivalence(utilityFieldType.astClass);
+ sb.writeln('''($thisName, $otherName, _) {
+ if (identical($thisName, $otherName)) return true;
+ if ($thisName is! ${utilityFieldType.astClass.name}) return false;
+ if ($otherName is! ${utilityFieldType.astClass.name}) return false;
+ return ${classCheckName(utilityFieldType.astClass)}(
+ visitor,
+ $thisName,
+ $otherName);
+ }''');
+ return sb.toString();
+ }
+ throw ArgumentError("Unexpected field type ${fieldType}");
+ }
+
+ /// Computes the expression code for checking the equivalence of two fields
+ /// of type [fieldType].
+ ///
+ /// Checking is used to check the AST for equivalence and inequivalences are
+ /// registered.
+ ///
+ /// [prefix] is used as the receiver of the invocation.
+ String computeEquivalenceHelper(FieldType fieldType, [String prefix = '']) {
+ String thisName = 'a';
+ String otherName = 'b';
+ switch (fieldType.kind) {
+ case AstFieldKind.value:
+ return '$prefix$checkValues';
+ case AstFieldKind.node:
+ return '$prefix$checkNodes';
+ case AstFieldKind.reference:
+ return '$prefix$checkReferences';
+ case AstFieldKind.use:
+ return '$prefix$checkDeclarations';
+ case AstFieldKind.list:
+ ListFieldType listFieldType = fieldType;
+ String elementEquivalence =
+ computeEquivalenceHelper(listFieldType.elementType);
+ return '($thisName, $otherName) => $prefix$checkLists('
+ '$thisName, $otherName, $elementEquivalence)';
+ case AstFieldKind.set:
+ SetFieldType setFieldType = fieldType;
+ String elementMatching =
+ computeMatchingHelper(setFieldType.elementType);
+ String elementEquivalence =
+ computeEquivalenceHelper(setFieldType.elementType);
+ return '($thisName, $otherName) => $prefix$checkSets('
+ '$thisName, $otherName, $elementMatching, $elementEquivalence)';
+ case AstFieldKind.map:
+ MapFieldType mapFieldType = fieldType;
+ String keyMatching = computeMatchingHelper(mapFieldType.keyType);
+ String keyEquivalence = computeEquivalenceHelper(mapFieldType.keyType);
+ String valueEquivalence =
+ computeEquivalenceHelper(mapFieldType.valueType);
+ return '($thisName, $otherName) => $prefix$checkMaps('
+ '$thisName, $otherName, $keyMatching, '
+ '$keyEquivalence, $valueEquivalence)';
+ case AstFieldKind.utility:
+ StringBuffer sb = new StringBuffer();
+ UtilityFieldType utilityFieldType = fieldType;
+ registerAstClassEquivalence(utilityFieldType.astClass);
+ sb.writeln('''($thisName, $otherName, _) {
+ if (identical($thisName, $otherName)) return true;
+ if ($thisName is! ${utilityFieldType.astClass.name}) return false;
+ if ($otherName is! ${utilityFieldType.astClass.name}) return false;
+ return ${classCheckName(utilityFieldType.astClass)}(
+ visitor,
+ $thisName,
+ $otherName);
+ }''');
+ return sb.toString();
+ }
+ throw ArgumentError("Unexpected field type ${fieldType}");
+ }
+
+ /// Registers that a strategy method is needed for checking [astClass].
+ ///
+ /// If the method has not already been generated, it is generated and stored
+ /// in [_classStrategyMembers].
+ void registerAstClassEquivalence(AstClass astClass) {
+ if (_classStrategyMembers.containsKey(astClass)) return;
+
+ String thisName = 'node';
+ String otherName = 'other';
+ StringBuffer classStrategy = new StringBuffer();
+ classStrategy.writeln('''
+ bool ${classCheckName(astClass)}(
+ $visitorName visitor,
+ ${astClass.name}? $thisName,
+ Object? $otherName) {''');
+
+ classStrategy.writeln('''
+ if (identical($thisName, $otherName)) return true;
+ if ($thisName is! ${astClass.name}) return false;
+ if ($otherName is! ${astClass.name}) return false;''');
+ if (astClass.kind == AstClassKind.named) {
+ classStrategy.writeln('''
+ if (!visitor.$matchNamedNodes($thisName, $otherName)) {
+ return false;
+ }''');
+ } else if (astClass.kind == AstClassKind.declarative) {
+ classStrategy.writeln('''
+ if (!visitor.$checkDeclarations($thisName, $otherName, '')) {
+ return false;
+ }''');
+ }
+
+ if (astClass.kind != AstClassKind.utilityAsStructure) {
+ classStrategy.writeln('''
+ visitor.pushNodeState($thisName, $otherName);''');
+ }
+ classStrategy.writeln('''
+ bool result = true;''');
+ for (AstField field in astClass.fields) {
+ registerAstFieldEquivalence(astClass, field);
+ classStrategy.writeln('''
+ if (!${fieldCheckName(astClass, field)}(visitor, $thisName, $otherName)) {
+ result = visitor.$resultOnInequivalence;
+ }''');
+ }
+
+ if (astClass.kind != AstClassKind.utilityAsStructure) {
+ classStrategy.writeln('''
+ visitor.popState();''');
+ }
+
+ classStrategy.writeln('''
+ return result;
+ }''');
+
+ _classStrategyMembers[astClass] = classStrategy.toString();
+ }
+
+ /// Registers that a strategy method is needed for checking [field] in
+ /// [astClass].
+ ///
+ /// If the method has not already been generated, it is generated and stored
+ /// in [_fieldStrategyMembers].
+ void registerAstFieldEquivalence(AstClass astClass, AstField field) {
+ if (_fieldStrategyMembers.containsKey(field)) return;
+
+ String thisName = 'node';
+ String otherName = 'other';
+ StringBuffer fieldStrategy = new StringBuffer();
+ fieldStrategy.writeln('''
+ bool ${fieldCheckName(astClass, field)}(
+ $visitorName visitor,
+ ${astClass.name} $thisName,
+ ${astClass.name} $otherName) {''');
+
+ switch (field.type.kind) {
+ case AstFieldKind.value:
+ fieldStrategy.writeln('''
+ return visitor.$checkValues(
+ $thisName.${field.name},
+ $otherName.${field.name},
+ '${field.name}');''');
+ break;
+ case AstFieldKind.node:
+ fieldStrategy.writeln('''
+ return visitor.$checkNodes(
+ $thisName.${field.name},
+ $otherName.${field.name},
+ '${field.name}');''');
+ break;
+ case AstFieldKind.reference:
+ fieldStrategy.writeln('''
+ return visitor.$checkReferences(
+ $thisName.${field.name},
+ $otherName.${field.name},
+ '${field.name}');''');
+ break;
+ case AstFieldKind.use:
+ fieldStrategy.writeln('''
+ return visitor.$checkDeclarations(
+ $thisName.${field.name},
+ $otherName.${field.name},
+ '${field.name}');''');
+ break;
+ case AstFieldKind.list:
+ ListFieldType listFieldType = field.type;
+ fieldStrategy.writeln('''
+ return visitor.$checkLists(
+ $thisName.${field.name},
+ $otherName.${field.name},
+ ${computeEquivalenceHelper(listFieldType.elementType, 'visitor.')},
+ '${field.name}');''');
+ break;
+ case AstFieldKind.set:
+ SetFieldType setFieldType = field.type;
+ fieldStrategy.writeln('''
+ return visitor.$checkSets(
+ $thisName.${field.name},
+ $otherName.${field.name},
+ ${computeMatchingHelper(setFieldType.elementType, 'visitor.')},
+ ${computeEquivalenceHelper(setFieldType.elementType, 'visitor.')},
+ '${field.name}');''');
+ break;
+ case AstFieldKind.map:
+ MapFieldType mapFieldType = field.type;
+ fieldStrategy.writeln('''
+ return visitor.$checkMaps(
+ $thisName.${field.name},
+ $otherName.${field.name},
+ ${computeMatchingHelper(mapFieldType.keyType, 'visitor.')},
+ ${computeEquivalenceHelper(mapFieldType.keyType, 'visitor.')},
+ ${computeEquivalenceHelper(mapFieldType.valueType, 'visitor.')},
+ '${field.name}');''');
+ break;
+ case AstFieldKind.utility:
+ UtilityFieldType utilityFieldType = field.type;
+ registerAstClassEquivalence(utilityFieldType.astClass);
+ fieldStrategy.writeln('''
+ '${field.name}';
+ return ${classCheckName(utilityFieldType.astClass)}(
+ visitor,
+ $thisName.${field.name},
+ $otherName.${field.name});''');
+ break;
+ }
+ fieldStrategy.writeln('''
+ }''');
+ _fieldStrategyMembers[field] = fieldStrategy.toString();
+ }
+
+ @override
+ void handleVisit(AstClass astClass, StringBuffer sb) {
+ registerAstClassEquivalence(astClass);
+ sb.writeln('''
+ return strategy.${classCheckName(astClass)}(
+ this, node, $argumentName);''');
+ }
+
+ @override
+ void handleDefaultVisitReference(AstClass astClass, StringBuffer sb) {
+ sb.writeln('''
+ return false;''');
+ }
+
+ @override
+ void handleVisitReference(AstClass astClass, StringBuffer sb) {
+ sb.writeln('''
+ return false;''');
+ }
+
+ void generateHeader(AstModel astModel, StringBuffer sb) {
+ sb.writeln('''
+// 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.
+
+// NOTE: THIS FILE IS GENERATED. DO NOT EDIT.
+//
+// Run 'dart pkg/front_end/tool/generate_ast_equivalence.dart' to update.
+
+import 'package:kernel/ast.dart';
+import 'package:kernel/src/printer.dart';
+import 'union_find.dart';
+
+part 'equivalence_helpers.dart';
+
+/// Visitor that uses a $strategyName to compute AST node equivalence.
+///
+/// The visitor hold a current state that collects found inequivalences and
+/// current assumptions. The current state has two modes. In the asserting mode,
+/// the default, inequivalences are registered when found. In the non-asserting
+/// mode, inequivalences are _not_ registered. The latter is used to compute
+/// equivalences in sand boxed state, for instance to determine which elements
+/// to pair when checking equivalence of two sets.
+class $visitorName$visitorTypeParameters
+ implements Visitor1<$returnType, $argumentType> {
+ final $strategyName strategy;
+
+ $visitorName({
+ this.strategy: const $strategyName()});
+''');
+ }
+
+ @override
+ void generateFooter(AstModel astModel, StringBuffer sb) {
+ sb.writeln('''
+ /// Returns `true` if [a] and [b] are identical or equal.
+ bool $internalCheckValues<T>(T? a, T? b) {
+ return identical(a, b) || a == b;
+ }
+
+ /// Returns `true` if [a] and [b] are identical or equal and registers the
+ /// inequivalence otherwise.
+ bool $checkValues<T>(T? a, T? b, String propertyName) {
+ bool result = $internalCheckValues(a, b);
+ if (!result) {
+ registerInequivalence(
+ propertyName, 'Values \${a} and \${b} are not equivalent');
+ }
+ return result;
+ }
+
+ /// Returns `true` if [a] and [b] are identical or equal. Inequivalence is
+ /// _not_ registered.
+ bool $matchValues<T>(T? a, T? b) {
+ return $internalCheckValues(a, b);
+ }
+
+ /// Returns `true` if [a] and [b] are equivalent.
+ bool $internalCheckNodes<T extends Node>(T? a, T? b) {
+ if (identical(a, b)) return true;
+ if (a == null || b == null) {
+ return false;
+ } else {
+ return a.accept1(this, b);
+ }
+ }
+
+ /// Returns `true` if [a] and [b] are equivalent, as defined by the current
+ /// strategy, and registers the inequivalence otherwise.
+ bool $checkNodes<T extends Node>(T? a, T? b,
+ [String propertyName = '']) {
+ $checkingState.pushPropertyState(propertyName);
+ bool result = $internalCheckNodes(a, b);
+ $checkingState.popState();
+ if (!result) {
+ $registerInequivalence(
+ propertyName, 'Inequivalent nodes\\n1: \${a}\\n2: \${b}');
+ }
+ return result;
+ }
+
+ /// Returns `true` if [a] and [b] are identical or equal. Inequivalence is
+ /// _not_ registered.
+ bool $shallowMatchNodes<T extends Node>(T? a, T? b) {
+ return $internalCheckValues(a, b);
+ }
+
+ /// Returns `true` if [a] and [b] are equivalent, as defined by the current
+ /// strategy. Inequivalence is _not_ registered.
+ bool $deepMatchNodes<T extends Node>(T? a, T? b) {
+ CheckingState oldState = $checkingState;
+ $checkingState = $checkingState.toMatchingState();
+ bool result = $checkNodes(a, b);
+ $checkingState = oldState;
+ return result;
+ }
+
+ /// Returns `true` if [a] and [b] are equivalent, as defined by their
+ /// corresponding canonical names. Inequivalence is _not_ registered.
+ bool $matchNamedNodes(NamedNode? a, NamedNode? b) {
+ return identical(a, b) ||
+ a == null ||
+ b == null ||
+ new ReferenceName.fromNamedNode(a) ==
+ new ReferenceName.fromNamedNode(b);
+ }
+
+ /// Returns `true` if [a] and [b] are currently assumed to be equivalent.
+ bool $checkAssumedReferences(Reference? a, Reference? b) {
+ return $checkingState.$checkAssumedReferences(a, b);
+ }
+
+ /// Assume that [a] and [b] are equivalent, if possible.
+ ///
+ /// Returns `true` if [a] and [b] could be assumed to be equivalent. This
+ /// would not be the case if [a] xor [b] is `null`.
+ bool $assumeReferences(Reference? a, Reference? b) {
+ return $checkingState.$assumeReferences(a, b);
+ }
+
+ /// Returns `true` if [a] and [b] are equivalent, as defined by their
+ /// corresponding canonical names. Inequivalence is _not_ registered.
+ bool $matchReferences(Reference? a, Reference? b) {
+ return identical(a, b) ||
+ ReferenceName.fromReference(a) ==
+ ReferenceName.fromReference(b);
+ }
+
+ /// Returns `true` if [a] and [b] are equivalent, either by their
+ /// corresponding canonical names or by assumption. Inequivalence is _not_
+ /// registered.
+ bool $internalCheckReferences(Reference? a, Reference? b) {
+ if (identical(a, b)) {
+ return true;
+ } else if (a == null || b == null) {
+ return false;
+ } else if ($matchReferences(a, b)) {
+ return true;
+ } else if ($checkAssumedReferences(a, b)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /// Returns `true` if [a] and [b] are equivalent, either by their
+ /// corresponding canonical names or by assumption. Inequivalence is _not_
+ /// registered.
+ bool $deepMatchReferences(Reference? a, Reference? b) {
+ CheckingState oldState = $checkingState;
+ $checkingState = $checkingState.toMatchingState();
+ bool result = $checkReferences(a, b);
+ $checkingState = oldState;
+ return result;
+ }
+
+ /// Returns `true` if [a] and [b] are equivalent, either by their
+ /// corresponding canonical names or by assumption, and registers the
+ /// inequivalence otherwise.
+ bool $checkReferences(
+ Reference? a,
+ Reference? b,
+ [String propertyName = '']) {
+ bool result = $internalCheckReferences(a, b);
+ if (!result) {
+ $registerInequivalence(
+ propertyName, 'Inequivalent references:\\n1: \${a}\\n2: \${b}');
+ }
+ return result;
+ }
+
+ /// Returns `true` if declarations [a] and [b] are currently assumed to be
+ /// equivalent.
+ bool $checkAssumedDeclarations(dynamic a, dynamic b) {
+ return $checkingState.$checkAssumedDeclarations(a, b);
+ }
+
+ /// Assume that [a] and [b] are equivalent, if possible.
+ ///
+ /// Returns `true` if [a] and [b] could be assumed to be equivalent. This
+ /// would not be the case if [a] is already assumed to be equivalent to
+ /// another declaration.
+ bool $assumeDeclarations(dynamic a, dynamic b) {
+ return $checkingState.$assumeDeclarations(a, b);
+ }
+
+ bool $shallowMatchDeclarations(dynamic a, dynamic b) {''');
+
+ for (AstClass cls in astModel.declarativeClasses) {
+ if (cls.declarativeName != null) {
+ sb.write('''
+ if (a is ${cls.name}) {
+ return b is ${cls.name} &&
+ a.${cls.declarativeName} == b.${cls.declarativeName};
+ }
+''');
+ } else {
+ sb.write('''
+ if (a is ${cls.name}) {
+ return b is ${cls.name};
+ }
+''');
+ }
+ }
+ try {
+ try {
+ try {
+ sb.writeln('''
+ return false;
+ }
+
+ bool $internalCheckDeclarations(dynamic a, dynamic b) {
+ if (identical(a, b)) {
+ return true;
+ } else if (a == null || b == null) {
+ return false;
+ } else if ($checkAssumedDeclarations(a, b)) {
+ return true;
+ } else if ($shallowMatchDeclarations(a, b)) {
+ return $assumeDeclarations(a, b);
+ } else {
+ return false;
+ }
+ }
+
+ bool $deepMatchDeclarations(dynamic a, dynamic b) {
+ CheckingState oldState = $checkingState;
+ $checkingState = $checkingState.toMatchingState();
+ bool result = $checkDeclarations(a, b);
+ $checkingState = oldState;
+ return result;
+ }
+
+ bool $checkDeclarations(dynamic a, dynamic b,
+ [String propertyName = '']) {
+ bool result = $internalCheckDeclarations(a, b);
+ if (!result) {
+ result = $assumeDeclarations(a, b);
+ }
+ if (!result) {
+ $registerInequivalence(
+ propertyName, 'Declarations \${a} and \${b} are not equivalent');
+ }
+ return result;
+ }
+
+ /// Returns `true` if lists [a] and [b] are equivalent, using
+ /// [equivalentValues] to determine element-wise equivalence.
+ ///
+ /// If run in a checking state, the [propertyName] is used for registering
+ /// inequivalences.
+ bool $checkLists<E>(
+ List<E>? a,
+ List<E>? b,
+ bool Function(E?, E?, String) equivalentValues,
+ [String propertyName = '']) {
+ if (identical(a, b)) return true;
+ if (a == null || b == null) return false;
+ if (a.length != b.length) {
+ $registerInequivalence(
+ '\${propertyName}.length', 'Lists \${a} and \${b} are not equivalent');
+ return false;
+ }
+ for (int i = 0; i < a.length; i++) {
+ if (!equivalentValues(a[i], b[i], '\${propertyName}[\${i}]')) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /// Returns `true` if lists [a] and [b] are equivalent, using
+ /// [equivalentValues] to determine element-wise equivalence.
+ ///
+ /// Inequivalence is _not_ registered.
+ bool $matchLists<E>(
+ List<E>? a,
+ List<E>? b,
+ bool Function(E?, E?, String) equivalentValues) {
+ CheckingState oldState = $checkingState;
+ $checkingState = $checkingState.toMatchingState();
+ bool result = $checkLists(a, b, equivalentValues);
+ $checkingState = oldState;
+ return result;
+ }
+
+ /// Returns `true` if sets [a] and [b] are equivalent, using
+ /// [matchingValues] to determine which elements that should be checked for
+ /// element-wise equivalence using [equivalentValues].
+ ///
+ /// If run in a checking state, the [propertyName] is used for registering
+ /// inequivalences.
+ bool $checkSets<E>(
+ Set<E>? a,
+ Set<E>? b,
+ bool Function(E?, E?) matchingValues,
+ bool Function(E?, E?, String) equivalentValues,
+ [String propertyName = '']) {
+ if (identical(a, b)) return true;
+ if (a == null || b == null) return false;
+ if (a.length != b.length) {
+ $registerInequivalence(
+ '\${propertyName}.length', 'Sets \${a} and \${b} are not equivalent');
+ return false;
+ }
+ b = b.toSet();
+ for (E aValue in a) {
+ bool hasFoundValue = false;
+ E? foundValue;
+ for (E bValue in b) {
+ if (matchingValues(aValue, bValue)) {
+ foundValue = bValue;
+ hasFoundValue = true;
+ if (!equivalentValues(aValue, bValue,
+ '\${propertyName}[\${aValue}]')) {
+ $registerInequivalence(
+ '\${propertyName}[\${aValue}]',
+ 'Elements \${aValue} and \${bValue} are not equivalent');
+ return false;
+ }
+ break;
+ }
+ }
+ if (hasFoundValue) {
+ b.remove(foundValue);
+ } else {
+ $registerInequivalence(
+ '\${propertyName}[\${aValue}]',
+ 'Sets \${a} and \${b} are not equivalent, no equivalent value '
+ 'found for \$aValue');
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /// Returns `true` if sets [a] and [b] are equivalent, using
+ /// [matchingValues] to determine which elements that should be checked for
+ /// element-wise equivalence using [equivalentValues].
+ ///
+ /// Inequivalence is _not_registered.
+ bool $matchSets<E>(
+ Set<E>? a,
+ Set<E>? b,
+ bool Function(E?, E?) matchingValues,
+ bool Function(E?, E?, String) equivalentValues) {
+ CheckingState oldState = $checkingState;
+ $checkingState = $checkingState.toMatchingState();
+ bool result = $checkSets(a, b, matchingValues, equivalentValues);
+ $checkingState = oldState;
+ return result;
+ }
+
+ /// Returns `true` if maps [a] and [b] are equivalent, using
+ /// [matchingKeys] to determine which entries that should be checked for
+ /// entry-wise equivalence using [equivalentKeys] and [equivalentValues] to
+ /// determine key and value equivalences, respectively.
+ ///
+ /// If run in a checking state, the [propertyName] is used for registering
+ /// inequivalences.
+ bool $checkMaps<K, V>(
+ Map<K, V>? a,
+ Map<K, V>? b,
+ bool Function(K?, K?) matchingKeys,
+ bool Function(K?, K?, String) equivalentKeys,
+ bool Function(V?, V?, String) equivalentValues,
+ [String propertyName = '']) {
+ if (identical(a, b)) return true;
+ if (a == null || b == null) return false;
+ if (a.length != b.length) {
+ $registerInequivalence(
+ '\${propertyName}.length',
+ 'Maps \${a} and \${b} are not equivalent');
+ return false;
+ }
+ Set<K> bKeys = b.keys.toSet();
+ for (K aKey in a.keys) {
+ bool hasFoundKey = false;
+ K? foundKey;
+ for (K bKey in bKeys) {
+ if (matchingKeys(aKey, bKey)) {
+ foundKey = bKey;
+ hasFoundKey = true;
+ if (!equivalentKeys(aKey, bKey, '\${propertyName}[\${aKey}]')) {
+ $registerInequivalence(
+ '\${propertyName}[\${aKey}]',
+ 'Keys \${aKey} and \${bKey} are not equivalent');
+ return false;
+ }
+ break;
+ }
+ }
+ if (hasFoundKey) {
+ bKeys.remove(foundKey);
+ if (!equivalentValues(a[aKey], b[foundKey],
+ '\${propertyName}[\${aKey}]')) {
+ return false;
+ }
+ } else {
+ $registerInequivalence(
+ '\${propertyName}[\${aKey}]',
+ 'Maps \${a} and \${b} are not equivalent, no equivalent key '
+ 'found for \$aKey');
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /// Returns `true` if maps [a] and [b] are equivalent, using
+ /// [matchingKeys] to determine which entries that should be checked for
+ /// entry-wise equivalence using [equivalentKeys] and [equivalentValues] to
+ /// determine key and value equivalences, respectively.
+ ///
+ /// Inequivalence is _not_ registered.
+ bool $matchMaps<K, V>(
+ Map<K, V>? a,
+ Map<K, V>? b,
+ bool Function(K?, K?) matchingKeys,
+ bool Function(K?, K?, String) equivalentKeys,
+ bool Function(V?, V?, String) equivalentValues) {
+ CheckingState oldState = $checkingState;
+ $checkingState = $checkingState.toMatchingState();
+ bool result = $checkMaps(a, b, matchingKeys, equivalentKeys,
+ equivalentValues);
+ $checkingState = oldState;
+ return result;
+ }
+
+ /// The current state of the visitor.
+ ///
+ /// This holds the current assumptions, found inequivalences, and whether
+ /// inequivalences are currently registered.
+ CheckingState $checkingState = new CheckingState();
+
+ /// Runs [f] in a new state that holds all current assumptions. If
+ /// [isAsserting] is `true`, inequivalences are registered. Returns the
+ /// collected inequivalences.
+ ///
+ /// If [f] returns `false`, the returned result is marked as having
+ /// inequivalences even when non have being registered.
+ EquivalenceResult inSubState(bool Function() f, {bool isAsserting: false}) {
+ CheckingState _oldState = $checkingState;
+ $checkingState = $checkingState.createSubState(isAsserting: isAsserting);
+ bool hasInequivalences = f();
+ EquivalenceResult result =
+ $checkingState.toResult(hasInequivalences: hasInequivalences);
+ $checkingState = _oldState;
+ return result;
+ }
+
+ /// Registers that the visitor enters the property named [propertyName] and
+ /// the currently visited node.
+ void pushPropertyState(String propertyName) {
+ $checkingState.pushPropertyState(propertyName);
+ }
+
+ /// Registers that the visitor enters nodes [a] and [b].
+ void pushNodeState(Node a, Node b) {
+ $checkingState.pushNodeState(a, b);
+ }
+
+ /// Register that the visitor leave the current node or property.
+ void popState() {
+ $checkingState.popState();
+ }
+
+ /// Returns the value used as the result for property inequivalences.
+ ///
+ /// When inequivalences are currently registered, this is `true`, so that the
+ /// visitor will continue find inequivalences that are not directly related.
+ ///
+ /// An example is finding several child inequivalences on otherwise equivalent
+ /// nodes, like finding inequivalences deeply in the members of the second
+ /// library of a component even when inequivalences deeply in the members of
+ /// the first library. Had the return value been `false`, signaling that the
+ /// first libraries were inequivalent, which they technically are, given that
+ /// the contain inequivalent subnodes, the visitor would have stopped short in
+ /// checking the list of libraries, and the inequivalences in the second
+ /// library would not have been found.
+ ///
+ /// When inequivalences are _not_ currently registered, i.e. we are only
+ /// interested in the true/false value of the equivalence test, `false` is
+ /// used as the result value to stop the equivalence checking short.
+ bool get $resultOnInequivalence =>
+ $checkingState.$resultOnInequivalence;
+
+ /// Registers an equivalence on the [propertyName] with a detailed description
+ /// in [message].
+ void $registerInequivalence(String propertyName, String message) {
+ $checkingState.registerInequivalence(propertyName, message);
+ }
+
+ /// Returns the inequivalences found by the visitor.
+ EquivalenceResult toResult() => $checkingState.toResult();
+
+ ''');
+ } catch (e, s) {
+ print(s);
+ }
+ } catch (e, s) {
+ print(s);
+ }
+ } catch (e, s) {
+ print(s);
+ }
+ super.generateFooter(astModel, sb);
+ sb.writeln('''
+/// Checks [a] and [b] be for equivalence using [strategy].
+///
+/// Returns an [EquivalenceResult] containing the found inequivalences.
+EquivalenceResult checkEquivalence(
+ Node a,
+ Node b,
+ {$strategyName strategy: const $strategyName()}) {
+ EquivalenceVisitor visitor = new EquivalenceVisitor(
+ strategy: strategy);
+ visitor.$checkNodes(a, b, 'root');
+ return visitor.toResult();
+}
+''');
+
+ sb.writeln('''
+/// Strategy used for determining equivalence of AST nodes.
+///
+/// The strategy has a method for determining the equivalence of each AST node
+/// class, and a method for determining the equivalence of each property on each
+/// AST node class.
+///
+/// The base implementation enforces a full structural equivalence.
+///
+/// Custom strategies can be made by extending this strategy and override
+/// methods where exceptions to the structural equivalence are needed.
+class $strategyName {
+ const $strategyName();
+''');
+ _classStrategyMembers.forEach((key, value) {
+ sb.write(value);
+ });
+ _fieldStrategyMembers.forEach((key, value) {
+ sb.write(value);
+ });
+ sb.writeln(r'''
+}
+''');
+ }
+}
diff --git a/pkg/front_end/tool/smoke_test_quick.dart b/pkg/front_end/tool/smoke_test_quick.dart
index 9c60324..9e7d790 100644
--- a/pkg/front_end/tool/smoke_test_quick.dart
+++ b/pkg/front_end/tool/smoke_test_quick.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart=2.9
-
import 'dart:io' show Platform, Process, ProcessResult, exitCode;
import '../test/utils/io_utils.dart' show computeRepoDir;
diff --git a/pkg/front_end/tool/stat_on_dash_v.dart b/pkg/front_end/tool/stat_on_dash_v.dart
index c0ac7b4..7040540 100644
--- a/pkg/front_end/tool/stat_on_dash_v.dart
+++ b/pkg/front_end/tool/stat_on_dash_v.dart
@@ -2,13 +2,11 @@
// 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.
-// @dart=2.9
-
import "dart:io";
import "../test/simple_stats.dart";
-void usage([String extraMessage]) {
+void usage([String? extraMessage]) {
print("Usage:");
print("On Linux via bash you can do something like");
print("dart pkg/front_end/tool/stat_on_dash_v.dart \ "
@@ -68,12 +66,12 @@
bool printedAnything = false;
for (String part in data.keys) {
- Map<String, List<int>> partData = data[part];
- List<int> prevRuntimes;
- String prevGroup;
+ Map<String, List<int>> partData = data[part]!;
+ List<int>? prevRuntimes;
+ String? prevGroup;
bool printed = false;
for (String group in allGroups) {
- List<int> runtimes = partData[group];
+ List<int>? runtimes = partData[group];
if (runtimes == null) {
// Fake it to be a small list of 0s.
runtimes = new List<int>.filled(5, 0);
@@ -101,7 +99,8 @@
leastConfidentChange = result.diff - result.confidence;
}
- combinedChange["$prevGroup => $group"] += leastConfidentChange;
+ combinedChange["$prevGroup => $group"] =
+ combinedChange["$prevGroup => $group"]! + leastConfidentChange;
}
}
prevRuntimes = runtimes;
@@ -115,7 +114,7 @@
if (printedAnything) {
for (String part in combinedChange.keys) {
print("Combined least change for $part: "
- "${combinedChange[part].toStringAsFixed(2)} ms.");
+ "${combinedChange[part]!.toStringAsFixed(2)} ms.");
}
} else {
print("Nothing significant found.");
diff --git a/pkg/front_end/tool/update_all.dart b/pkg/front_end/tool/update_all.dart
index c25162c..3f9bfd1 100644
--- a/pkg/front_end/tool/update_all.dart
+++ b/pkg/front_end/tool/update_all.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart=2.9
-
import 'package:_fe_analyzer_shared/src/testing/id_testing.dart' as id;
import 'update_expectations.dart' as expectations;
diff --git a/pkg/front_end/tool/update_expectations.dart b/pkg/front_end/tool/update_expectations.dart
index 4ea0272..bd97672 100644
--- a/pkg/front_end/tool/update_expectations.dart
+++ b/pkg/front_end/tool/update_expectations.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart=2.9
-
import 'fasta.dart' as fasta;
const List<String> standardSuites = <String>[
@@ -19,7 +17,7 @@
'incremental',
];
-Future<void> runStandardSuites([List<String> args]) async {
+Future<void> runStandardSuites([List<String>? args]) async {
// Assert that 'strong' is the first suite - we use the assumption below.
assert(standardSuites.first == 'weak', "Suite 'weak' most be the first.");
bool first = true;
diff --git a/pkg/front_end/tool/visitor_generator.dart b/pkg/front_end/tool/visitor_generator.dart
new file mode 100644
index 0000000..ff3bace
--- /dev/null
+++ b/pkg/front_end/tool/visitor_generator.dart
@@ -0,0 +1,304 @@
+// 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.
+
+// @dart = 2.9
+
+import 'package:dart_style/dart_style.dart' show DartFormatter;
+
+import 'ast_model.dart';
+
+/// Generates a visitor library into [sb] based on [astModel] and [strategy].
+String generateVisitor(AstModel astModel, VisitorStrategy strategy) {
+ StringBuffer sb = new StringBuffer();
+ strategy.generateHeader(astModel, sb);
+
+ void addVisitNode(AstClass astClass) {
+ switch (astClass.kind) {
+ case AstClassKind.root:
+ case AstClassKind.inner:
+ if (astClass.hasVisitMethod) {
+ strategy.generateDefaultVisit(astClass, sb);
+ }
+ for (AstClass subclass in astClass.subclasses) {
+ addVisitNode(subclass);
+ }
+ break;
+ case AstClassKind.public:
+ case AstClassKind.named:
+ case AstClassKind.declarative:
+ if (astClass.hasVisitMethod) {
+ strategy.generateVisit(astClass, sb);
+ }
+ break;
+ case AstClassKind.implementation:
+ case AstClassKind.interface:
+ case AstClassKind.utilityAsStructure:
+ case AstClassKind.utilityAsValue:
+ break;
+ }
+ }
+
+ void addVisitReference(AstClass astClass) {
+ switch (astClass.kind) {
+ case AstClassKind.root:
+ case AstClassKind.inner:
+ if (astClass.hasVisitReferenceMethod) {
+ strategy.generateDefaultVisitReference(astClass, sb);
+ }
+ for (AstClass subclass in astClass.subclasses) {
+ addVisitReference(subclass);
+ }
+ break;
+ case AstClassKind.public:
+ case AstClassKind.named:
+ case AstClassKind.declarative:
+ if (astClass.hasVisitReferenceMethod) {
+ strategy.generateVisitReference(astClass, sb);
+ }
+ break;
+ case AstClassKind.implementation:
+ case AstClassKind.interface:
+ case AstClassKind.utilityAsStructure:
+ case AstClassKind.utilityAsValue:
+ break;
+ }
+ }
+
+ addVisitNode(astModel.nodeClass);
+ addVisitReference(astModel.namedNodeClass);
+ addVisitReference(astModel.constantClass);
+ strategy.generateFooter(astModel, sb);
+
+ String result = sb.toString();
+ result = new DartFormatter().format(result);
+ return result;
+}
+
+/// Strategy for generating a visitor in its own library based on an [AstModel].
+abstract class VisitorStrategy {
+ const VisitorStrategy();
+
+ /// Generates the header of the visitor library, including preamble, imports
+ /// and visitor class declaration start.
+ void generateHeader(AstModel astModel, StringBuffer sb);
+
+ /// Generates a `defaultX` visitor method for [astClass].
+ void generateDefaultVisit(AstClass astClass, StringBuffer sb);
+
+ /// Generates a `visitX` visitor method for [astClass].
+ void generateVisit(AstClass astClass, StringBuffer sb);
+
+ /// Generates a `defaultXReference` visitor method for [astClass].
+ void generateDefaultVisitReference(AstClass astClass, StringBuffer sb);
+
+ /// Generates a `visitXReference` visitor method for [astClass].
+ void generateVisitReference(AstClass astClass, StringBuffer sb);
+
+ /// Generates the footer of the visitor library, including the visitor class
+ /// declaration end.
+ void generateFooter(AstModel astModel, StringBuffer sb);
+}
+
+/// Base strategy for creating a [Visitor] implementation.
+abstract class Visitor0Strategy extends VisitorStrategy {
+ const Visitor0Strategy();
+
+ /// The name of the generated visitor class.
+ String get visitorName;
+
+ /// The type parameters of the generated visitor class.
+ String get visitorTypeParameters => '';
+
+ /// The return type for the visitor methods.
+ ///
+ /// The generated visitor will implement `Visitor<$returnType>`.
+ String get returnType;
+
+ void generateHeader(AstModel astModel, StringBuffer sb) {
+ sb.writeln('''
+import 'package:kernel/ast.dart';
+
+class $visitorName$visitorTypeParameters implements Visitor<$returnType> {''');
+ }
+
+ void generateFooter(AstModel astModel, StringBuffer sb) {
+ sb.writeln('''
+}''');
+ }
+
+ @override
+ void generateDefaultVisit(AstClass astClass, StringBuffer sb) {
+ sb.writeln('''
+ @override
+ ${returnType} default${astClass.name}(
+ ${astClass.name} node) {''');
+ handleDefaultVisit(astClass, sb);
+ sb.writeln('}');
+ }
+
+ /// Generates the body of a `defaultX` visitor method of [astClass].
+ void handleDefaultVisit(AstClass astClass, StringBuffer sb) {}
+
+ @override
+ void generateVisit(AstClass astClass, StringBuffer sb) {
+ sb.writeln('''
+ @override
+ ${returnType} visit${astClass.name}(
+ ${astClass.name} node) {''');
+ handleVisit(astClass, sb);
+ sb.writeln('}');
+ }
+
+ /// Generates the body of a `visitX` visitor method of [astClass].
+ void handleVisit(AstClass astClass, StringBuffer sb) {}
+
+ @override
+ void generateDefaultVisitReference(AstClass astClass, StringBuffer sb) {
+ sb.writeln(''''
+ @override
+ ${returnType} default${astClass.name}Reference(
+ '${astClass.name} node) {''');
+ handleDefaultVisitReference(astClass, sb);
+ sb.writeln('}');
+ }
+
+ /// Generates the body of a `defaultXReference` visitor method of [astClass].
+ void handleDefaultVisitReference(AstClass astClass, StringBuffer sb) {}
+
+ @override
+ void generateVisitReference(AstClass astClass, StringBuffer sb) {
+ sb.writeln('''
+ @override
+ ${returnType} visit${astClass.name}Reference(
+ ${astClass.name} node) {''');
+ handleVisitReference(astClass, sb);
+ sb.writeln('}');
+ }
+
+ /// Generates the body of a `visitXReference` visitor method of [astClass].
+ void handleVisitReference(AstClass astClass, StringBuffer sb) {}
+}
+
+/// Strategy for creating an empty `Visitor<void>` implementation.
+class VoidVisitor0Strategy extends Visitor0Strategy {
+ const VoidVisitor0Strategy();
+
+ @override
+ String get visitorName => 'VoidVisitor';
+
+ @override
+ String get returnType => 'void';
+}
+
+/// Base strategy for creating a [Visitor1] implementation.
+abstract class Visitor1Strategy extends VisitorStrategy {
+ const Visitor1Strategy();
+
+ /// The name of the generated visitor class.
+ String get visitorName;
+
+ /// The type parameters of the generated visitor class.
+ String get visitorTypeParameters => '';
+
+ /// The type of the argument of the visitor methods.
+ ///
+ /// The generated visitor will implement
+ /// `Visitor1<$returnType, $argumentType>`.
+ String get argumentType;
+
+ /// The name of the argument parameter name.
+ String get argumentName => 'arg';
+
+ /// The return type for the visitor methods.
+ ///
+ /// The generated visitor will implement
+ /// `Visitor1<$returnType, $argumentType>`.
+ String get returnType;
+
+ void generateHeader(AstModel astModel, StringBuffer sb) {
+ sb.writeln('''
+import 'package:kernel/ast.dart';
+
+class $visitorName$visitorTypeParameters
+ implements Visitor1<$returnType, $argumentType> {''');
+ }
+
+ void generateFooter(AstModel astModel, StringBuffer sb) {
+ sb.writeln('''
+}''');
+ }
+
+ @override
+ void generateDefaultVisit(AstClass astClass, StringBuffer sb) {
+ sb.writeln('''
+ @override
+ ${returnType} default${astClass.name}(
+ ${astClass.name} node, $argumentType $argumentName) {''');
+ handleDefaultVisit(astClass, sb);
+ sb.writeln('''
+ }''');
+ }
+
+ /// Generates the body of a `defaultX` visitor method of [astClass].
+ void handleDefaultVisit(AstClass astClass, StringBuffer sb) {}
+
+ @override
+ void generateVisit(AstClass astClass, StringBuffer sb) {
+ sb.writeln('''
+ @override
+ ${returnType} visit${astClass.name}(
+ ${astClass.name} node, $argumentType $argumentName) {''');
+ handleVisit(astClass, sb);
+ sb.writeln('''
+ }''');
+ }
+
+ /// Generates the body of a `visitX` visitor method of [astClass].
+ void handleVisit(AstClass astClass, StringBuffer sb) {}
+
+ @override
+ void generateDefaultVisitReference(AstClass astClass, StringBuffer sb) {
+ sb.writeln('''
+ @override
+ ${returnType} default${astClass.name}Reference(
+ ${astClass.name} node, $argumentType $argumentName) {''');
+ handleDefaultVisitReference(astClass, sb);
+ sb.writeln('''
+ }''');
+ }
+
+ /// Generates the body of a `defaultXReference` visitor method of [astClass].
+ void handleDefaultVisitReference(AstClass astClass, StringBuffer sb) {}
+
+ @override
+ void generateVisitReference(AstClass astClass, StringBuffer sb) {
+ sb.writeln('''
+ @override
+ ${returnType} visit${astClass.name}Reference(
+ ${astClass.name} node, $argumentType $argumentName) {''');
+ handleVisitReference(astClass, sb);
+ sb.writeln('''
+ }''');
+ }
+
+ /// Generates the body of a `visitXReference` visitor method of [astClass].
+ void handleVisitReference(AstClass astClass, StringBuffer sb) {}
+}
+
+/// Strategy for creating an empty `Visitor1<void,Null>` implementation.
+class VoidVisitor1Strategy extends Visitor1Strategy {
+ const VoidVisitor1Strategy();
+
+ @override
+ String get visitorName => 'VoidVisitor';
+
+ @override
+ String get returnType => 'void';
+
+ @override
+ String get argumentType => 'Null';
+
+ @override
+ String get argumentName => '_';
+}
diff --git a/pkg/kernel/binary.md b/pkg/kernel/binary.md
index 4dd9aa7..e013be5 100644
--- a/pkg/kernel/binary.md
+++ b/pkg/kernel/binary.md
@@ -147,7 +147,7 @@
type ComponentFile {
UInt32 magic = 0x90ABCDEF;
- UInt32 formatVersion = 67;
+ UInt32 formatVersion = 69;
Byte[10] shortSdkHash;
List<String> problemsAsJson; // Described in problems.md.
Library[] libraries;
@@ -328,7 +328,7 @@
List<Field> fields;
List<Constructor> constructors;
List<Procedure> procedures;
- List<RedirectingFactoryConstructor> redirectingFactoryConstructors;
+ List<RedirectingFactory> redirectingFactories;
// Class index. Offsets are used to get start (inclusive) and end (exclusive) byte positions for
// a specific procedure. Note the "+1" to account for needing the end of the last entry.
@@ -424,7 +424,7 @@
Byte kind; // Index into the ProcedureKind enum above.
Byte stubKind; // Index into the ProcedureStubKind enum above.
UInt flags (isStatic, isAbstract, isExternal, isConst,
- isRedirectingFactoryConstructor, isExtensionMember,
+ isRedirectingFactory, isExtensionMember,
isNonNullableByDefault);
Name name;
List<Expression> annotations;
@@ -432,7 +432,7 @@
FunctionNode function;
}
-type RedirectingFactoryConstructor extends Member {
+type RedirectingFactory extends Member {
Byte tag = 108;
CanonicalNameReference canonicalName;
UriReference fileUri;
@@ -584,25 +584,6 @@
// Equivalent to VariableSet with index N.
}
-type PropertyGet extends Expression {
- Byte tag = 22;
- FileOffset fileOffset;
- Expression receiver;
- Name name;
- MemberReference interfaceTarget; // May be NullReference.
- MemberReference interfaceTargetOrigin; // May be NullReference.
-}
-
-type PropertySet extends Expression {
- Byte tag = 23;
- FileOffset fileOffset;
- Expression receiver;
- Name name;
- Expression value;
- MemberReference interfaceTarget; // May be NullReference.
- MemberReference interfaceTargetOrigin; // May be NullReference.
-}
-
type SuperPropertyGet extends Expression {
Byte tag = 24;
FileOffset fileOffset;
@@ -703,8 +684,13 @@
type ConstructorTearOff extends Expression {
Byte tag = 60;
FileOffset fileOffset;
- ConstructorReference constructor;
- Option<List<DartType>> typeArguments;
+ MemberReference target;
+}
+
+type RedirectingFactoryTearOff extends Expression {
+ Byte tag = 84;
+ FileOffset fileOffset;
+ MemberReference target;
}
type TypedefTearOff extends Expression {
@@ -735,17 +721,6 @@
Expression value;
}
-type MethodInvocation extends Expression {
- Byte tag = 28;
- Byte flags (isInvariant, isBoundsSafe);
- FileOffset fileOffset;
- Expression receiver;
- Name name;
- Arguments arguments;
- MemberReference interfaceTarget; // May be NullReference.
- MemberReference interfaceTargetOrigin; // May be NullReference.
-}
-
type InstanceInvocation extends Expression {
Byte tag = 120;
Byte kind; // Index into InstanceAccessKind above.
@@ -1219,6 +1194,11 @@
CanonicalNameReference constructorReference;
}
+type RedirectingFactoryTearOffConstant extends Constant {
+ Byte tag = 16;
+ CanonicalNameReference constructorReference;
+}
+
abstract type Statement extends Node {}
type ExpressionStatement extends Statement {
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index 4c7f24f..69df63a 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -92,6 +92,7 @@
const Node();
R accept<R>(Visitor<R> v);
+ R accept1<R, A>(Visitor1<R, A> v, A arg);
void visitChildren(Visitor v);
/// Returns the textual representation of this node for use in debugging.
@@ -1190,19 +1191,18 @@
_proceduresView = null;
}
- List<RedirectingFactoryConstructor> _redirectingFactoryConstructorsInternal;
- DirtifyingList<RedirectingFactoryConstructor>?
- _redirectingFactoryConstructorsView;
+ List<RedirectingFactory> _redirectingFactoriesInternal;
+ DirtifyingList<RedirectingFactory>? _redirectingFactoriesView;
/// Redirecting factory constructors declared in the class.
///
/// For mixin applications this should be empty.
- List<RedirectingFactoryConstructor> get redirectingFactoryConstructors {
+ List<RedirectingFactory> get redirectingFactories {
ensureLoaded();
// If already dirty the caller just might as well add stuff directly too.
- if (dirty) return _redirectingFactoryConstructorsInternal;
- return _redirectingFactoryConstructorsView ??=
- new DirtifyingList(this, _redirectingFactoryConstructorsInternal);
+ if (dirty) return _redirectingFactoriesInternal;
+ return _redirectingFactoriesView ??=
+ new DirtifyingList(this, _redirectingFactoriesInternal);
}
/// Internal. Should *ONLY* be used from within kernel.
@@ -1210,9 +1210,9 @@
/// Used for adding redirecting factory constructor when reading the dill
/// file.
void set redirectingFactoryConstructorsInternal(
- List<RedirectingFactoryConstructor> redirectingFactoryConstructors) {
- _redirectingFactoryConstructorsInternal = redirectingFactoryConstructors;
- _redirectingFactoryConstructorsView = null;
+ List<RedirectingFactory> redirectingFactoryConstructors) {
+ _redirectingFactoriesInternal = redirectingFactoryConstructors;
+ _redirectingFactoriesView = null;
}
Class(
@@ -1226,7 +1226,7 @@
List<Constructor>? constructors,
List<Procedure>? procedures,
List<Field>? fields,
- List<RedirectingFactoryConstructor>? redirectingFactoryConstructors,
+ List<RedirectingFactory>? redirectingFactoryConstructors,
required this.fileUri,
Reference? reference})
// ignore: unnecessary_null_comparison
@@ -1238,14 +1238,14 @@
this._fieldsInternal = fields ?? <Field>[],
this._constructorsInternal = constructors ?? <Constructor>[],
this._proceduresInternal = procedures ?? <Procedure>[],
- this._redirectingFactoryConstructorsInternal =
- redirectingFactoryConstructors ?? <RedirectingFactoryConstructor>[],
+ this._redirectingFactoriesInternal =
+ redirectingFactoryConstructors ?? <RedirectingFactory>[],
super(reference) {
setParents(this.typeParameters, this);
setParents(this._constructorsInternal, this);
setParents(this._proceduresInternal, this);
setParents(this._fieldsInternal, this);
- setParents(this._redirectingFactoryConstructorsInternal, this);
+ setParents(this._redirectingFactoriesInternal, this);
this.isAbstract = isAbstract;
this.isAnonymousMixin = isAnonymousMixin;
}
@@ -1270,10 +1270,10 @@
Constructor member = constructors[i];
canonicalName.getChildFromConstructor(member).bindTo(member.reference);
}
- for (int i = 0; i < redirectingFactoryConstructors.length; ++i) {
- RedirectingFactoryConstructor member = redirectingFactoryConstructors[i];
+ for (int i = 0; i < redirectingFactories.length; ++i) {
+ RedirectingFactory member = redirectingFactories[i];
canonicalName
- .getChildFromRedirectingFactoryConstructor(member)
+ .getChildFromRedirectingFactory(member)
.bindTo(member.reference);
}
dirty = false;
@@ -1300,8 +1300,8 @@
Constructor member = constructors[i];
member._relinkNode();
}
- for (int i = 0; i < redirectingFactoryConstructors.length; ++i) {
- RedirectingFactoryConstructor member = redirectingFactoryConstructors[i];
+ for (int i = 0; i < redirectingFactories.length; ++i) {
+ RedirectingFactory member = redirectingFactories[i];
member._relinkNode();
}
dirty = false;
@@ -1345,7 +1345,7 @@
fields,
constructors,
procedures,
- redirectingFactoryConstructors
+ redirectingFactories
].expand((x) => x);
/// The immediately extended, mixed-in, and implemented types.
@@ -1389,11 +1389,10 @@
}
/// Adds a field to this class.
- void addRedirectingFactoryConstructor(
- RedirectingFactoryConstructor redirectingFactoryConstructor) {
+ void addRedirectingFactory(RedirectingFactory redirectingFactory) {
dirty = true;
- redirectingFactoryConstructor.parent = this;
- _redirectingFactoryConstructorsInternal.add(redirectingFactoryConstructor);
+ redirectingFactory.parent = this;
+ _redirectingFactoriesInternal.add(redirectingFactory);
}
@override
@@ -1446,7 +1445,7 @@
visitList(constructors, v);
visitList(procedures, v);
visitList(fields, v);
- visitList(redirectingFactoryConstructors, v);
+ visitList(redirectingFactories, v);
}
@override
@@ -1463,7 +1462,7 @@
v.transformList(constructors, this);
v.transformList(procedures, this);
v.transformList(fields, this);
- v.transformList(redirectingFactoryConstructors, this);
+ v.transformList(redirectingFactories, this);
}
@override
@@ -1490,8 +1489,7 @@
v.transformConstructorList(constructors, this);
v.transformProcedureList(procedures, this);
v.transformFieldList(fields, this);
- v.transformRedirectingFactoryConstructorList(
- redirectingFactoryConstructors, this);
+ v.transformRedirectingFactoryList(redirectingFactories, this);
}
@override
@@ -2237,64 +2235,45 @@
/// be removed from the class. However, it is needed during the linking phase,
/// because other modules can refer to that constructor.
///
-/// [RedirectingFactoryConstructor]s contain the necessary information for
+/// [RedirectingFactory]s contain the necessary information for
/// linking and are treated as non-runnable members of classes that merely serve
/// as containers for that information.
///
/// Redirecting factory constructors can be unnamed. In this case, the name is
/// an empty string (in a [Name]).
-class RedirectingFactoryConstructor extends Member {
+class RedirectingFactory extends Member {
int flags = 0;
- /// [RedirectingFactoryConstructor]s may redirect to constructors or factories
+ /// [RedirectingFactory]s may redirect to constructors or factories
/// of instantiated generic types, that is, generic types with supplied type
/// arguments. The supplied type arguments are stored in this field.
final List<DartType> typeArguments;
/// Reference to the constructor or the factory that this
- /// [RedirectingFactoryConstructor] redirects to.
+ /// [RedirectingFactory] redirects to.
// TODO(johnniwinther): Make this non-nullable.
Reference? targetReference;
- /// [typeParameters] are duplicates of the type parameters of the enclosing
- /// class. Because [RedirectingFactoryConstructor]s aren't instance members,
- /// references to the type parameters of the enclosing class in the
- /// redirection target description are encoded with references to the elements
- /// of [typeParameters].
- List<TypeParameter> typeParameters;
+ /// [FunctionNode] that holds the type parameters, copied from the enclosing
+ /// class, and the parameters defined on the redirecting factory.
+ ///
+ /// The `FunctionNode.body` is `null` or a synthesized [ConstructorInvocation]
+ /// of the [targetReference] constructor using the [typeArguments] and
+ /// [VariableGet] of the parameters.
+ FunctionNode function;
- /// Positional parameters of [RedirectingFactoryConstructor]s should be
- /// compatible with that of the target constructor.
- List<VariableDeclaration> positionalParameters;
- int requiredParameterCount;
-
- /// Named parameters of [RedirectingFactoryConstructor]s should be compatible
- /// with that of the target constructor.
- List<VariableDeclaration> namedParameters;
-
- RedirectingFactoryConstructor(this.targetReference,
+ RedirectingFactory(this.targetReference,
{required Name name,
bool isConst: false,
bool isExternal: false,
int transformerFlags: 0,
List<DartType>? typeArguments,
- List<TypeParameter>? typeParameters,
- List<VariableDeclaration>? positionalParameters,
- List<VariableDeclaration>? namedParameters,
- int? requiredParameterCount,
+ required this.function,
required Uri fileUri,
Reference? reference})
: this.typeArguments = typeArguments ?? <DartType>[],
- this.typeParameters = typeParameters ?? <TypeParameter>[],
- this.positionalParameters =
- positionalParameters ?? <VariableDeclaration>[],
- this.namedParameters = namedParameters ?? <VariableDeclaration>[],
- this.requiredParameterCount =
- requiredParameterCount ?? positionalParameters?.length ?? 0,
super(name, fileUri, reference) {
- setParents(this.typeParameters, this);
- setParents(this.positionalParameters, this);
- setParents(this.namedParameters, this);
+ function.parent = this;
this.isConst = isConst;
this.isExternal = isExternal;
this.transformerFlags = transformerFlags;
@@ -2355,15 +2334,15 @@
}
@override
- R accept<R>(MemberVisitor<R> v) => v.visitRedirectingFactoryConstructor(this);
+ R accept<R>(MemberVisitor<R> v) => v.visitRedirectingFactory(this);
@override
R accept1<R, A>(MemberVisitor1<R, A> v, A arg) =>
- v.visitRedirectingFactoryConstructor(this, arg);
+ v.visitRedirectingFactory(this, arg);
@override
R acceptReference<R>(MemberReferenceVisitor<R> v) =>
- v.visitRedirectingFactoryConstructorReference(this);
+ v.visitRedirectingFactoryReference(this);
@override
void visitChildren(Visitor v) {
@@ -2371,18 +2350,21 @@
target?.acceptReference(v);
visitList(typeArguments, v);
name.accept(v);
+ function.accept(v);
}
@override
void transformChildren(Transformer v) {
v.transformList(annotations, this);
v.transformDartTypeList(typeArguments);
+ function = v.transform(function)..parent = this;
}
@override
void transformOrRemoveChildren(RemovingTransformer v) {
v.transformExpressionList(annotations, this);
v.transformDartTypeList(typeArguments);
+ function = v.transform(function)..parent = this;
}
@override
@@ -2705,7 +2687,7 @@
static const int FlagExternal = 1 << 2;
static const int FlagConst = 1 << 3; // Only for external const factories.
// TODO(29841): Remove this flag after the issue is resolved.
- static const int FlagRedirectingFactoryConstructor = 1 << 4;
+ static const int FlagRedirectingFactory = 1 << 4;
static const int FlagExtensionMember = 1 << 5;
static const int FlagNonNullableByDefault = 1 << 6;
static const int FlagSynthetic = 1 << 7;
@@ -2750,8 +2732,8 @@
// Indicates if this [Procedure] represents a redirecting factory constructor
// and doesn't have a runnable body.
- bool get isRedirectingFactoryConstructor {
- return flags & FlagRedirectingFactoryConstructor != 0;
+ bool get isRedirectingFactory {
+ return flags & FlagRedirectingFactory != 0;
}
/// If set, this flag indicates that this function was not present in the
@@ -2783,10 +2765,10 @@
flags = value ? (flags | FlagConst) : (flags & ~FlagConst);
}
- void set isRedirectingFactoryConstructor(bool value) {
+ void set isRedirectingFactory(bool value) {
flags = value
- ? (flags | FlagRedirectingFactoryConstructor)
- : (flags & ~FlagRedirectingFactoryConstructor);
+ ? (flags | FlagRedirectingFactory)
+ : (flags & ~FlagRedirectingFactory);
}
void set isExtensionMember(bool value) {
@@ -3101,7 +3083,12 @@
@override
void toTextInternal(AstPrinter printer) {
- // TODO(johnniwinther): Implement this.
+ printer.write('super');
+ if (target.name.text.isNotEmpty) {
+ printer.write('.');
+ printer.write(target.name.text);
+ }
+ printer.writeArguments(arguments, includeTypeArguments: false);
}
}
@@ -3405,6 +3392,14 @@
/// resulting function type is generic, a fresh set of type parameters is used
/// in it.
FunctionType computeFunctionType(Nullability nullability) {
+ TreeNode? parent = this.parent;
+ List<TypeParameter> typeParameters;
+ if (parent is Constructor) {
+ assert(this.typeParameters.isEmpty);
+ typeParameters = parent.enclosingClass.typeParameters;
+ } else {
+ typeParameters = this.typeParameters;
+ }
return typeParameters.isEmpty
? computeThisFunctionType(nullability)
: getFreshTypeParameters(typeParameters)
@@ -4233,96 +4228,6 @@
}
}
-/// Expression of form `x.field`.
-///
-/// This may invoke a getter, read a field, or tear off a method.
-class PropertyGet extends Expression {
- Expression receiver;
- Name name;
-
- Reference? interfaceTargetReference;
-
- PropertyGet(Expression receiver, Name name, [Member? interfaceTarget])
- : this.byReference(
- receiver, name, getMemberReferenceGetter(interfaceTarget));
-
- PropertyGet.byReference(
- this.receiver, this.name, this.interfaceTargetReference) {
- receiver.parent = this;
- }
-
- Member? get interfaceTarget => interfaceTargetReference?.asMember;
-
- void set interfaceTarget(Member? member) {
- interfaceTargetReference = getMemberReferenceGetter(member);
- }
-
- @override
- DartType getStaticTypeInternal(StaticTypeContext context) {
- Member? interfaceTarget = this.interfaceTarget;
- if (interfaceTarget != null) {
- Class superclass = interfaceTarget.enclosingClass!;
- InterfaceType receiverType =
- receiver.getStaticTypeAsInstanceOf(superclass, context);
- return Substitution.fromInterfaceType(receiverType)
- .substituteType(interfaceTarget.getterType);
- }
- // Treat the properties of Object specially.
- String nameString = name.text;
- if (nameString == 'hashCode') {
- return context.typeEnvironment.coreTypes.intRawType(context.nonNullable);
- } else if (nameString == 'runtimeType') {
- return context.typeEnvironment.coreTypes.typeRawType(context.nonNullable);
- }
- return const DynamicType();
- }
-
- @override
- R accept<R>(ExpressionVisitor<R> v) => v.visitPropertyGet(this);
-
- @override
- R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
- v.visitPropertyGet(this, arg);
-
- @override
- void visitChildren(Visitor v) {
- receiver.accept(v);
- interfaceTarget?.acceptReference(v);
- name.accept(v);
- }
-
- @override
- void transformChildren(Transformer v) {
- // ignore: unnecessary_null_comparison
- if (receiver != null) {
- receiver = v.transform(receiver);
- receiver.parent = this;
- }
- }
-
- @override
- void transformOrRemoveChildren(RemovingTransformer v) {
- // ignore: unnecessary_null_comparison
- if (receiver != null) {
- receiver = v.transform(receiver);
- receiver.parent = this;
- }
- }
-
- @override
- String toString() {
- return "PropertyGet(${toStringInternal()})";
- }
-
- @override
- void toTextInternal(AstPrinter printer) {
- printer.writeExpression(receiver,
- minimumPrecedence: astToText.Precedence.PRIMARY);
- printer.write('.');
- printer.writeInterfaceMemberName(interfaceTargetReference, name);
- }
-}
-
class DynamicSet extends Expression {
final DynamicAccessKind kind;
Expression receiver;
@@ -4490,98 +4395,6 @@
}
}
-/// Expression of form `x.field = value`.
-///
-/// This may invoke a setter or assign a field.
-///
-/// Evaluates to the value of [value].
-class PropertySet extends Expression {
- Expression receiver;
- Name name;
- Expression value;
-
- Reference? interfaceTargetReference;
-
- PropertySet(Expression receiver, Name name, Expression value,
- [Member? interfaceTarget])
- : this.byReference(
- receiver, name, value, getMemberReferenceSetter(interfaceTarget));
-
- PropertySet.byReference(
- this.receiver, this.name, this.value, this.interfaceTargetReference) {
- receiver.parent = this;
- value.parent = this;
- }
-
- Member? get interfaceTarget => interfaceTargetReference?.asMember;
-
- void set interfaceTarget(Member? member) {
- interfaceTargetReference = getMemberReferenceSetter(member);
- }
-
- @override
- DartType getStaticTypeInternal(StaticTypeContext context) =>
- value.getStaticType(context);
-
- @override
- R accept<R>(ExpressionVisitor<R> v) => v.visitPropertySet(this);
-
- @override
- R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
- v.visitPropertySet(this, arg);
-
- @override
- void visitChildren(Visitor v) {
- receiver.accept(v);
- interfaceTarget?.acceptReference(v);
- name.accept(v);
- value.accept(v);
- }
-
- @override
- void transformChildren(Transformer v) {
- // ignore: unnecessary_null_comparison
- if (receiver != null) {
- receiver = v.transform(receiver);
- receiver.parent = this;
- }
- // ignore: unnecessary_null_comparison
- if (value != null) {
- value = v.transform(value);
- value.parent = this;
- }
- }
-
- @override
- void transformOrRemoveChildren(RemovingTransformer v) {
- // ignore: unnecessary_null_comparison
- if (receiver != null) {
- receiver = v.transform(receiver);
- receiver.parent = this;
- }
- // ignore: unnecessary_null_comparison
- if (value != null) {
- value = v.transform(value);
- value.parent = this;
- }
- }
-
- @override
- String toString() {
- return "PropertySet(${toStringInternal()})";
- }
-
- @override
- void toTextInternal(AstPrinter printer) {
- printer.writeExpression(receiver,
- minimumPrecedence: astToText.Precedence.PRIMARY);
- printer.write('.');
- printer.writeInterfaceMemberName(interfaceTargetReference, name);
- printer.write(' = ');
- printer.writeExpression(value);
- }
-}
-
/// Expression of form `super.field`.
///
/// This may invoke a getter, read a field, or tear off a method.
@@ -5954,210 +5767,6 @@
}
}
-/// Expression of form `x.foo(y)`.
-class MethodInvocation extends InstanceInvocationExpression {
- // Must match serialized bit positions.
- static const int FlagInvariant = 1 << 0;
- static const int FlagBoundsSafe = 1 << 1;
-
- @override
- Expression receiver;
-
- @override
- Name name;
-
- @override
- Arguments arguments;
-
- int flags = 0;
-
- Reference? interfaceTargetReference;
-
- MethodInvocation(Expression receiver, Name name, Arguments arguments,
- [Member? interfaceTarget])
- : this.byReference(
- receiver,
- name,
- arguments,
- // An invocation doesn't refer to the setter.
- getMemberReferenceGetter(interfaceTarget));
-
- MethodInvocation.byReference(
- this.receiver, this.name, this.arguments, this.interfaceTargetReference) {
- receiver.parent = this;
- arguments.parent = this;
- }
-
- Member? get interfaceTarget => interfaceTargetReference?.asMember;
-
- void set interfaceTarget(Member? target) {
- // An invocation doesn't refer to the setter.
- interfaceTargetReference = getMemberReferenceGetter(target);
- }
-
- /// If `true`, this call is known to be safe wrt. parameter covariance checks.
- ///
- /// This is for instance the case in code patterns like this
- ///
- /// List<int> list = <int>[];
- /// list.add(0);
- ///
- /// where the `list` variable is known to hold a value of the same type as
- /// the static type. In contrast the would not be the case in code patterns
- /// like this
- ///
- /// List<num> list = <double>[];
- /// list.add(0); // Runtime error `int` is not a subtype of `double`.
- ///
- bool get isInvariant => flags & FlagInvariant != 0;
-
- void set isInvariant(bool value) {
- flags = value ? (flags | FlagInvariant) : (flags & ~FlagInvariant);
- }
-
- /// If `true`, this call is known to be safe wrt. parameter covariance checks.
- ///
- /// This is for instance the case in code patterns like this
- ///
- /// List list = new List.filled(2, 0);
- /// list[1] = 42;
- ///
- /// where the `list` is known to have a sufficient length for the update
- /// in `list[1] = 42`.
- bool get isBoundsSafe => flags & FlagBoundsSafe != 0;
-
- void set isBoundsSafe(bool value) {
- flags = value ? (flags | FlagBoundsSafe) : (flags & ~FlagBoundsSafe);
- }
-
- @override
- DartType getStaticTypeInternal(StaticTypeContext context) {
- Member? interfaceTarget = this.interfaceTarget;
- if (interfaceTarget != null) {
- if (interfaceTarget is Procedure &&
- context.typeEnvironment
- .isSpecialCasedBinaryOperator(interfaceTarget)) {
- return context.typeEnvironment.getTypeOfSpecialCasedBinaryOperator(
- receiver.getStaticType(context),
- arguments.positional[0].getStaticType(context));
- }
- Class superclass = interfaceTarget.enclosingClass!;
- InterfaceType receiverType =
- receiver.getStaticTypeAsInstanceOf(superclass, context);
- DartType getterType = Substitution.fromInterfaceType(receiverType)
- .substituteType(interfaceTarget.getterType);
- if (getterType is FunctionType) {
- Substitution substitution;
- if (getterType.typeParameters.length == arguments.types.length) {
- substitution = Substitution.fromPairs(
- getterType.typeParameters, arguments.types);
- } else {
- // TODO(johnniwinther): The front end should normalize the type
- // argument count or create an invalid expression in case of method
- // invocations with invalid type argument count.
- substitution = Substitution.fromPairs(
- getterType.typeParameters,
- getterType.typeParameters
- .map((TypeParameter typeParameter) =>
- typeParameter.defaultType)
- .toList());
- }
- return substitution.substituteType(getterType.returnType);
- }
- // The front end currently do not replace a property call `o.foo()`, where
- // `foo` is a field or getter, with a function call on the property,
- // `o.foo.call()`, so we look up the call method explicitly here.
- // TODO(johnniwinther): Remove this when the front end performs the
- // correct replacement.
- if (getterType is InterfaceType) {
- Member? member = context.typeEnvironment
- .getInterfaceMember(getterType.classNode, new Name('call'));
- if (member != null) {
- DartType callType = member.getterType;
- if (callType is FunctionType) {
- return Substitution.fromInterfaceType(getterType)
- .substituteType(callType.returnType);
- }
- }
- }
- return const DynamicType();
- }
- if (name.text == 'call') {
- DartType receiverType = receiver.getStaticType(context);
- if (receiverType is FunctionType) {
- if (receiverType.typeParameters.length != arguments.types.length) {
- return const NeverType.nonNullable();
- }
- return Substitution.fromPairs(
- receiverType.typeParameters, arguments.types)
- .substituteType(receiverType.returnType);
- }
- }
- if (name.text == '==') {
- // We use this special case to simplify generation of '==' checks.
- return context.typeEnvironment.coreTypes.boolRawType(context.nonNullable);
- }
- return const DynamicType();
- }
-
- @override
- R accept<R>(ExpressionVisitor<R> v) => v.visitMethodInvocation(this);
-
- @override
- R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
- v.visitMethodInvocation(this, arg);
-
- @override
- void visitChildren(Visitor v) {
- receiver.accept(v);
- interfaceTarget?.acceptReference(v);
- name.accept(v);
- arguments.accept(v);
- }
-
- @override
- void transformChildren(Transformer v) {
- // ignore: unnecessary_null_comparison
- if (receiver != null) {
- receiver = v.transform(receiver);
- receiver.parent = this;
- }
- // ignore: unnecessary_null_comparison
- if (arguments != null) {
- arguments = v.transform(arguments);
- arguments.parent = this;
- }
- }
-
- @override
- void transformOrRemoveChildren(RemovingTransformer v) {
- // ignore: unnecessary_null_comparison
- if (receiver != null) {
- receiver = v.transform(receiver);
- receiver.parent = this;
- }
- // ignore: unnecessary_null_comparison
- if (arguments != null) {
- arguments = v.transform(arguments);
- arguments.parent = this;
- }
- }
-
- @override
- String toString() {
- return "MethodInvocation(${toStringInternal()})";
- }
-
- @override
- void toTextInternal(AstPrinter printer) {
- printer.writeExpression(receiver,
- minimumPrecedence: astToText.Precedence.PRIMARY);
- printer.write('.');
- printer.writeInterfaceMemberName(interfaceTargetReference, name);
- printer.writeArguments(arguments);
- }
-}
-
/// Expression of form `super.foo(x)`.
///
/// The provided arguments might not match the parameters of the target.
@@ -8611,23 +8220,28 @@
/// Tearing off a constructor of a class.
class ConstructorTearOff extends Expression {
/// The reference to the constructor being torn off.
- Reference constructorReference;
+ Reference targetReference;
- ConstructorTearOff(Constructor constructor)
- : this.byReference(getNonNullableMemberReferenceGetter(constructor));
+ ConstructorTearOff(Member target)
+ : assert(target is Constructor ||
+ (target is Procedure && target.kind == ProcedureKind.Factory)),
+ this.targetReference = getNonNullableMemberReferenceGetter(target);
- ConstructorTearOff.byReference(this.constructorReference);
+ ConstructorTearOff.byReference(this.targetReference);
- Constructor get constructor => constructorReference.asConstructor;
+ Member get target => targetReference.asMember;
- void set constructor(Constructor constructor) {
- constructorReference = getNonNullableMemberReferenceGetter(constructor);
+ FunctionNode get function => target.function!;
+
+ void set target(Member member) {
+ assert(member is Constructor ||
+ (member is Procedure && member.kind == ProcedureKind.Factory));
+ targetReference = getNonNullableMemberReferenceGetter(member);
}
@override
DartType getStaticTypeInternal(StaticTypeContext context) {
- return constructorReference.asConstructor.function
- .computeFunctionType(Nullability.nonNullable);
+ return target.function!.computeFunctionType(Nullability.nonNullable);
}
@override
@@ -8639,7 +8253,7 @@
@override
void visitChildren(Visitor v) {
- constructor.acceptReference(v);
+ target.acceptReference(v);
}
@override
@@ -8655,7 +8269,60 @@
@override
void toTextInternal(AstPrinter printer) {
- printer.writeMemberName(constructorReference);
+ printer.writeMemberName(targetReference);
+ }
+}
+
+/// Tearing off a redirecting factory constructor of a class.
+class RedirectingFactoryTearOff extends Expression {
+ /// The reference to the redirecting factory constructor being torn off.
+ Reference targetReference;
+
+ RedirectingFactoryTearOff(Procedure target)
+ : assert(target.isRedirectingFactory),
+ this.targetReference = getNonNullableMemberReferenceGetter(target);
+
+ RedirectingFactoryTearOff.byReference(this.targetReference);
+
+ Procedure get target => targetReference.asProcedure;
+
+ void set target(Procedure target) {
+ targetReference = getNonNullableMemberReferenceGetter(target);
+ }
+
+ FunctionNode get function => target.function;
+
+ @override
+ DartType getStaticTypeInternal(StaticTypeContext context) {
+ return target.function.computeFunctionType(Nullability.nonNullable);
+ }
+
+ @override
+ R accept<R>(ExpressionVisitor<R> v) => v.visitRedirectingFactoryTearOff(this);
+
+ @override
+ R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
+ v.visitRedirectingFactoryTearOff(this, arg);
+
+ @override
+ void visitChildren(Visitor v) {
+ target.acceptReference(v);
+ }
+
+ @override
+ void transformChildren(Transformer v) {}
+
+ @override
+ void transformOrRemoveChildren(RemovingTransformer v) {}
+
+ @override
+ String toString() {
+ return "RedirectingFactoryTearOff(${toStringInternal()})";
+ }
+
+ @override
+ void toTextInternal(AstPrinter printer) {
+ printer.writeMemberName(targetReference);
}
}
@@ -8674,10 +8341,9 @@
FreshTypeParameters freshTypeParameters =
getFreshTypeParameters(typeParameters);
FunctionType type = expression.getStaticType(context) as FunctionType;
- type = Substitution.combine(
- Substitution.fromPairs(type.typeParameters, typeArguments),
- freshTypeParameters.substitution)
- .substituteType(type.withoutTypeParameters) as FunctionType;
+ type = freshTypeParameters.substitute(
+ Substitution.fromPairs(type.typeParameters, typeArguments)
+ .substituteType(type.withoutTypeParameters)) as FunctionType;
return new FunctionType(
type.positionalParameters, type.returnType, type.declaredNullability,
namedParameters: type.namedParameters,
@@ -8729,9 +8395,11 @@
@override
void toTextInternal(AstPrinter printer) {
- printer.writeExpression(expression);
printer.writeTypeParameters(typeParameters);
+ printer.write(".(");
+ printer.writeExpression(expression);
printer.writeTypeArguments(typeArguments);
+ printer.write(")");
}
}
@@ -10534,6 +10202,9 @@
R accept<R>(Visitor<R> v) => v.visitName(this);
@override
+ R accept1<R, A>(Visitor1<R, A> v, A arg) => v.visitName(this, arg);
+
+ @override
void visitChildren(Visitor v) {
// DESIGN TODO: Should we visit the library as a library reference?
}
@@ -11637,6 +11308,9 @@
R accept<R>(Visitor<R> v) => v.visitNamedType(this);
@override
+ R accept1<R, A>(Visitor1<R, A> v, A arg) => v.visitNamedType(this, arg);
+
+ @override
void visitChildren(Visitor v) {
type.accept(v);
}
@@ -12392,6 +12066,9 @@
R accept<R>(Visitor<R> v) => v.visitSupertype(this);
+ @override
+ R accept1<R, A>(Visitor1<R, A> v, A arg) => v.visitSupertype(this, arg);
+
visitChildren(Visitor v) {
classNode.acceptReference(v);
visitList(typeArguments, v);
@@ -12445,31 +12122,46 @@
///
/// (Note that a constant can be seen as a DAG (directed acyclic graph) and
/// not a tree!)
- visitChildren(Visitor v);
+ @override
+ void visitChildren(Visitor v);
/// Calls the `visit*Constant()` method on the visitor [v].
+ @override
R accept<R>(ConstantVisitor<R> v);
+ /// Calls the `visit*Constant()` method on the visitor [v].
+ @override
+ R accept1<R, A>(ConstantVisitor1<R, A> v, A arg);
+
/// Calls the `visit*ConstantReference()` method on the visitor [v].
R acceptReference<R>(Visitor<R> v);
+ /// Calls the `visit*ConstantReference()` method on the visitor [v].
+ R acceptReference1<R, A>(Visitor1<R, A> v, A arg);
+
/// The Kernel AST will reference [Constant]s via [ConstantExpression]s. The
/// constants are not required to be canonicalized, but they have to be deeply
/// comparable via hashCode/==!
+ @override
int get hashCode;
+
+ @override
bool operator ==(Object other);
+ @override
String toString() => throw '$runtimeType';
/// Returns a textual representation of the this constant.
///
/// If [verbose] is `true`, qualified names will include the library name/uri.
+ @override
String toText(AstTextStrategy strategy) {
AstPrinter printer = new AstPrinter(strategy);
printer.writeConstant(this);
return printer.getText();
}
+ @override
void toTextInternal(AstPrinter printer);
/// Gets the type of this constant.
@@ -12485,8 +12177,10 @@
PrimitiveConstant(this.value);
+ @override
int get hashCode => value.hashCode;
+ @override
bool operator ==(Object other) =>
other is PrimitiveConstant<T> && other.value == value;
@@ -12499,10 +12193,24 @@
class NullConstant extends PrimitiveConstant<Null> {
NullConstant() : super(null);
- visitChildren(Visitor v) {}
+ @override
+ void visitChildren(Visitor v) {}
+
+ @override
R accept<R>(ConstantVisitor<R> v) => v.visitNullConstant(this);
+
+ @override
+ R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
+ v.visitNullConstant(this, arg);
+
+ @override
R acceptReference<R>(Visitor<R> v) => v.visitNullConstantReference(this);
+ @override
+ R acceptReference1<R, A>(Visitor1<R, A> v, A arg) =>
+ v.visitNullConstantReference(this, arg);
+
+ @override
DartType getType(StaticTypeContext context) => const NullType();
@override
@@ -12512,10 +12220,24 @@
class BoolConstant extends PrimitiveConstant<bool> {
BoolConstant(bool value) : super(value);
- visitChildren(Visitor v) {}
+ @override
+ void visitChildren(Visitor v) {}
+
+ @override
R accept<R>(ConstantVisitor<R> v) => v.visitBoolConstant(this);
+
+ @override
+ R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
+ v.visitBoolConstant(this, arg);
+
+ @override
R acceptReference<R>(Visitor<R> v) => v.visitBoolConstantReference(this);
+ @override
+ R acceptReference1<R, A>(Visitor1<R, A> v, A arg) =>
+ v.visitBoolConstantReference(this, arg);
+
+ @override
DartType getType(StaticTypeContext context) =>
context.typeEnvironment.coreTypes.boolRawType(context.nonNullable);
@@ -12527,10 +12249,24 @@
class IntConstant extends PrimitiveConstant<int> {
IntConstant(int value) : super(value);
- visitChildren(Visitor v) {}
+ @override
+ void visitChildren(Visitor v) {}
+
+ @override
R accept<R>(ConstantVisitor<R> v) => v.visitIntConstant(this);
+
+ @override
+ R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
+ v.visitIntConstant(this, arg);
+
+ @override
R acceptReference<R>(Visitor<R> v) => v.visitIntConstantReference(this);
+ @override
+ R acceptReference1<R, A>(Visitor1<R, A> v, A arg) =>
+ v.visitIntConstantReference(this, arg);
+
+ @override
DartType getType(StaticTypeContext context) =>
context.typeEnvironment.coreTypes.intRawType(context.nonNullable);
@@ -12542,14 +12278,31 @@
class DoubleConstant extends PrimitiveConstant<double> {
DoubleConstant(double value) : super(value);
- visitChildren(Visitor v) {}
+ @override
+ void visitChildren(Visitor v) {}
+
+ @override
R accept<R>(ConstantVisitor<R> v) => v.visitDoubleConstant(this);
+
+ @override
+ R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
+ v.visitDoubleConstant(this, arg);
+
+ @override
R acceptReference<R>(Visitor<R> v) => v.visitDoubleConstantReference(this);
+ @override
+ R acceptReference1<R, A>(Visitor1<R, A> v, A arg) =>
+ v.visitDoubleConstantReference(this, arg);
+
+ @override
int get hashCode => value.isNaN ? 199 : super.hashCode;
+
+ @override
bool operator ==(Object other) =>
other is DoubleConstant && identical(value, other.value);
+ @override
DartType getType(StaticTypeContext context) =>
context.typeEnvironment.coreTypes.doubleRawType(context.nonNullable);
@@ -12563,11 +12316,24 @@
assert(value != null);
}
- visitChildren(Visitor v) {}
+ @override
+ void visitChildren(Visitor v) {}
+
+ @override
R accept<R>(ConstantVisitor<R> v) => v.visitStringConstant(this);
+
+ @override
+ R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
+ v.visitStringConstant(this, arg);
+
+ @override
R acceptReference<R>(Visitor<R> v) => v.visitStringConstantReference(this);
@override
+ R acceptReference1<R, A>(Visitor1<R, A> v, A arg) =>
+ v.visitStringConstantReference(this, arg);
+
+ @override
DartType getType(StaticTypeContext context) =>
context.typeEnvironment.coreTypes.stringRawType(context.nonNullable);
@@ -12578,6 +12344,7 @@
printer.write('"');
}
+ @override
String toString() => 'StringConstant(${toStringInternal()})';
}
@@ -12587,22 +12354,37 @@
SymbolConstant(this.name, this.libraryReference);
- visitChildren(Visitor v) {}
+ @override
+ void visitChildren(Visitor v) {}
+ @override
R accept<R>(ConstantVisitor<R> v) => v.visitSymbolConstant(this);
+
+ @override
+ R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
+ v.visitSymbolConstant(this, arg);
+
+ @override
R acceptReference<R>(Visitor<R> v) => v.visitSymbolConstantReference(this);
@override
+ R acceptReference1<R, A>(Visitor1<R, A> v, A arg) =>
+ v.visitSymbolConstantReference(this, arg);
+
+ @override
String toString() => 'SymbolConstant(${toStringInternal()})';
+ @override
int get hashCode => _Hash.hash2(name, libraryReference);
+ @override
bool operator ==(Object other) =>
identical(this, other) ||
(other is SymbolConstant &&
other.name == name &&
other.libraryReference == libraryReference);
+ @override
DartType getType(StaticTypeContext context) =>
context.typeEnvironment.coreTypes.symbolRawType(context.nonNullable);
@@ -12624,7 +12406,8 @@
MapConstant(this.keyType, this.valueType, this.entries);
- visitChildren(Visitor v) {
+ @override
+ void visitChildren(Visitor v) {
keyType.accept(v);
valueType.accept(v);
for (final ConstantMapEntry entry in entries) {
@@ -12633,10 +12416,21 @@
}
}
+ @override
R accept<R>(ConstantVisitor<R> v) => v.visitMapConstant(this);
+
+ @override
+ R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
+ v.visitMapConstant(this, arg);
+
+ @override
R acceptReference<R>(Visitor<R> v) => v.visitMapConstantReference(this);
@override
+ R acceptReference1<R, A>(Visitor1<R, A> v, A arg) =>
+ v.visitMapConstantReference(this, arg);
+
+ @override
void toTextInternal(AstPrinter printer) {
printer.write('const <');
printer.writeType(keyType);
@@ -12659,6 +12453,7 @@
late final int hashCode = _Hash.combine2Finish(
keyType.hashCode, valueType.hashCode, _Hash.combineListHash(entries));
+ @override
bool operator ==(Object other) =>
identical(this, other) ||
(other is MapConstant &&
@@ -12666,6 +12461,7 @@
other.valueType == valueType &&
listEquals(other.entries, entries));
+ @override
DartType getType(StaticTypeContext context) =>
context.typeEnvironment.mapType(keyType, valueType, context.nonNullable);
}
@@ -12706,17 +12502,29 @@
ListConstant(this.typeArgument, this.entries);
- visitChildren(Visitor v) {
+ @override
+ void visitChildren(Visitor v) {
typeArgument.accept(v);
for (final Constant constant in entries) {
constant.acceptReference(v);
}
}
+ @override
R accept<R>(ConstantVisitor<R> v) => v.visitListConstant(this);
+
+ @override
+ R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
+ v.visitListConstant(this, arg);
+
+ @override
R acceptReference<R>(Visitor<R> v) => v.visitListConstantReference(this);
@override
+ R acceptReference1<R, A>(Visitor1<R, A> v, A arg) =>
+ v.visitListConstantReference(this, arg);
+
+ @override
void toTextInternal(AstPrinter printer) {
printer.write('const <');
printer.writeType(typeArgument);
@@ -12737,12 +12545,14 @@
late final int hashCode = _Hash.combineFinish(
typeArgument.hashCode, _Hash.combineListHash(entries));
+ @override
bool operator ==(Object other) =>
identical(this, other) ||
(other is ListConstant &&
other.typeArgument == typeArgument &&
listEquals(other.entries, entries));
+ @override
DartType getType(StaticTypeContext context) =>
context.typeEnvironment.listType(typeArgument, context.nonNullable);
}
@@ -12753,17 +12563,29 @@
SetConstant(this.typeArgument, this.entries);
- visitChildren(Visitor v) {
+ @override
+ void visitChildren(Visitor v) {
typeArgument.accept(v);
for (final Constant constant in entries) {
constant.acceptReference(v);
}
}
+ @override
R accept<R>(ConstantVisitor<R> v) => v.visitSetConstant(this);
+
+ @override
+ R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
+ v.visitSetConstant(this, arg);
+
+ @override
R acceptReference<R>(Visitor<R> v) => v.visitSetConstantReference(this);
@override
+ R acceptReference1<R, A>(Visitor1<R, A> v, A arg) =>
+ v.visitSetConstantReference(this, arg);
+
+ @override
void toTextInternal(AstPrinter printer) {
printer.write('const <');
printer.writeType(typeArgument);
@@ -12784,12 +12606,14 @@
late final int hashCode = _Hash.combineFinish(
typeArgument.hashCode, _Hash.combineListHash(entries));
+ @override
bool operator ==(Object other) =>
identical(this, other) ||
(other is SetConstant &&
other.typeArgument == typeArgument &&
listEquals(other.entries, entries));
+ @override
DartType getType(StaticTypeContext context) =>
context.typeEnvironment.setType(typeArgument, context.nonNullable);
}
@@ -12815,9 +12639,19 @@
}
R accept<R>(ConstantVisitor<R> v) => v.visitInstanceConstant(this);
+
+ @override
+ R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
+ v.visitInstanceConstant(this, arg);
+
+ @override
R acceptReference<R>(Visitor<R> v) => v.visitInstanceConstantReference(this);
@override
+ R acceptReference1<R, A>(Visitor1<R, A> v, A arg) =>
+ v.visitInstanceConstantReference(this, arg);
+
+ @override
void toTextInternal(AstPrinter printer) {
printer.write('const ');
printer.writeClassName(classReference);
@@ -12841,6 +12675,7 @@
late final int hashCode = _Hash.combine2Finish(classReference.hashCode,
listHashCode(typeArguments), _Hash.combineMapHashUnordered(fieldValues));
+ @override
bool operator ==(Object other) {
return identical(this, other) ||
(other is InstanceConstant &&
@@ -12849,26 +12684,39 @@
mapEquals(other.fieldValues, fieldValues));
}
+ @override
DartType getType(StaticTypeContext context) =>
new InterfaceType(classNode, context.nonNullable, typeArguments);
}
class InstantiationConstant extends Constant {
- final TearOffConstant tearOffConstant;
+ final Constant tearOffConstant;
final List<DartType> types;
InstantiationConstant(this.tearOffConstant, this.types);
- visitChildren(Visitor v) {
+ @override
+ void visitChildren(Visitor v) {
tearOffConstant.acceptReference(v);
visitList(types, v);
}
+ @override
R accept<R>(ConstantVisitor<R> v) => v.visitInstantiationConstant(this);
+
+ @override
+ R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
+ v.visitInstantiationConstant(this, arg);
+
+ @override
R acceptReference<R>(Visitor<R> v) =>
v.visitInstantiationConstantReference(this);
@override
+ R acceptReference1<R, A>(Visitor1<R, A> v, A arg) =>
+ v.visitInstantiationConstantReference(this, arg);
+
+ @override
void toTextInternal(AstPrinter printer) {
printer.writeConstant(tearOffConstant);
printer.writeTypeArguments(types);
@@ -12877,15 +12725,18 @@
@override
String toString() => 'InstantiationConstant(${toStringInternal()})';
+ @override
int get hashCode => _Hash.combineFinish(
tearOffConstant.hashCode, _Hash.combineListHash(types));
+ @override
bool operator ==(Object other) {
return other is InstantiationConstant &&
other.tearOffConstant == tearOffConstant &&
listEquals(other.types, types);
}
+ @override
DartType getType(StaticTypeContext context) {
final FunctionType type = tearOffConstant.getType(context) as FunctionType;
final Map<TypeParameter, DartType> mapping = <TypeParameter, DartType>{};
@@ -12897,100 +12748,184 @@
}
abstract class TearOffConstant implements Constant {
- Reference get memberReference;
- Member get member;
+ Reference get targetReference;
+ Member get target;
FunctionNode get function;
}
class StaticTearOffConstant extends Constant implements TearOffConstant {
@override
- final Reference memberReference;
+ final Reference targetReference;
StaticTearOffConstant(Procedure procedure)
- : memberReference = procedure.reference {
+ : targetReference = procedure.reference {
assert(procedure.isStatic);
}
- StaticTearOffConstant.byReference(this.memberReference);
+ StaticTearOffConstant.byReference(this.targetReference);
@override
- Member get member => memberReference.asMember;
+ Procedure get target => targetReference.asProcedure;
@override
- FunctionNode get function => procedure.function;
+ FunctionNode get function => target.function;
- Procedure get procedure => memberReference.asProcedure;
-
- visitChildren(Visitor v) {
- memberReference.asProcedure.acceptReference(v);
+ @override
+ void visitChildren(Visitor v) {
+ target.acceptReference(v);
}
+ @override
R accept<R>(ConstantVisitor<R> v) => v.visitStaticTearOffConstant(this);
+
+ @override
+ R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
+ v.visitStaticTearOffConstant(this, arg);
+
+ @override
R acceptReference<R>(Visitor<R> v) =>
v.visitStaticTearOffConstantReference(this);
@override
+ R acceptReference1<R, A>(Visitor1<R, A> v, A arg) =>
+ v.visitStaticTearOffConstantReference(this, arg);
+
+ @override
void toTextInternal(AstPrinter printer) {
- printer.writeMemberName(memberReference);
+ printer.writeMemberName(targetReference);
}
@override
String toString() => 'StaticTearOffConstant(${toStringInternal()})';
- int get hashCode => memberReference.hashCode;
+ @override
+ int get hashCode => targetReference.hashCode;
+ @override
bool operator ==(Object other) {
return other is StaticTearOffConstant &&
- other.memberReference == memberReference;
+ other.targetReference == targetReference;
}
+ @override
FunctionType getType(StaticTypeContext context) {
- return procedure.function.computeFunctionType(context.nonNullable);
+ return target.function.computeFunctionType(context.nonNullable);
}
}
class ConstructorTearOffConstant extends Constant implements TearOffConstant {
@override
- final Reference memberReference;
+ final Reference targetReference;
- ConstructorTearOffConstant(Constructor constructor)
- : memberReference = constructor.reference;
+ ConstructorTearOffConstant(Member target)
+ : assert(target is Constructor ||
+ (target is Procedure && target.kind == ProcedureKind.Factory)),
+ this.targetReference = getNonNullableMemberReferenceGetter(target);
- ConstructorTearOffConstant.byReference(this.memberReference);
+ ConstructorTearOffConstant.byReference(this.targetReference);
@override
- Member get member => memberReference.asMember;
+ Member get target => targetReference.asMember;
@override
- FunctionNode get function => constructor.function;
+ FunctionNode get function => target.function!;
- Constructor get constructor => memberReference.asConstructor;
-
- visitChildren(Visitor v) {
- memberReference.asProcedure.acceptReference(v);
+ @override
+ void visitChildren(Visitor v) {
+ target.acceptReference(v);
}
+ @override
R accept<R>(ConstantVisitor<R> v) => v.visitConstructorTearOffConstant(this);
+
+ @override
+ R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
+ v.visitConstructorTearOffConstant(this, arg);
+
+ @override
R acceptReference<R>(Visitor<R> v) =>
v.visitConstructorTearOffConstantReference(this);
@override
+ R acceptReference1<R, A>(Visitor1<R, A> v, A arg) =>
+ v.visitConstructorTearOffConstantReference(this, arg);
+
+ @override
void toTextInternal(AstPrinter printer) {
- printer.writeMemberName(memberReference);
+ printer.writeMemberName(targetReference);
}
@override
String toString() => 'ConstructorTearOffConstant(${toStringInternal()})';
- int get hashCode => memberReference.hashCode;
+ int get hashCode => targetReference.hashCode;
bool operator ==(Object other) {
- return other is StaticTearOffConstant &&
- other.memberReference == memberReference;
+ return other is ConstructorTearOffConstant &&
+ other.targetReference == targetReference;
}
FunctionType getType(StaticTypeContext context) {
- return constructor.function.computeFunctionType(context.nonNullable);
+ return function.computeFunctionType(context.nonNullable);
+ }
+}
+
+class RedirectingFactoryTearOffConstant extends Constant
+ implements TearOffConstant {
+ @override
+ final Reference targetReference;
+
+ RedirectingFactoryTearOffConstant(Procedure target)
+ : assert(target.isRedirectingFactory),
+ this.targetReference = getNonNullableMemberReferenceGetter(target);
+
+ RedirectingFactoryTearOffConstant.byReference(this.targetReference);
+
+ @override
+ Procedure get target => targetReference.asProcedure;
+
+ @override
+ FunctionNode get function => target.function;
+
+ @override
+ void visitChildren(Visitor v) {
+ target.acceptReference(v);
+ }
+
+ @override
+ R accept<R>(ConstantVisitor<R> v) =>
+ v.visitRedirectingFactoryTearOffConstant(this);
+
+ @override
+ R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
+ v.visitRedirectingFactoryTearOffConstant(this, arg);
+
+ @override
+ R acceptReference<R>(Visitor<R> v) =>
+ v.visitRedirectingFactoryTearOffConstantReference(this);
+
+ @override
+ R acceptReference1<R, A>(Visitor1<R, A> v, A arg) =>
+ v.visitRedirectingFactoryTearOffConstantReference(this, arg);
+
+ @override
+ void toTextInternal(AstPrinter printer) {
+ printer.writeMemberName(targetReference);
+ }
+
+ @override
+ String toString() =>
+ 'RedirectingFactoryTearOffConstant(${toStringInternal()})';
+
+ int get hashCode => targetReference.hashCode;
+
+ bool operator ==(Object other) {
+ return other is RedirectingFactoryTearOffConstant &&
+ other.targetReference == targetReference;
+ }
+
+ FunctionType getType(StaticTypeContext context) {
+ return function.computeFunctionType(context.nonNullable);
}
}
@@ -12999,21 +12934,36 @@
final TearOffConstant tearOffConstant;
final List<DartType> types;
+ late final int hashCode = _computeHashCode();
+
TypedefTearOffConstant(this.parameters, this.tearOffConstant, this.types);
- visitChildren(Visitor v) {
+ @override
+ void visitChildren(Visitor v) {
visitList(parameters, v);
tearOffConstant.acceptReference(v);
visitList(types, v);
}
+ @override
R accept<R>(ConstantVisitor<R> v) => v.visitTypedefTearOffConstant(this);
- R acceptReference<R>(Visitor<R> v) => v.visitTypedefTearOffConstant(this);
+
+ @override
+ R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
+ v.visitTypedefTearOffConstant(this, arg);
+
+ @override
+ R acceptReference<R>(Visitor<R> v) =>
+ v.visitTypedefTearOffConstantReference(this);
+
+ @override
+ R acceptReference1<R, A>(Visitor1<R, A> v, A arg) =>
+ v.visitTypedefTearOffConstantReference(this, arg);
@override
void toTextInternal(AstPrinter printer) {
- printer.writeConstant(tearOffConstant);
printer.writeTypeParameters(parameters);
+ printer.writeConstant(tearOffConstant);
printer.writeTypeArguments(types);
}
@@ -13045,13 +12995,26 @@
return true;
}
+ int _computeHashCode() {
+ int hash = 1237;
+ for (int i = 0; i < parameters.length; ++i) {
+ TypeParameter parameter = parameters[i];
+ hash = 0x3fffffff & (hash * 31 + parameter.bound.hashCode);
+ }
+ for (int i = 0; i < types.length; ++i) {
+ hash = 0x3fffffff & (hash * 31 + types[i].hashCode);
+ }
+ hash = 0x3fffffff & (hash * 31 + tearOffConstant.hashCode);
+ return hash;
+ }
+
DartType getType(StaticTypeContext context) {
FunctionType type = tearOffConstant.getType(context) as FunctionType;
FreshTypeParameters freshTypeParameters =
getFreshTypeParameters(parameters);
type = freshTypeParameters.substitute(
- Substitution.fromPairs(parameters, types).substituteType(type))
- as FunctionType;
+ Substitution.fromPairs(type.typeParameters, types)
+ .substituteType(type.withoutTypeParameters)) as FunctionType;
return new FunctionType(
type.positionalParameters, type.returnType, type.declaredNullability,
namedParameters: type.namedParameters,
@@ -13066,15 +13029,27 @@
TypeLiteralConstant(this.type);
- visitChildren(Visitor v) {
+ @override
+ void visitChildren(Visitor v) {
type.accept(v);
}
+ @override
R accept<R>(ConstantVisitor<R> v) => v.visitTypeLiteralConstant(this);
+
+ @override
+ R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
+ v.visitTypeLiteralConstant(this, arg);
+
+ @override
R acceptReference<R>(Visitor<R> v) =>
v.visitTypeLiteralConstantReference(this);
@override
+ R acceptReference1<R, A>(Visitor1<R, A> v, A arg) =>
+ v.visitTypeLiteralConstantReference(this, arg);
+
+ @override
void toTextInternal(AstPrinter printer) {
printer.writeType(type);
}
@@ -13082,8 +13057,10 @@
@override
String toString() => 'TypeLiteralConstant(${toStringInternal()})';
+ @override
int get hashCode => type.hashCode;
+ @override
bool operator ==(Object other) {
return other is TypeLiteralConstant && other.type == type;
}
@@ -13099,14 +13076,26 @@
expression.parent = null;
}
- visitChildren(Visitor v) {
+ @override
+ void visitChildren(Visitor v) {
expression.accept(v);
}
+ @override
R accept<R>(ConstantVisitor<R> v) => v.visitUnevaluatedConstant(this);
+
+ @override
+ R accept1<R, A>(ConstantVisitor1<R, A> v, A arg) =>
+ v.visitUnevaluatedConstant(this, arg);
+
+ @override
R acceptReference<R>(Visitor<R> v) =>
v.visitUnevaluatedConstantReference(this);
+ @override
+ R acceptReference1<R, A>(Visitor1<R, A> v, A arg) =>
+ v.visitUnevaluatedConstantReference(this, arg);
+
DartType getType(StaticTypeContext context) =>
expression.getStaticType(context);
@@ -13383,7 +13372,7 @@
/// Write List<Byte> into the sink.
void writeByteList(List<int> bytes);
- void writeNullAllowedCanonicalNameReference(CanonicalName name);
+ void writeNullAllowedCanonicalNameReference(CanonicalName? name);
void writeStringReference(String str);
void writeName(Name node);
void writeDartType(DartType type);
@@ -14037,12 +14026,11 @@
final List<Constructor> emptyListOfConstructor =
List.filled(0, dummyConstructor, growable: false);
-/// Almost const <RedirectingFactoryConstructor>[], but not const in an attempt
-/// to avoid polymorphism. See
+/// Almost const <RedirectingFactory>[], but not const in an attempt to avoid
+/// polymorphism. See
/// https://dart-review.googlesource.com/c/sdk/+/185828.
-final List<RedirectingFactoryConstructor>
- emptyListOfRedirectingFactoryConstructor =
- List.filled(0, dummyRedirectingFactoryConstructor, growable: false);
+final List<RedirectingFactory> emptyListOfRedirectingFactory =
+ List.filled(0, dummyRedirectingFactory, growable: false);
/// Almost const <Initializer>[], but not const in an attempt to avoid
/// polymorphism. See https://dart-review.googlesource.com/c/sdk/+/185828.
@@ -14170,13 +14158,13 @@
/// constructor.
final Field dummyField = new Field.mutable(dummyName, fileUri: dummyUri);
-/// Non-nullable [RedirectingFactoryConstructor] dummy value.
+/// Non-nullable [RedirectingFactory] dummy value.
///
/// This is used as the removal sentinel in [RemovingTransformer] and can be
/// used for instance as a dummy initial value for the `List.filled`
/// constructor.
-final RedirectingFactoryConstructor dummyRedirectingFactoryConstructor =
- new RedirectingFactoryConstructor(null, name: dummyName, fileUri: dummyUri);
+final RedirectingFactory dummyRedirectingFactory = new RedirectingFactory(null,
+ name: dummyName, fileUri: dummyUri, function: dummyFunctionNode);
/// Non-nullable [Typedef] dummy value.
///
@@ -14307,7 +14295,7 @@
dummyMember,
dummyProcedure,
dummyField,
- dummyRedirectingFactoryConstructor,
+ dummyRedirectingFactory,
dummyTypedef,
dummyInitializer,
dummyFunctionNode,
diff --git a/pkg/kernel/lib/binary/ast_from_binary.dart b/pkg/kernel/lib/binary/ast_from_binary.dart
index a257708..80b2979 100644
--- a/pkg/kernel/lib/binary/ast_from_binary.dart
+++ b/pkg/kernel/lib/binary/ast_from_binary.dart
@@ -373,6 +373,8 @@
return _readStaticTearOffConstant();
case ConstantTag.ConstructorTearOffConstant:
return _readConstructorTearOffConstant();
+ case ConstantTag.RedirectingFactoryTearOffConstant:
+ return _readRedirectingFactoryTearOffConstant();
case ConstantTag.TypeLiteralConstant:
return _readTypeLiteralConstant();
case ConstantTag.UnevaluatedConstant:
@@ -446,17 +448,17 @@
}
Constant _readInstantiationConstant() {
- final StaticTearOffConstant tearOffConstant =
- readConstantReference() as StaticTearOffConstant;
+ final Constant tearOffConstant = readConstantReference();
final List<DartType> types = readDartTypeList();
return new InstantiationConstant(tearOffConstant, types);
}
Constant _readTypedefTearOffConstant() {
final List<TypeParameter> parameters = readAndPushTypeParameterList();
- final StaticTearOffConstant tearOffConstant =
- readConstantReference() as StaticTearOffConstant;
+ final TearOffConstant tearOffConstant =
+ readConstantReference() as TearOffConstant;
final List<DartType> types = readDartTypeList();
+ typeParameterStack.length -= parameters.length;
return new TypedefTearOffConstant(parameters, tearOffConstant, types);
}
@@ -470,6 +472,11 @@
return new ConstructorTearOffConstant.byReference(reference);
}
+ Constant _readRedirectingFactoryTearOffConstant() {
+ final Reference reference = readNonNullCanonicalNameReference().reference;
+ return new RedirectingFactoryTearOffConstant.byReference(reference);
+ }
+
Constant _readTypeLiteralConstant() {
final DartType type = readDartType();
return new TypeLiteralConstant(type);
@@ -1478,7 +1485,7 @@
node.fieldsInternal = _readFieldList(node);
_readConstructorList(node);
node.proceduresInternal = _readProcedureList(node, procedureOffsets);
- _readRedirectingFactoryConstructorList(node);
+ _readRedirectingFactoryList(node);
}
void _readConstructorList(Class node) {
@@ -1494,17 +1501,17 @@
}
}
- void _readRedirectingFactoryConstructorList(Class node) {
+ void _readRedirectingFactoryList(Class node) {
int length = readUInt30();
if (!useGrowableLists && length == 0) {
// When lists don't have to be growable anyway, we might as well use a
// constant one for the empty list.
node.redirectingFactoryConstructorsInternal =
- emptyListOfRedirectingFactoryConstructor;
+ emptyListOfRedirectingFactory;
} else {
node.redirectingFactoryConstructorsInternal =
- new List<RedirectingFactoryConstructor>.generate(length,
- (int index) => readRedirectingFactoryConstructor()..parent = node,
+ new List<RedirectingFactory>.generate(
+ length, (int index) => readRedirectingFactory()..parent = node,
growable: useGrowableLists);
}
}
@@ -1690,13 +1697,12 @@
return node;
}
- RedirectingFactoryConstructor readRedirectingFactoryConstructor() {
+ RedirectingFactory readRedirectingFactory() {
int tag = readByte();
- assert(tag == Tag.RedirectingFactoryConstructor);
+ assert(tag == Tag.RedirectingFactory);
CanonicalName canonicalName = readNonNullCanonicalNameReference();
Reference reference = canonicalName.reference;
- RedirectingFactoryConstructor? node =
- reference.node as RedirectingFactoryConstructor?;
+ RedirectingFactory? node = reference.node as RedirectingFactory?;
if (alwaysCreateNewNamedNodes) {
node = null;
}
@@ -1705,39 +1711,34 @@
int fileEndOffset = readOffset();
int flags = readByte();
Name name = readName();
- if (node == null) {
- node = new RedirectingFactoryConstructor(null,
- reference: reference, name: name, fileUri: fileUri);
- }
- List<Expression> annotations = readAnnotationList(node);
assert(() {
debugPath.add(name.text);
return true;
}());
+ List<Expression> annotations = readAnnotationList();
Reference targetReference = readNonNullMemberReference();
List<DartType> typeArguments = readDartTypeList();
- int typeParameterStackHeight = typeParameterStack.length;
- List<TypeParameter> typeParameters = readAndPushTypeParameterList();
- readUInt30(); // Total parameter count.
- int requiredParameterCount = readUInt30();
- int variableStackHeight = variableStack.length;
- List<VariableDeclaration> positional = readAndPushVariableDeclarationList();
- List<VariableDeclaration> named = readAndPushVariableDeclarationList();
- variableStack.length = variableStackHeight;
- typeParameterStack.length = typeParameterStackHeight;
- debugPath.removeLast();
+ FunctionNode function = readFunctionNode(outerEndOffset: fileEndOffset);
+ if (node == null) {
+ node = new RedirectingFactory(targetReference,
+ reference: reference,
+ name: name,
+ fileUri: fileUri,
+ function: function,
+ typeArguments: typeArguments);
+ } else {
+ node.name = name;
+ node.fileUri = fileUri;
+ node.targetReference = targetReference;
+ node.typeArguments.addAll(typeArguments);
+ node.function = function..parent = node;
+ }
node.fileOffset = fileOffset;
node.fileEndOffset = fileEndOffset;
node.flags = flags;
- node.name = name;
- node.fileUri = fileUri;
node.annotations = annotations;
- node.targetReference = targetReference;
- node.typeArguments.addAll(typeArguments);
- node.typeParameters = typeParameters;
- node.requiredParameterCount = requiredParameterCount;
- node.positionalParameters = positional;
- node.namedParameters = named;
+ setParents(annotations, node);
+ debugPath.removeLast();
return node;
}
@@ -1959,16 +1960,12 @@
return _readVariableSet();
case Tag.SpecializedVariableSet:
return _readSpecializedVariableSet(tagByte);
- case Tag.PropertyGet:
- return _readPropertyGet();
case Tag.InstanceGet:
return _readInstanceGet();
case Tag.InstanceTearOff:
return _readInstanceTearOff();
case Tag.DynamicGet:
return _readDynamicGet();
- case Tag.PropertySet:
- return _readPropertySet();
case Tag.InstanceSet:
return _readInstanceSet();
case Tag.DynamicSet:
@@ -1987,8 +1984,8 @@
return _readConstructorTearOff();
case Tag.TypedefTearOff:
return _readTypedefTearOff();
- case Tag.MethodInvocation:
- return _readMethodInvocation();
+ case Tag.RedirectingFactoryTearOff:
+ return _readRedirectingFactoryTearOff();
case Tag.InstanceInvocation:
return _readInstanceInvocation();
case Tag.InstanceGetterInvocation:
@@ -2139,13 +2136,6 @@
..fileOffset = offset;
}
- Expression _readPropertyGet() {
- int offset = readOffset();
- return new PropertyGet.byReference(
- readExpression(), readName(), readNullableInstanceMemberReference())
- ..fileOffset = offset;
- }
-
Expression _readInstanceGet() {
InstanceAccessKind kind = InstanceAccessKind.values[readByte()];
int offset = readOffset();
@@ -2171,13 +2161,6 @@
..fileOffset = offset;
}
- Expression _readPropertySet() {
- int offset = readOffset();
- return new PropertySet.byReference(readExpression(), readName(),
- readExpression(), readNullableInstanceMemberReference())
- ..fileOffset = offset;
- }
-
Expression _readInstanceSet() {
InstanceAccessKind kind = InstanceAccessKind.values[readByte()];
int offset = readOffset();
@@ -2231,6 +2214,13 @@
return new TypedefTearOff(typeParameters, expression, typeArguments);
}
+ Expression _readRedirectingFactoryTearOff() {
+ int offset = readOffset();
+ Reference constructorReference = readNonNullMemberReference();
+ return new RedirectingFactoryTearOff.byReference(constructorReference)
+ ..fileOffset = offset;
+ }
+
Expression _readStaticTearOff() {
int offset = readOffset();
return new StaticTearOff.byReference(readNonNullMemberReference())
@@ -2244,15 +2234,6 @@
..fileOffset = offset;
}
- Expression _readMethodInvocation() {
- int flags = readByte();
- int offset = readOffset();
- return new MethodInvocation.byReference(readExpression(), readName(),
- readArguments(), readNullableInstanceMemberReference())
- ..fileOffset = offset
- ..flags = flags;
- }
-
Expression _readInstanceInvocation() {
InstanceAccessKind kind = InstanceAccessKind.values[readByte()];
int flags = readByte();
@@ -3372,10 +3353,9 @@
}
@override
- RedirectingFactoryConstructor readRedirectingFactoryConstructor() {
+ RedirectingFactory readRedirectingFactory() {
final int nodeOffset = _byteOffset;
- final RedirectingFactoryConstructor result =
- super.readRedirectingFactoryConstructor();
+ final RedirectingFactory result = super.readRedirectingFactory();
return _associateMetadata(result, nodeOffset);
}
diff --git a/pkg/kernel/lib/binary/ast_to_binary.dart b/pkg/kernel/lib/binary/ast_to_binary.dart
index 5460a6e..aa211d3 100644
--- a/pkg/kernel/lib/binary/ast_to_binary.dart
+++ b/pkg/kernel/lib/binary/ast_to_binary.dart
@@ -25,8 +25,8 @@
final ConstantIndexer _constantIndexer;
final UriIndexer _sourceUriIndexer = new UriIndexer();
bool _currentlyInNonimplementation = false;
- final List<bool> _sourcesFromRealImplementation = <bool>[];
- final List<bool> _sourcesUsedInLibrary = <bool>[];
+ final List<bool?> _sourcesFromRealImplementation = <bool?>[];
+ final List<bool?> _sourcesUsedInLibrary = <bool?>[];
Map<LibraryDependency, int> _libraryDependencyIndex =
<LibraryDependency, int>{};
NonNullableByDefaultCompiledMode? compilationMode;
@@ -264,11 +264,15 @@
} else if (constant is StaticTearOffConstant) {
writeByte(ConstantTag.StaticTearOffConstant);
writeNonNullCanonicalNameReference(
- constant.procedure.reference.canonicalName!);
+ constant.targetReference.canonicalName!);
} else if (constant is ConstructorTearOffConstant) {
writeByte(ConstantTag.ConstructorTearOffConstant);
writeNonNullCanonicalNameReference(
- constant.constructor.reference.canonicalName!);
+ constant.targetReference.canonicalName!);
+ } else if (constant is RedirectingFactoryTearOffConstant) {
+ writeByte(ConstantTag.RedirectingFactoryTearOffConstant);
+ writeNonNullCanonicalNameReference(
+ constant.targetReference.canonicalName!);
} else if (constant is TypeLiteralConstant) {
writeByte(ConstantTag.TypeLiteralConstant);
writeDartType(constant.type);
@@ -373,13 +377,12 @@
}
}
- void writeRedirectingFactoryConstructorNodeList(
- List<RedirectingFactoryConstructor> nodes) {
+ void writeRedirectingFactoryNodeList(List<RedirectingFactory> nodes) {
final int len = nodes.length;
writeUInt30(len);
for (int i = 0; i < len; i++) {
- final RedirectingFactoryConstructor node = nodes[i];
- writeRedirectingFactoryConstructorNode(node);
+ final RedirectingFactory node = nodes[i];
+ writeRedirectingFactoryNode(node);
}
}
@@ -473,8 +476,7 @@
node.accept(this);
}
- void writeRedirectingFactoryConstructorNode(
- RedirectingFactoryConstructor node) {
+ void writeRedirectingFactoryNode(RedirectingFactory node) {
if (_metadataSubsections != null) {
_writeNodeMetadata(node);
}
@@ -1205,8 +1207,7 @@
procedureOffsets = <int>[];
writeProcedureNodeList(node.procedures);
procedureOffsets.add(getBufferOffset());
- writeRedirectingFactoryConstructorNodeList(
- node.redirectingFactoryConstructors);
+ writeRedirectingFactoryNodeList(node.redirectingFactories);
leaveScope(typeParameters: node.typeParameters);
assert(procedureOffsets.length > 0);
@@ -1366,35 +1367,21 @@
}
@override
- void visitRedirectingFactoryConstructor(RedirectingFactoryConstructor node) {
+ void visitRedirectingFactory(RedirectingFactory node) {
if (node.reference.canonicalName == null) {
throw new ArgumentError('Missing canonical name for $node');
}
- writeByte(Tag.RedirectingFactoryConstructor);
- enterScope(
- typeParameters: node.typeParameters,
- memberScope: true,
- variableScope: true);
+ writeByte(Tag.RedirectingFactory);
writeNonNullCanonicalNameReference(getCanonicalNameOfMemberGetter(node));
writeUriReference(node.fileUri);
writeOffset(node.fileOffset);
writeOffset(node.fileEndOffset);
writeByte(node.flags);
writeName(node.name);
-
writeAnnotationList(node.annotations);
writeNonNullReference(node.targetReference!);
writeNodeList(node.typeArguments);
- writeNodeList(node.typeParameters);
- writeUInt30(node.positionalParameters.length + node.namedParameters.length);
- writeUInt30(node.requiredParameterCount);
- writeVariableDeclarationList(node.positionalParameters);
- writeVariableDeclarationList(node.namedParameters);
-
- leaveScope(
- typeParameters: node.typeParameters,
- memberScope: true,
- variableScope: true);
+ writeFunctionNode(node.function);
}
@override
@@ -1542,15 +1529,6 @@
}
@override
- void visitPropertyGet(PropertyGet node) {
- writeByte(Tag.PropertyGet);
- writeOffset(node.fileOffset);
- writeNode(node.receiver);
- writeName(node.name);
- writeNullAllowedInstanceMemberReference(node.interfaceTargetReference);
- }
-
- @override
void visitDynamicSet(DynamicSet node) {
writeByte(Tag.DynamicSet);
writeByte(node.kind.index);
@@ -1572,16 +1550,6 @@
}
@override
- void visitPropertySet(PropertySet node) {
- writeByte(Tag.PropertySet);
- writeOffset(node.fileOffset);
- writeNode(node.receiver);
- writeName(node.name);
- writeNode(node.value);
- writeNullAllowedInstanceMemberReference(node.interfaceTargetReference);
- }
-
- @override
void visitSuperPropertyGet(SuperPropertyGet node) {
writeByte(Tag.SuperPropertyGet);
writeOffset(node.fileOffset);
@@ -1609,15 +1577,24 @@
void visitConstructorTearOff(ConstructorTearOff node) {
writeByte(Tag.ConstructorTearOff);
writeOffset(node.fileOffset);
- writeNonNullReference(node.constructorReference);
+ writeNonNullReference(node.targetReference);
+ }
+
+ @override
+ void visitRedirectingFactoryTearOff(RedirectingFactoryTearOff node) {
+ writeByte(Tag.RedirectingFactoryTearOff);
+ writeOffset(node.fileOffset);
+ writeNonNullReference(node.targetReference);
}
@override
void visitTypedefTearOff(TypedefTearOff node) {
writeByte(Tag.TypedefTearOff);
+ enterScope(typeParameters: node.typeParameters);
writeNodeList(node.typeParameters);
writeNode(node.expression);
writeNodeList(node.typeArguments);
+ leaveScope(typeParameters: node.typeParameters);
}
@override
@@ -1712,17 +1689,6 @@
}
@override
- void visitMethodInvocation(MethodInvocation node) {
- writeByte(Tag.MethodInvocation);
- writeByte(node.flags);
- writeOffset(node.fileOffset);
- writeNode(node.receiver);
- writeName(node.name);
- writeArgumentsNode(node.arguments);
- writeNullAllowedInstanceMemberReference(node.interfaceTargetReference);
- }
-
- @override
void visitSuperMethodInvocation(SuperMethodInvocation node) {
writeByte(Tag.SuperMethodInvocation);
writeOffset(node.fileOffset);
@@ -2685,10 +2651,9 @@
}
@override
- void visitRedirectingFactoryConstructorReference(
- RedirectingFactoryConstructor node) {
+ void visitRedirectingFactoryReference(RedirectingFactory node) {
throw new UnsupportedError(
- 'serialization of RedirectingFactoryConstructor references');
+ 'serialization of RedirectingFactory references');
}
@override
@@ -2738,6 +2703,13 @@
}
@override
+ void visitRedirectingFactoryTearOffConstant(
+ RedirectingFactoryTearOffConstant node) {
+ throw new UnsupportedError(
+ 'serialization of RedirectingFactoryTearOffConstants ');
+ }
+
+ @override
void visitStaticTearOffConstantReference(StaticTearOffConstant node) {
throw new UnsupportedError(
'serialization of StaticTearOffConstant references');
@@ -2751,6 +2723,18 @@
}
@override
+ void visitRedirectingFactoryTearOffConstantReference(
+ RedirectingFactoryTearOffConstant node) {
+ throw new UnsupportedError(
+ 'serialization of RedirectingFactoryTearOffConstant references');
+ }
+
+ @override
+ void visitTypedefTearOffConstantReference(TypedefTearOffConstant node) {
+ throw new UnsupportedError('serialization of TypedefTearOffConstants ');
+ }
+
+ @override
void visitTypeLiteralConstant(TypeLiteralConstant node) {
throw new UnsupportedError('serialization of TypeLiteralConstants');
}
diff --git a/pkg/kernel/lib/binary/tag.dart b/pkg/kernel/lib/binary/tag.dart
index e5291c5..d578618 100644
--- a/pkg/kernel/lib/binary/tag.dart
+++ b/pkg/kernel/lib/binary/tag.dart
@@ -17,7 +17,7 @@
static const int Field = 4;
static const int Constructor = 5;
static const int Procedure = 6;
- static const int RedirectingFactoryConstructor = 108;
+ static const int RedirectingFactory = 108;
// Initializers
static const int InvalidInitializer = 7;
@@ -37,13 +37,10 @@
static const int InvalidExpression = 19;
static const int VariableGet = 20;
static const int VariableSet = 21;
- static const int PropertyGet = 22;
- static const int PropertySet = 23;
static const int SuperPropertyGet = 24;
static const int SuperPropertySet = 25;
static const int StaticGet = 26;
static const int StaticSet = 27;
- static const int MethodInvocation = 28;
static const int SuperMethodInvocation = 29;
static const int StaticInvocation = 30;
static const int ConstructorInvocation = 31;
@@ -78,6 +75,7 @@
static const int ConstMapLiteral = 59;
static const int ConstructorTearOff = 60;
static const int TypedefTearOff = 83;
+ static const int RedirectingFactoryTearOff = 84;
static const int SetLiteral = 109;
static const int ConstSetLiteral = 110;
@@ -125,6 +123,7 @@
static const int AssertBlock = 81;
// 82 is occupied by [BlockExpression] (expression).
// 83 is occupied by [TypedefTearOff] (expression).
+ // 84 is occupied by [RedirectingFactoryTearOff] (expression).
// Types
static const int TypedefType = 87;
@@ -141,7 +140,7 @@
static const int ConstantExpression = 106;
- /// 108 is occupied by [RedirectingFactoryConstructor] (member).
+ /// 108 is occupied by [RedirectingFactory] (member).
/// 109 is occupied by [SetLiteral] (expression).
/// 110 is occupied by [ConstSetLiteral] (expression).
/// 111 is occupied by [ListConcatenation] (expression).
@@ -177,7 +176,7 @@
/// Internal version of kernel binary format.
/// Bump it when making incompatible changes in kernel binaries.
/// Keep in sync with runtime/vm/kernel_binary.h, pkg/kernel/binary.md.
- static const int BinaryFormatVersion = 67;
+ static const int BinaryFormatVersion = 69;
}
abstract class ConstantTag {
@@ -198,6 +197,7 @@
// 13 is occupied by [SetConstant]
static const int TypedefTearOffConstant = 14;
static const int ConstructorTearOffConstant = 15;
+ static const int RedirectingFactoryTearOffConstant = 16;
}
const int sdkHashLength = 10; // Bytes, a Git "short hash".
diff --git a/pkg/kernel/lib/canonical_name.dart b/pkg/kernel/lib/canonical_name.dart
index 21eb6b3..6d7bd11 100644
--- a/pkg/kernel/lib/canonical_name.dart
+++ b/pkg/kernel/lib/canonical_name.dart
@@ -137,34 +137,34 @@
}
CanonicalName getChildFromField(Field field) {
- return getChild('@getters').getChildFromQualifiedName(field.name);
+ return getChild(gettersName).getChildFromQualifiedName(field.name);
}
CanonicalName getChildFromFieldSetter(Field field) {
- return getChild('@setters').getChildFromQualifiedName(field.name);
+ return getChild(settersName).getChildFromQualifiedName(field.name);
}
CanonicalName getChildFromConstructor(Constructor constructor) {
- return getChild('@constructors')
+ return getChild(constructorsName)
.getChildFromQualifiedName(constructor.name);
}
- CanonicalName getChildFromRedirectingFactoryConstructor(
- RedirectingFactoryConstructor redirectingFactoryConstructor) {
- return getChild('@factories')
- .getChildFromQualifiedName(redirectingFactoryConstructor.name);
+ CanonicalName getChildFromRedirectingFactory(
+ RedirectingFactory redirectingFactory) {
+ return getChild(factoriesName)
+ .getChildFromQualifiedName(redirectingFactory.name);
}
CanonicalName getChildFromFieldWithName(Name name) {
- return getChild('@getters').getChildFromQualifiedName(name);
+ return getChild(gettersName).getChildFromQualifiedName(name);
}
CanonicalName getChildFromFieldSetterWithName(Name name) {
- return getChild('@setters').getChildFromQualifiedName(name);
+ return getChild(settersName).getChildFromQualifiedName(name);
}
CanonicalName getChildFromTypedef(Typedef typedef_) {
- return getChild('@typedefs').getChild(typedef_.name);
+ return getChild(typedefsName).getChild(typedef_.name);
}
/// Take ownership of a child canonical name and its subtree.
@@ -279,14 +279,7 @@
Iterable<CanonicalName>? parentChildren = parent.childrenOrNull;
if (parentChildren != null) {
for (CanonicalName child in parentChildren) {
- if (child.name != '@methods' &&
- child.name != '@typedefs' &&
- child.name != '@fields' &&
- child.name != '@=fields' &&
- child.name != '@getters' &&
- child.name != '@setters' &&
- child.name != '@factories' &&
- child.name != '@constructors') {
+ if (!isSymbolicName(child.name)) {
bool checkReferenceNode = true;
if (child._reference == null) {
// OK for "if private: URI of library" part of "Qualified name"...
@@ -333,11 +326,46 @@
return sb.toString();
}
+ /// Symbolic name used for the [CanonicalName] node that holds all
+ /// constructors within a class.
+ static const String constructorsName = '@constructors';
+
+ /// Symbolic name used for the [CanonicalName] node that holds all factories
+ /// within a class.
+ static const String factoriesName = '@factories';
+
+ /// Symbolic name used for the [CanonicalName] node that holds all methods
+ /// within a library or a class.
+ static const String methodsName = '@methods';
+
+ /// Symbolic name used for the [CanonicalName] node that holds all getters and
+ /// readable fields within a library or class.
+ static const String gettersName = '@getters';
+
+ /// Symbolic name used for the [CanonicalName] node that holds all setters and
+ /// writable fields within a library or class.
+ static const String settersName = '@setters';
+
+ /// Symbolic name used for the [CanonicalName] node that holds all typedefs
+ /// within a library.
+ static const String typedefsName = '@typedefs';
+
+ static const Set<String> symbolicNames = {
+ constructorsName,
+ factoriesName,
+ methodsName,
+ gettersName,
+ settersName,
+ typedefsName,
+ };
+
+ static bool isSymbolicName(String name) => symbolicNames.contains(name);
+
static String getProcedureQualifier(Procedure procedure) {
- if (procedure.isGetter) return '@getters';
- if (procedure.isSetter) return '@setters';
- if (procedure.isFactory) return '@factories';
- return '@methods';
+ if (procedure.isGetter) return gettersName;
+ if (procedure.isSetter) return settersName;
+ if (procedure.isFactory) return factoriesName;
+ return methodsName;
}
/// Returns `true` if [node] is orphaned through its [reference].
diff --git a/pkg/kernel/lib/clone.dart b/pkg/kernel/lib/clone.dart
index 86e78d6..9127088 100644
--- a/pkg/kernel/lib/clone.dart
+++ b/pkg/kernel/lib/clone.dart
@@ -81,8 +81,7 @@
throw 'Cloning of fields is not implemented here';
}
- TreeNode visitRedirectingFactoryConstructor(
- RedirectingFactoryConstructor node) {
+ TreeNode visitRedirectingFactory(RedirectingFactory node) {
throw 'Cloning of redirecting factory constructors is not implemented here';
}
@@ -165,16 +164,6 @@
return new VariableSet(getVariableClone(node.variable)!, clone(node.value));
}
- visitPropertyGet(PropertyGet node) {
- return new PropertyGet.byReference(
- clone(node.receiver), node.name, node.interfaceTargetReference);
- }
-
- visitPropertySet(PropertySet node) {
- return new PropertySet.byReference(clone(node.receiver), node.name,
- clone(node.value), node.interfaceTargetReference);
- }
-
visitSuperPropertyGet(SuperPropertyGet node) {
return new SuperPropertyGet.byReference(
node.name, node.interfaceTargetReference);
@@ -193,12 +182,6 @@
return new StaticSet.byReference(node.targetReference, clone(node.value));
}
- visitMethodInvocation(MethodInvocation node) {
- return new MethodInvocation.byReference(clone(node.receiver), node.name,
- clone(node.arguments), node.interfaceTargetReference)
- ..flags = node.flags;
- }
-
visitSuperMethodInvocation(SuperMethodInvocation node) {
return new SuperMethodInvocation.byReference(
node.name, clone(node.arguments), node.interfaceTargetReference);
@@ -738,7 +721,12 @@
@override
TreeNode visitConstructorTearOff(ConstructorTearOff node) {
- return new ConstructorTearOff.byReference(node.constructorReference);
+ return new ConstructorTearOff.byReference(node.targetReference);
+ }
+
+ @override
+ TreeNode visitRedirectingFactoryTearOff(RedirectingFactoryTearOff node) {
+ return new RedirectingFactoryTearOff.byReference(node.targetReference);
}
@override
@@ -856,24 +844,18 @@
return result;
}
- RedirectingFactoryConstructor cloneRedirectingFactoryConstructor(
- RedirectingFactoryConstructor node, Reference? reference) {
+ RedirectingFactory cloneRedirectingFactory(
+ RedirectingFactory node, Reference? reference) {
final Uri? activeFileUriSaved = _activeFileUri;
_activeFileUri = node.fileUri;
- prepareTypeParameters(node.typeParameters);
- RedirectingFactoryConstructor result = new RedirectingFactoryConstructor(
- node.targetReference,
+ RedirectingFactory result = new RedirectingFactory(node.targetReference,
name: node.name,
isConst: node.isConst,
isExternal: node.isExternal,
transformerFlags: node.transformerFlags,
typeArguments: node.typeArguments.map(visitType).toList(),
- typeParameters: node.typeParameters.map(super.clone).toList(),
- positionalParameters:
- node.positionalParameters.map(super.clone).toList(),
- namedParameters: node.namedParameters.map(super.clone).toList(),
- requiredParameterCount: node.requiredParameterCount,
+ function: super.clone(node.function),
fileUri: node.fileUri,
reference: reference)
..annotations = cloneAnnotations && !node.annotations.isEmpty
diff --git a/pkg/kernel/lib/naive_type_checker.dart b/pkg/kernel/lib/naive_type_checker.dart
index d3a6638..7470718 100644
--- a/pkg/kernel/lib/naive_type_checker.dart
+++ b/pkg/kernel/lib/naive_type_checker.dart
@@ -287,7 +287,6 @@
receiver == environment.coreTypes.functionNonNullableRawType ||
receiver is FunctionType) &&
(where is InvocationExpression && where.name.text == 'call') ||
- (where is PropertyGet && where.name.text == 'call') ||
where is FunctionTearOff) {
return;
}
diff --git a/pkg/kernel/lib/src/equivalence.dart b/pkg/kernel/lib/src/equivalence.dart
new file mode 100644
index 0000000..a6667e8
--- /dev/null
+++ b/pkg/kernel/lib/src/equivalence.dart
@@ -0,0 +1,7220 @@
+// 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.
+
+// NOTE: THIS FILE IS GENERATED. DO NOT EDIT.
+//
+// Run 'dart pkg/front_end/tool/generate_ast_equivalence.dart' to update.
+
+import 'package:kernel/ast.dart';
+import 'package:kernel/src/printer.dart';
+import 'union_find.dart';
+
+part 'equivalence_helpers.dart';
+
+/// Visitor that uses a EquivalenceStrategy to compute AST node equivalence.
+///
+/// The visitor hold a current state that collects found inequivalences and
+/// current assumptions. The current state has two modes. In the asserting mode,
+/// the default, inequivalences are registered when found. In the non-asserting
+/// mode, inequivalences are _not_ registered. The latter is used to compute
+/// equivalences in sand boxed state, for instance to determine which elements
+/// to pair when checking equivalence of two sets.
+class EquivalenceVisitor implements Visitor1<bool, Node> {
+ final EquivalenceStrategy strategy;
+
+ EquivalenceVisitor({this.strategy: const EquivalenceStrategy()});
+
+ @override
+ bool defaultNode(Node node, Node other) {
+ return false;
+ }
+
+ @override
+ bool defaultTreeNode(TreeNode node, Node other) {
+ return false;
+ }
+
+ @override
+ bool visitLibrary(Library node, Node other) {
+ return strategy.checkLibrary(this, node, other);
+ }
+
+ @override
+ bool visitTypedef(Typedef node, Node other) {
+ return strategy.checkTypedef(this, node, other);
+ }
+
+ @override
+ bool visitClass(Class node, Node other) {
+ return strategy.checkClass(this, node, other);
+ }
+
+ @override
+ bool visitExtension(Extension node, Node other) {
+ return strategy.checkExtension(this, node, other);
+ }
+
+ @override
+ bool defaultMember(Member node, Node other) {
+ return false;
+ }
+
+ @override
+ bool visitField(Field node, Node other) {
+ return strategy.checkField(this, node, other);
+ }
+
+ @override
+ bool visitConstructor(Constructor node, Node other) {
+ return strategy.checkConstructor(this, node, other);
+ }
+
+ @override
+ bool visitRedirectingFactory(RedirectingFactory node, Node other) {
+ return strategy.checkRedirectingFactory(this, node, other);
+ }
+
+ @override
+ bool visitProcedure(Procedure node, Node other) {
+ return strategy.checkProcedure(this, node, other);
+ }
+
+ @override
+ bool visitLibraryDependency(LibraryDependency node, Node other) {
+ return strategy.checkLibraryDependency(this, node, other);
+ }
+
+ @override
+ bool visitLibraryPart(LibraryPart node, Node other) {
+ return strategy.checkLibraryPart(this, node, other);
+ }
+
+ @override
+ bool visitCombinator(Combinator node, Node other) {
+ return strategy.checkCombinator(this, node, other);
+ }
+
+ @override
+ bool defaultInitializer(Initializer node, Node other) {
+ return false;
+ }
+
+ @override
+ bool visitInvalidInitializer(InvalidInitializer node, Node other) {
+ return strategy.checkInvalidInitializer(this, node, other);
+ }
+
+ @override
+ bool visitFieldInitializer(FieldInitializer node, Node other) {
+ return strategy.checkFieldInitializer(this, node, other);
+ }
+
+ @override
+ bool visitSuperInitializer(SuperInitializer node, Node other) {
+ return strategy.checkSuperInitializer(this, node, other);
+ }
+
+ @override
+ bool visitRedirectingInitializer(RedirectingInitializer node, Node other) {
+ return strategy.checkRedirectingInitializer(this, node, other);
+ }
+
+ @override
+ bool visitLocalInitializer(LocalInitializer node, Node other) {
+ return strategy.checkLocalInitializer(this, node, other);
+ }
+
+ @override
+ bool visitAssertInitializer(AssertInitializer node, Node other) {
+ return strategy.checkAssertInitializer(this, node, other);
+ }
+
+ @override
+ bool visitFunctionNode(FunctionNode node, Node other) {
+ return strategy.checkFunctionNode(this, node, other);
+ }
+
+ @override
+ bool defaultExpression(Expression node, Node other) {
+ return false;
+ }
+
+ @override
+ bool visitInvalidExpression(InvalidExpression node, Node other) {
+ return strategy.checkInvalidExpression(this, node, other);
+ }
+
+ @override
+ bool visitVariableGet(VariableGet node, Node other) {
+ return strategy.checkVariableGet(this, node, other);
+ }
+
+ @override
+ bool visitVariableSet(VariableSet node, Node other) {
+ return strategy.checkVariableSet(this, node, other);
+ }
+
+ @override
+ bool visitDynamicGet(DynamicGet node, Node other) {
+ return strategy.checkDynamicGet(this, node, other);
+ }
+
+ @override
+ bool visitInstanceGet(InstanceGet node, Node other) {
+ return strategy.checkInstanceGet(this, node, other);
+ }
+
+ @override
+ bool visitFunctionTearOff(FunctionTearOff node, Node other) {
+ return strategy.checkFunctionTearOff(this, node, other);
+ }
+
+ @override
+ bool visitInstanceTearOff(InstanceTearOff node, Node other) {
+ return strategy.checkInstanceTearOff(this, node, other);
+ }
+
+ @override
+ bool visitDynamicSet(DynamicSet node, Node other) {
+ return strategy.checkDynamicSet(this, node, other);
+ }
+
+ @override
+ bool visitInstanceSet(InstanceSet node, Node other) {
+ return strategy.checkInstanceSet(this, node, other);
+ }
+
+ @override
+ bool visitSuperPropertyGet(SuperPropertyGet node, Node other) {
+ return strategy.checkSuperPropertyGet(this, node, other);
+ }
+
+ @override
+ bool visitSuperPropertySet(SuperPropertySet node, Node other) {
+ return strategy.checkSuperPropertySet(this, node, other);
+ }
+
+ @override
+ bool visitStaticGet(StaticGet node, Node other) {
+ return strategy.checkStaticGet(this, node, other);
+ }
+
+ @override
+ bool visitStaticTearOff(StaticTearOff node, Node other) {
+ return strategy.checkStaticTearOff(this, node, other);
+ }
+
+ @override
+ bool visitStaticSet(StaticSet node, Node other) {
+ return strategy.checkStaticSet(this, node, other);
+ }
+
+ @override
+ bool visitDynamicInvocation(DynamicInvocation node, Node other) {
+ return strategy.checkDynamicInvocation(this, node, other);
+ }
+
+ @override
+ bool visitInstanceInvocation(InstanceInvocation node, Node other) {
+ return strategy.checkInstanceInvocation(this, node, other);
+ }
+
+ @override
+ bool visitInstanceGetterInvocation(
+ InstanceGetterInvocation node, Node other) {
+ return strategy.checkInstanceGetterInvocation(this, node, other);
+ }
+
+ @override
+ bool visitFunctionInvocation(FunctionInvocation node, Node other) {
+ return strategy.checkFunctionInvocation(this, node, other);
+ }
+
+ @override
+ bool visitLocalFunctionInvocation(LocalFunctionInvocation node, Node other) {
+ return strategy.checkLocalFunctionInvocation(this, node, other);
+ }
+
+ @override
+ bool visitSuperMethodInvocation(SuperMethodInvocation node, Node other) {
+ return strategy.checkSuperMethodInvocation(this, node, other);
+ }
+
+ @override
+ bool visitStaticInvocation(StaticInvocation node, Node other) {
+ return strategy.checkStaticInvocation(this, node, other);
+ }
+
+ @override
+ bool visitConstructorInvocation(ConstructorInvocation node, Node other) {
+ return strategy.checkConstructorInvocation(this, node, other);
+ }
+
+ @override
+ bool visitEqualsNull(EqualsNull node, Node other) {
+ return strategy.checkEqualsNull(this, node, other);
+ }
+
+ @override
+ bool visitEqualsCall(EqualsCall node, Node other) {
+ return strategy.checkEqualsCall(this, node, other);
+ }
+
+ @override
+ bool visitInstantiation(Instantiation node, Node other) {
+ return strategy.checkInstantiation(this, node, other);
+ }
+
+ @override
+ bool visitNot(Not node, Node other) {
+ return strategy.checkNot(this, node, other);
+ }
+
+ @override
+ bool visitLogicalExpression(LogicalExpression node, Node other) {
+ return strategy.checkLogicalExpression(this, node, other);
+ }
+
+ @override
+ bool visitConditionalExpression(ConditionalExpression node, Node other) {
+ return strategy.checkConditionalExpression(this, node, other);
+ }
+
+ @override
+ bool visitStringConcatenation(StringConcatenation node, Node other) {
+ return strategy.checkStringConcatenation(this, node, other);
+ }
+
+ @override
+ bool visitListConcatenation(ListConcatenation node, Node other) {
+ return strategy.checkListConcatenation(this, node, other);
+ }
+
+ @override
+ bool visitSetConcatenation(SetConcatenation node, Node other) {
+ return strategy.checkSetConcatenation(this, node, other);
+ }
+
+ @override
+ bool visitMapConcatenation(MapConcatenation node, Node other) {
+ return strategy.checkMapConcatenation(this, node, other);
+ }
+
+ @override
+ bool visitInstanceCreation(InstanceCreation node, Node other) {
+ return strategy.checkInstanceCreation(this, node, other);
+ }
+
+ @override
+ bool visitFileUriExpression(FileUriExpression node, Node other) {
+ return strategy.checkFileUriExpression(this, node, other);
+ }
+
+ @override
+ bool visitIsExpression(IsExpression node, Node other) {
+ return strategy.checkIsExpression(this, node, other);
+ }
+
+ @override
+ bool visitAsExpression(AsExpression node, Node other) {
+ return strategy.checkAsExpression(this, node, other);
+ }
+
+ @override
+ bool visitNullCheck(NullCheck node, Node other) {
+ return strategy.checkNullCheck(this, node, other);
+ }
+
+ @override
+ bool defaultBasicLiteral(BasicLiteral node, Node other) {
+ return false;
+ }
+
+ @override
+ bool visitStringLiteral(StringLiteral node, Node other) {
+ return strategy.checkStringLiteral(this, node, other);
+ }
+
+ @override
+ bool visitIntLiteral(IntLiteral node, Node other) {
+ return strategy.checkIntLiteral(this, node, other);
+ }
+
+ @override
+ bool visitDoubleLiteral(DoubleLiteral node, Node other) {
+ return strategy.checkDoubleLiteral(this, node, other);
+ }
+
+ @override
+ bool visitBoolLiteral(BoolLiteral node, Node other) {
+ return strategy.checkBoolLiteral(this, node, other);
+ }
+
+ @override
+ bool visitNullLiteral(NullLiteral node, Node other) {
+ return strategy.checkNullLiteral(this, node, other);
+ }
+
+ @override
+ bool visitSymbolLiteral(SymbolLiteral node, Node other) {
+ return strategy.checkSymbolLiteral(this, node, other);
+ }
+
+ @override
+ bool visitTypeLiteral(TypeLiteral node, Node other) {
+ return strategy.checkTypeLiteral(this, node, other);
+ }
+
+ @override
+ bool visitThisExpression(ThisExpression node, Node other) {
+ return strategy.checkThisExpression(this, node, other);
+ }
+
+ @override
+ bool visitRethrow(Rethrow node, Node other) {
+ return strategy.checkRethrow(this, node, other);
+ }
+
+ @override
+ bool visitThrow(Throw node, Node other) {
+ return strategy.checkThrow(this, node, other);
+ }
+
+ @override
+ bool visitListLiteral(ListLiteral node, Node other) {
+ return strategy.checkListLiteral(this, node, other);
+ }
+
+ @override
+ bool visitSetLiteral(SetLiteral node, Node other) {
+ return strategy.checkSetLiteral(this, node, other);
+ }
+
+ @override
+ bool visitMapLiteral(MapLiteral node, Node other) {
+ return strategy.checkMapLiteral(this, node, other);
+ }
+
+ @override
+ bool visitAwaitExpression(AwaitExpression node, Node other) {
+ return strategy.checkAwaitExpression(this, node, other);
+ }
+
+ @override
+ bool visitFunctionExpression(FunctionExpression node, Node other) {
+ return strategy.checkFunctionExpression(this, node, other);
+ }
+
+ @override
+ bool visitConstantExpression(ConstantExpression node, Node other) {
+ return strategy.checkConstantExpression(this, node, other);
+ }
+
+ @override
+ bool visitLet(Let node, Node other) {
+ return strategy.checkLet(this, node, other);
+ }
+
+ @override
+ bool visitBlockExpression(BlockExpression node, Node other) {
+ return strategy.checkBlockExpression(this, node, other);
+ }
+
+ @override
+ bool visitLoadLibrary(LoadLibrary node, Node other) {
+ return strategy.checkLoadLibrary(this, node, other);
+ }
+
+ @override
+ bool visitCheckLibraryIsLoaded(CheckLibraryIsLoaded node, Node other) {
+ return strategy.checkCheckLibraryIsLoaded(this, node, other);
+ }
+
+ @override
+ bool visitConstructorTearOff(ConstructorTearOff node, Node other) {
+ return strategy.checkConstructorTearOff(this, node, other);
+ }
+
+ @override
+ bool visitRedirectingFactoryTearOff(
+ RedirectingFactoryTearOff node, Node other) {
+ return strategy.checkRedirectingFactoryTearOff(this, node, other);
+ }
+
+ @override
+ bool visitTypedefTearOff(TypedefTearOff node, Node other) {
+ return strategy.checkTypedefTearOff(this, node, other);
+ }
+
+ @override
+ bool visitArguments(Arguments node, Node other) {
+ return strategy.checkArguments(this, node, other);
+ }
+
+ @override
+ bool visitNamedExpression(NamedExpression node, Node other) {
+ return strategy.checkNamedExpression(this, node, other);
+ }
+
+ @override
+ bool visitMapLiteralEntry(MapLiteralEntry node, Node other) {
+ return strategy.checkMapLiteralEntry(this, node, other);
+ }
+
+ @override
+ bool defaultStatement(Statement node, Node other) {
+ return false;
+ }
+
+ @override
+ bool visitExpressionStatement(ExpressionStatement node, Node other) {
+ return strategy.checkExpressionStatement(this, node, other);
+ }
+
+ @override
+ bool visitBlock(Block node, Node other) {
+ return strategy.checkBlock(this, node, other);
+ }
+
+ @override
+ bool visitAssertBlock(AssertBlock node, Node other) {
+ return strategy.checkAssertBlock(this, node, other);
+ }
+
+ @override
+ bool visitEmptyStatement(EmptyStatement node, Node other) {
+ return strategy.checkEmptyStatement(this, node, other);
+ }
+
+ @override
+ bool visitAssertStatement(AssertStatement node, Node other) {
+ return strategy.checkAssertStatement(this, node, other);
+ }
+
+ @override
+ bool visitLabeledStatement(LabeledStatement node, Node other) {
+ return strategy.checkLabeledStatement(this, node, other);
+ }
+
+ @override
+ bool visitBreakStatement(BreakStatement node, Node other) {
+ return strategy.checkBreakStatement(this, node, other);
+ }
+
+ @override
+ bool visitWhileStatement(WhileStatement node, Node other) {
+ return strategy.checkWhileStatement(this, node, other);
+ }
+
+ @override
+ bool visitDoStatement(DoStatement node, Node other) {
+ return strategy.checkDoStatement(this, node, other);
+ }
+
+ @override
+ bool visitForStatement(ForStatement node, Node other) {
+ return strategy.checkForStatement(this, node, other);
+ }
+
+ @override
+ bool visitForInStatement(ForInStatement node, Node other) {
+ return strategy.checkForInStatement(this, node, other);
+ }
+
+ @override
+ bool visitSwitchStatement(SwitchStatement node, Node other) {
+ return strategy.checkSwitchStatement(this, node, other);
+ }
+
+ @override
+ bool visitContinueSwitchStatement(ContinueSwitchStatement node, Node other) {
+ return strategy.checkContinueSwitchStatement(this, node, other);
+ }
+
+ @override
+ bool visitIfStatement(IfStatement node, Node other) {
+ return strategy.checkIfStatement(this, node, other);
+ }
+
+ @override
+ bool visitReturnStatement(ReturnStatement node, Node other) {
+ return strategy.checkReturnStatement(this, node, other);
+ }
+
+ @override
+ bool visitTryCatch(TryCatch node, Node other) {
+ return strategy.checkTryCatch(this, node, other);
+ }
+
+ @override
+ bool visitTryFinally(TryFinally node, Node other) {
+ return strategy.checkTryFinally(this, node, other);
+ }
+
+ @override
+ bool visitYieldStatement(YieldStatement node, Node other) {
+ return strategy.checkYieldStatement(this, node, other);
+ }
+
+ @override
+ bool visitVariableDeclaration(VariableDeclaration node, Node other) {
+ return strategy.checkVariableDeclaration(this, node, other);
+ }
+
+ @override
+ bool visitFunctionDeclaration(FunctionDeclaration node, Node other) {
+ return strategy.checkFunctionDeclaration(this, node, other);
+ }
+
+ @override
+ bool visitSwitchCase(SwitchCase node, Node other) {
+ return strategy.checkSwitchCase(this, node, other);
+ }
+
+ @override
+ bool visitCatch(Catch node, Node other) {
+ return strategy.checkCatch(this, node, other);
+ }
+
+ @override
+ bool visitTypeParameter(TypeParameter node, Node other) {
+ return strategy.checkTypeParameter(this, node, other);
+ }
+
+ @override
+ bool visitComponent(Component node, Node other) {
+ return strategy.checkComponent(this, node, other);
+ }
+
+ @override
+ bool visitName(Name node, Node other) {
+ return strategy.checkName(this, node, other);
+ }
+
+ @override
+ bool defaultDartType(DartType node, Node other) {
+ return false;
+ }
+
+ @override
+ bool visitInvalidType(InvalidType node, Node other) {
+ return strategy.checkInvalidType(this, node, other);
+ }
+
+ @override
+ bool visitDynamicType(DynamicType node, Node other) {
+ return strategy.checkDynamicType(this, node, other);
+ }
+
+ @override
+ bool visitVoidType(VoidType node, Node other) {
+ return strategy.checkVoidType(this, node, other);
+ }
+
+ @override
+ bool visitNeverType(NeverType node, Node other) {
+ return strategy.checkNeverType(this, node, other);
+ }
+
+ @override
+ bool visitNullType(NullType node, Node other) {
+ return strategy.checkNullType(this, node, other);
+ }
+
+ @override
+ bool visitInterfaceType(InterfaceType node, Node other) {
+ return strategy.checkInterfaceType(this, node, other);
+ }
+
+ @override
+ bool visitFunctionType(FunctionType node, Node other) {
+ return strategy.checkFunctionType(this, node, other);
+ }
+
+ @override
+ bool visitTypedefType(TypedefType node, Node other) {
+ return strategy.checkTypedefType(this, node, other);
+ }
+
+ @override
+ bool visitFutureOrType(FutureOrType node, Node other) {
+ return strategy.checkFutureOrType(this, node, other);
+ }
+
+ @override
+ bool visitExtensionType(ExtensionType node, Node other) {
+ return strategy.checkExtensionType(this, node, other);
+ }
+
+ @override
+ bool visitTypeParameterType(TypeParameterType node, Node other) {
+ return strategy.checkTypeParameterType(this, node, other);
+ }
+
+ @override
+ bool visitNamedType(NamedType node, Node other) {
+ return strategy.checkNamedType(this, node, other);
+ }
+
+ @override
+ bool visitSupertype(Supertype node, Node other) {
+ return strategy.checkSupertype(this, node, other);
+ }
+
+ @override
+ bool defaultConstant(Constant node, Node other) {
+ return false;
+ }
+
+ @override
+ bool visitNullConstant(NullConstant node, Node other) {
+ return strategy.checkNullConstant(this, node, other);
+ }
+
+ @override
+ bool visitBoolConstant(BoolConstant node, Node other) {
+ return strategy.checkBoolConstant(this, node, other);
+ }
+
+ @override
+ bool visitIntConstant(IntConstant node, Node other) {
+ return strategy.checkIntConstant(this, node, other);
+ }
+
+ @override
+ bool visitDoubleConstant(DoubleConstant node, Node other) {
+ return strategy.checkDoubleConstant(this, node, other);
+ }
+
+ @override
+ bool visitStringConstant(StringConstant node, Node other) {
+ return strategy.checkStringConstant(this, node, other);
+ }
+
+ @override
+ bool visitSymbolConstant(SymbolConstant node, Node other) {
+ return strategy.checkSymbolConstant(this, node, other);
+ }
+
+ @override
+ bool visitMapConstant(MapConstant node, Node other) {
+ return strategy.checkMapConstant(this, node, other);
+ }
+
+ @override
+ bool visitListConstant(ListConstant node, Node other) {
+ return strategy.checkListConstant(this, node, other);
+ }
+
+ @override
+ bool visitSetConstant(SetConstant node, Node other) {
+ return strategy.checkSetConstant(this, node, other);
+ }
+
+ @override
+ bool visitInstanceConstant(InstanceConstant node, Node other) {
+ return strategy.checkInstanceConstant(this, node, other);
+ }
+
+ @override
+ bool visitInstantiationConstant(InstantiationConstant node, Node other) {
+ return strategy.checkInstantiationConstant(this, node, other);
+ }
+
+ @override
+ bool visitStaticTearOffConstant(StaticTearOffConstant node, Node other) {
+ return strategy.checkStaticTearOffConstant(this, node, other);
+ }
+
+ @override
+ bool visitConstructorTearOffConstant(
+ ConstructorTearOffConstant node, Node other) {
+ return strategy.checkConstructorTearOffConstant(this, node, other);
+ }
+
+ @override
+ bool visitRedirectingFactoryTearOffConstant(
+ RedirectingFactoryTearOffConstant node, Node other) {
+ return strategy.checkRedirectingFactoryTearOffConstant(this, node, other);
+ }
+
+ @override
+ bool visitTypedefTearOffConstant(TypedefTearOffConstant node, Node other) {
+ return strategy.checkTypedefTearOffConstant(this, node, other);
+ }
+
+ @override
+ bool visitTypeLiteralConstant(TypeLiteralConstant node, Node other) {
+ return strategy.checkTypeLiteralConstant(this, node, other);
+ }
+
+ @override
+ bool visitUnevaluatedConstant(UnevaluatedConstant node, Node other) {
+ return strategy.checkUnevaluatedConstant(this, node, other);
+ }
+
+ @override
+ bool visitTypedefReference(Typedef node, Node other) {
+ return false;
+ }
+
+ @override
+ bool visitClassReference(Class node, Node other) {
+ return false;
+ }
+
+ @override
+ bool visitExtensionReference(Extension node, Node other) {
+ return false;
+ }
+
+ @override
+ bool defaultMemberReference(Member node, Node other) {
+ return false;
+ }
+
+ @override
+ bool visitFieldReference(Field node, Node other) {
+ return false;
+ }
+
+ @override
+ bool visitConstructorReference(Constructor node, Node other) {
+ return false;
+ }
+
+ @override
+ bool visitRedirectingFactoryReference(RedirectingFactory node, Node other) {
+ return false;
+ }
+
+ @override
+ bool visitProcedureReference(Procedure node, Node other) {
+ return false;
+ }
+
+ @override
+ bool defaultConstantReference(Constant node, Node other) {
+ return false;
+ }
+
+ @override
+ bool visitNullConstantReference(NullConstant node, Node other) {
+ return false;
+ }
+
+ @override
+ bool visitBoolConstantReference(BoolConstant node, Node other) {
+ return false;
+ }
+
+ @override
+ bool visitIntConstantReference(IntConstant node, Node other) {
+ return false;
+ }
+
+ @override
+ bool visitDoubleConstantReference(DoubleConstant node, Node other) {
+ return false;
+ }
+
+ @override
+ bool visitStringConstantReference(StringConstant node, Node other) {
+ return false;
+ }
+
+ @override
+ bool visitSymbolConstantReference(SymbolConstant node, Node other) {
+ return false;
+ }
+
+ @override
+ bool visitMapConstantReference(MapConstant node, Node other) {
+ return false;
+ }
+
+ @override
+ bool visitListConstantReference(ListConstant node, Node other) {
+ return false;
+ }
+
+ @override
+ bool visitSetConstantReference(SetConstant node, Node other) {
+ return false;
+ }
+
+ @override
+ bool visitInstanceConstantReference(InstanceConstant node, Node other) {
+ return false;
+ }
+
+ @override
+ bool visitInstantiationConstantReference(
+ InstantiationConstant node, Node other) {
+ return false;
+ }
+
+ @override
+ bool visitStaticTearOffConstantReference(
+ StaticTearOffConstant node, Node other) {
+ return false;
+ }
+
+ @override
+ bool visitConstructorTearOffConstantReference(
+ ConstructorTearOffConstant node, Node other) {
+ return false;
+ }
+
+ @override
+ bool visitRedirectingFactoryTearOffConstantReference(
+ RedirectingFactoryTearOffConstant node, Node other) {
+ return false;
+ }
+
+ @override
+ bool visitTypedefTearOffConstantReference(
+ TypedefTearOffConstant node, Node other) {
+ return false;
+ }
+
+ @override
+ bool visitTypeLiteralConstantReference(TypeLiteralConstant node, Node other) {
+ return false;
+ }
+
+ @override
+ bool visitUnevaluatedConstantReference(UnevaluatedConstant node, Node other) {
+ return false;
+ }
+
+ /// Returns `true` if [a] and [b] are identical or equal.
+ bool _checkValues<T>(T? a, T? b) {
+ return identical(a, b) || a == b;
+ }
+
+ /// Returns `true` if [a] and [b] are identical or equal and registers the
+ /// inequivalence otherwise.
+ bool checkValues<T>(T? a, T? b, String propertyName) {
+ bool result = _checkValues(a, b);
+ if (!result) {
+ registerInequivalence(
+ propertyName, 'Values ${a} and ${b} are not equivalent');
+ }
+ return result;
+ }
+
+ /// Returns `true` if [a] and [b] are identical or equal. Inequivalence is
+ /// _not_ registered.
+ bool matchValues<T>(T? a, T? b) {
+ return _checkValues(a, b);
+ }
+
+ /// Returns `true` if [a] and [b] are equivalent.
+ bool _checkNodes<T extends Node>(T? a, T? b) {
+ if (identical(a, b)) return true;
+ if (a == null || b == null) {
+ return false;
+ } else {
+ return a.accept1(this, b);
+ }
+ }
+
+ /// Returns `true` if [a] and [b] are equivalent, as defined by the current
+ /// strategy, and registers the inequivalence otherwise.
+ bool checkNodes<T extends Node>(T? a, T? b, [String propertyName = '']) {
+ _checkingState.pushPropertyState(propertyName);
+ bool result = _checkNodes(a, b);
+ _checkingState.popState();
+ if (!result) {
+ registerInequivalence(
+ propertyName, 'Inequivalent nodes\n1: ${a}\n2: ${b}');
+ }
+ return result;
+ }
+
+ /// Returns `true` if [a] and [b] are identical or equal. Inequivalence is
+ /// _not_ registered.
+ bool shallowMatchNodes<T extends Node>(T? a, T? b) {
+ return _checkValues(a, b);
+ }
+
+ /// Returns `true` if [a] and [b] are equivalent, as defined by the current
+ /// strategy. Inequivalence is _not_ registered.
+ bool deepMatchNodes<T extends Node>(T? a, T? b) {
+ CheckingState oldState = _checkingState;
+ _checkingState = _checkingState.toMatchingState();
+ bool result = checkNodes(a, b);
+ _checkingState = oldState;
+ return result;
+ }
+
+ /// Returns `true` if [a] and [b] are equivalent, as defined by their
+ /// corresponding canonical names. Inequivalence is _not_ registered.
+ bool matchNamedNodes(NamedNode? a, NamedNode? b) {
+ return identical(a, b) ||
+ a == null ||
+ b == null ||
+ new ReferenceName.fromNamedNode(a) ==
+ new ReferenceName.fromNamedNode(b);
+ }
+
+ /// Returns `true` if [a] and [b] are currently assumed to be equivalent.
+ bool checkAssumedReferences(Reference? a, Reference? b) {
+ return _checkingState.checkAssumedReferences(a, b);
+ }
+
+ /// Assume that [a] and [b] are equivalent, if possible.
+ ///
+ /// Returns `true` if [a] and [b] could be assumed to be equivalent. This
+ /// would not be the case if [a] xor [b] is `null`.
+ bool assumeReferences(Reference? a, Reference? b) {
+ return _checkingState.assumeReferences(a, b);
+ }
+
+ /// Returns `true` if [a] and [b] are equivalent, as defined by their
+ /// corresponding canonical names. Inequivalence is _not_ registered.
+ bool matchReferences(Reference? a, Reference? b) {
+ return identical(a, b) ||
+ ReferenceName.fromReference(a) == ReferenceName.fromReference(b);
+ }
+
+ /// Returns `true` if [a] and [b] are equivalent, either by their
+ /// corresponding canonical names or by assumption. Inequivalence is _not_
+ /// registered.
+ bool _checkReferences(Reference? a, Reference? b) {
+ if (identical(a, b)) {
+ return true;
+ } else if (a == null || b == null) {
+ return false;
+ } else if (matchReferences(a, b)) {
+ return true;
+ } else if (checkAssumedReferences(a, b)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /// Returns `true` if [a] and [b] are equivalent, either by their
+ /// corresponding canonical names or by assumption. Inequivalence is _not_
+ /// registered.
+ bool deeplyMatchReferences(Reference? a, Reference? b) {
+ CheckingState oldState = _checkingState;
+ _checkingState = _checkingState.toMatchingState();
+ bool result = checkReferences(a, b);
+ _checkingState = oldState;
+ return result;
+ }
+
+ /// Returns `true` if [a] and [b] are equivalent, either by their
+ /// corresponding canonical names or by assumption, and registers the
+ /// inequivalence otherwise.
+ bool checkReferences(Reference? a, Reference? b, [String propertyName = '']) {
+ bool result = _checkReferences(a, b);
+ if (!result) {
+ registerInequivalence(
+ propertyName, 'Inequivalent references:\n1: ${a}\n2: ${b}');
+ }
+ return result;
+ }
+
+ /// Returns `true` if declarations [a] and [b] are currently assumed to be
+ /// equivalent.
+ bool checkAssumedDeclarations(dynamic a, dynamic b) {
+ return _checkingState.checkAssumedDeclarations(a, b);
+ }
+
+ /// Assume that [a] and [b] are equivalent, if possible.
+ ///
+ /// Returns `true` if [a] and [b] could be assumed to be equivalent. This
+ /// would not be the case if [a] is already assumed to be equivalent to
+ /// another declaration.
+ bool assumeDeclarations(dynamic a, dynamic b) {
+ return _checkingState.assumeDeclarations(a, b);
+ }
+
+ bool matchDeclarations(dynamic a, dynamic b) {
+ if (a is LabeledStatement) {
+ return b is LabeledStatement;
+ }
+ if (a is VariableDeclaration) {
+ return b is VariableDeclaration && a.name == b.name;
+ }
+ if (a is SwitchCase) {
+ return b is SwitchCase;
+ }
+ if (a is TypeParameter) {
+ return b is TypeParameter && a.name == b.name;
+ }
+ return false;
+ }
+
+ bool _checkDeclarations(dynamic a, dynamic b) {
+ if (identical(a, b)) {
+ return true;
+ } else if (a == null || b == null) {
+ return false;
+ } else if (checkAssumedDeclarations(a, b)) {
+ return true;
+ } else if (matchDeclarations(a, b)) {
+ return assumeDeclarations(a, b);
+ } else {
+ return false;
+ }
+ }
+
+ bool deepMatchDeclarations(dynamic a, dynamic b) {
+ CheckingState oldState = _checkingState;
+ _checkingState = _checkingState.toMatchingState();
+ bool result = checkDeclarations(a, b);
+ _checkingState = oldState;
+ return result;
+ }
+
+ bool checkDeclarations(dynamic a, dynamic b, [String propertyName = '']) {
+ bool result = _checkDeclarations(a, b);
+ if (!result) {
+ result = assumeDeclarations(a, b);
+ }
+ if (!result) {
+ registerInequivalence(
+ propertyName, 'Declarations ${a} and ${b} are not equivalent');
+ }
+ return result;
+ }
+
+ /// Returns `true` if lists [a] and [b] are equivalent, using
+ /// [equivalentValues] to determine element-wise equivalence.
+ ///
+ /// If run in a checking state, the [propertyName] is used for registering
+ /// inequivalences.
+ bool checkLists<E>(
+ List<E>? a, List<E>? b, bool Function(E?, E?, String) equivalentValues,
+ [String propertyName = '']) {
+ if (identical(a, b)) return true;
+ if (a == null || b == null) return false;
+ if (a.length != b.length) {
+ registerInequivalence(
+ '${propertyName}.length', 'Lists ${a} and ${b} are not equivalent');
+ return false;
+ }
+ for (int i = 0; i < a.length; i++) {
+ if (!equivalentValues(a[i], b[i], '${propertyName}[${i}]')) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /// Returns `true` if lists [a] and [b] are equivalent, using
+ /// [equivalentValues] to determine element-wise equivalence.
+ ///
+ /// Inequivalence is _not_ registered.
+ bool matchLists<E>(
+ List<E>? a, List<E>? b, bool Function(E?, E?, String) equivalentValues) {
+ CheckingState oldState = _checkingState;
+ _checkingState = _checkingState.toMatchingState();
+ bool result = checkLists(a, b, equivalentValues);
+ _checkingState = oldState;
+ return result;
+ }
+
+ /// Returns `true` if sets [a] and [b] are equivalent, using
+ /// [matchingValues] to determine which elements that should be checked for
+ /// element-wise equivalence using [equivalentValues].
+ ///
+ /// If run in a checking state, the [propertyName] is used for registering
+ /// inequivalences.
+ bool checkSets<E>(Set<E>? a, Set<E>? b, bool Function(E?, E?) matchingValues,
+ bool Function(E?, E?, String) equivalentValues,
+ [String propertyName = '']) {
+ if (identical(a, b)) return true;
+ if (a == null || b == null) return false;
+ if (a.length != b.length) {
+ registerInequivalence(
+ '${propertyName}.length', 'Sets ${a} and ${b} are not equivalent');
+ return false;
+ }
+ b = b.toSet();
+ for (E aValue in a) {
+ bool hasFoundValue = false;
+ E? foundValue;
+ for (E bValue in b) {
+ if (matchingValues(aValue, bValue)) {
+ foundValue = bValue;
+ hasFoundValue = true;
+ if (!equivalentValues(aValue, bValue, '${propertyName}[${aValue}]')) {
+ registerInequivalence('${propertyName}[${aValue}]',
+ 'Elements ${aValue} and ${bValue} are not equivalent');
+ return false;
+ }
+ break;
+ }
+ }
+ if (hasFoundValue) {
+ b.remove(foundValue);
+ } else {
+ registerInequivalence(
+ '${propertyName}[${aValue}]',
+ 'Sets ${a} and ${b} are not equivalent, no equivalent value '
+ 'found for $aValue');
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /// Returns `true` if sets [a] and [b] are equivalent, using
+ /// [matchingValues] to determine which elements that should be checked for
+ /// element-wise equivalence using [equivalentValues].
+ ///
+ /// Inequivalence is _not_registered.
+ bool matchSets<E>(Set<E>? a, Set<E>? b, bool Function(E?, E?) matchingValues,
+ bool Function(E?, E?, String) equivalentValues) {
+ CheckingState oldState = _checkingState;
+ _checkingState = _checkingState.toMatchingState();
+ bool result = checkSets(a, b, matchingValues, equivalentValues);
+ _checkingState = oldState;
+ return result;
+ }
+
+ /// Returns `true` if maps [a] and [b] are equivalent, using
+ /// [matchingKeys] to determine which entries that should be checked for
+ /// entry-wise equivalence using [equivalentKeys] and [equivalentValues] to
+ /// determine key and value equivalences, respectively.
+ ///
+ /// If run in a checking state, the [propertyName] is used for registering
+ /// inequivalences.
+ bool checkMaps<K, V>(
+ Map<K, V>? a,
+ Map<K, V>? b,
+ bool Function(K?, K?) matchingKeys,
+ bool Function(K?, K?, String) equivalentKeys,
+ bool Function(V?, V?, String) equivalentValues,
+ [String propertyName = '']) {
+ if (identical(a, b)) return true;
+ if (a == null || b == null) return false;
+ if (a.length != b.length) {
+ registerInequivalence(
+ '${propertyName}.length', 'Maps ${a} and ${b} are not equivalent');
+ return false;
+ }
+ Set<K> bKeys = b.keys.toSet();
+ for (K aKey in a.keys) {
+ bool hasFoundKey = false;
+ K? foundKey;
+ for (K bKey in bKeys) {
+ if (matchingKeys(aKey, bKey)) {
+ foundKey = bKey;
+ hasFoundKey = true;
+ if (!equivalentKeys(aKey, bKey, '${propertyName}[${aKey}]')) {
+ registerInequivalence('${propertyName}[${aKey}]',
+ 'Keys ${aKey} and ${bKey} are not equivalent');
+ return false;
+ }
+ break;
+ }
+ }
+ if (hasFoundKey) {
+ bKeys.remove(foundKey);
+ if (!equivalentValues(
+ a[aKey], b[foundKey], '${propertyName}[${aKey}]')) {
+ return false;
+ }
+ } else {
+ registerInequivalence(
+ '${propertyName}[${aKey}]',
+ 'Maps ${a} and ${b} are not equivalent, no equivalent key '
+ 'found for $aKey');
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /// Returns `true` if maps [a] and [b] are equivalent, using
+ /// [matchingKeys] to determine which entries that should be checked for
+ /// entry-wise equivalence using [equivalentKeys] and [equivalentValues] to
+ /// determine key and value equivalences, respectively.
+ ///
+ /// Inequivalence is _not_ registered.
+ bool matchMaps<K, V>(
+ Map<K, V>? a,
+ Map<K, V>? b,
+ bool Function(K?, K?) matchingKeys,
+ bool Function(K?, K?, String) equivalentKeys,
+ bool Function(V?, V?, String) equivalentValues) {
+ CheckingState oldState = _checkingState;
+ _checkingState = _checkingState.toMatchingState();
+ bool result =
+ checkMaps(a, b, matchingKeys, equivalentKeys, equivalentValues);
+ _checkingState = oldState;
+ return result;
+ }
+
+ /// The current state of the visitor.
+ ///
+ /// This holds the current assumptions, found inequivalences, and whether
+ /// inequivalences are currently registered.
+ CheckingState _checkingState = new CheckingState();
+
+ /// Runs [f] in a new state that holds all current assumptions. If
+ /// [isAsserting] is `true`, inequivalences are registered. Returns the
+ /// collected inequivalences.
+ ///
+ /// If [f] returns `false`, the returned result is marked as having
+ /// inequivalences even when non have being registered.
+ EquivalenceResult inSubState(bool Function() f, {bool isAsserting: false}) {
+ CheckingState _oldState = _checkingState;
+ _checkingState = _checkingState.createSubState(isAsserting: isAsserting);
+ bool hasInequivalences = f();
+ EquivalenceResult result =
+ _checkingState.toResult(hasInequivalences: hasInequivalences);
+ _checkingState = _oldState;
+ return result;
+ }
+
+ /// Registers that the visitor enters the property named [propertyName] and
+ /// the currently visited node.
+ void pushPropertyState(String propertyName) {
+ _checkingState.pushPropertyState(propertyName);
+ }
+
+ /// Registers that the visitor enters nodes [a] and [b].
+ void pushNodeState(Node a, Node b) {
+ _checkingState.pushNodeState(a, b);
+ }
+
+ /// Register that the visitor leave the current node or property.
+ void popState() {
+ _checkingState.popState();
+ }
+
+ /// Returns the value used as the result for property inequivalences.
+ ///
+ /// When inequivalences are currently registered, this is `true`, so that the
+ /// visitor will continue find inequivalences that are not directly related.
+ ///
+ /// An example is finding several child inequivalences on otherwise equivalent
+ /// nodes, like finding inequivalences deeply in the members of the second
+ /// library of a component even when inequivalences deeply in the members of
+ /// the first library. Had the return value been `false`, signaling that the
+ /// first libraries were inequivalent, which they technically are, given that
+ /// the contain inequivalent subnodes, the visitor would have stopped short in
+ /// checking the list of libraries, and the inequivalences in the second
+ /// library would not have been found.
+ ///
+ /// When inequivalences are _not_ currently registered, i.e. we are only
+ /// interested in the true/false value of the equivalence test, `false` is
+ /// used as the result value to stop the equivalence checking short.
+ bool get resultOnInequivalence => _checkingState.resultOnInequivalence;
+
+ /// Registers an equivalence on the [propertyName] with a detailed description
+ /// in [message].
+ void registerInequivalence(String propertyName, String message) {
+ _checkingState.registerInequivalence(propertyName, message);
+ }
+
+ /// Returns the inequivalences found by the visitor.
+ EquivalenceResult toResult() => _checkingState.toResult();
+}
+
+/// Checks [a] and [b] be for equivalence using [strategy].
+///
+/// Returns an [EquivalenceResult] containing the found inequivalences.
+EquivalenceResult checkEquivalence(Node a, Node b,
+ {EquivalenceStrategy strategy: const EquivalenceStrategy()}) {
+ EquivalenceVisitor visitor = new EquivalenceVisitor(strategy: strategy);
+ visitor.checkNodes(a, b, 'root');
+ return visitor.toResult();
+}
+
+/// Strategy used for determining equivalence of AST nodes.
+///
+/// The strategy has a method for determining the equivalence of each AST node
+/// class, and a method for determining the equivalence of each property on each
+/// AST node class.
+///
+/// The base implementation enforces a full structural equivalence.
+///
+/// Custom strategies can be made by extending this strategy and override
+/// methods where exceptions to the structural equivalence are needed.
+class EquivalenceStrategy {
+ const EquivalenceStrategy();
+
+ bool checkLibrary(EquivalenceVisitor visitor, Library? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! Library) return false;
+ if (other is! Library) return false;
+ if (!visitor.matchNamedNodes(node, other)) {
+ return false;
+ }
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkLibrary_importUri(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkLibrary_fileUri(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkLibrary_languageVersion(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkLibrary_flags(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkLibrary_name(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkLibrary_problemsAsJson(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkLibrary_annotations(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkLibrary_dependencies(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkLibrary_additionalExports(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkLibrary_parts(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkLibrary_typedefs(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkLibrary_classes(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkLibrary_extensions(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkLibrary_procedures(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkLibrary_fields(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkLibrary_reference(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkLibrary_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkTypedef(EquivalenceVisitor visitor, Typedef? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! Typedef) return false;
+ if (other is! Typedef) return false;
+ if (!visitor.matchNamedNodes(node, other)) {
+ return false;
+ }
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkTypedef_fileUri(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkTypedef_annotations(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkTypedef_name(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkTypedef_typeParameters(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkTypedef_type(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkTypedef_typeParametersOfFunctionType(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkTypedef_positionalParameters(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkTypedef_namedParameters(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkTypedef_reference(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkTypedef_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkClass(EquivalenceVisitor visitor, Class? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! Class) return false;
+ if (other is! Class) return false;
+ if (!visitor.matchNamedNodes(node, other)) {
+ return false;
+ }
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkClass_startFileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkClass_fileEndOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkClass_annotations(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkClass_name(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkClass_flags(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkClass_fileUri(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkClass_typeParameters(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkClass_supertype(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkClass_mixedInType(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkClass_implementedTypes(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkClass_fields(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkClass_constructors(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkClass_procedures(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkClass_redirectingFactories(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkClass_reference(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkClass_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkExtensionMemberDescriptor(EquivalenceVisitor visitor,
+ ExtensionMemberDescriptor? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! ExtensionMemberDescriptor) return false;
+ if (other is! ExtensionMemberDescriptor) return false;
+ bool result = true;
+ if (!checkExtensionMemberDescriptor_name(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkExtensionMemberDescriptor_kind(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkExtensionMemberDescriptor_flags(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkExtensionMemberDescriptor_member(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ return result;
+ }
+
+ bool checkExtension(
+ EquivalenceVisitor visitor, Extension? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! Extension) return false;
+ if (other is! Extension) return false;
+ if (!visitor.matchNamedNodes(node, other)) {
+ return false;
+ }
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkExtension_name(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkExtension_fileUri(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkExtension_typeParameters(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkExtension_onType(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkExtension_members(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkExtension_annotations(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkExtension_flags(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkExtension_reference(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkExtension_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkField(EquivalenceVisitor visitor, Field? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! Field) return false;
+ if (other is! Field) return false;
+ if (!visitor.matchNamedNodes(node, other)) {
+ return false;
+ }
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkField_type(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkField_flags(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkField_initializer(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkField_setterReference(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkField_fileEndOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkField_annotations(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkField_name(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkField_fileUri(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkField_transformerFlags(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkField_getterReference(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkField_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkConstructor(
+ EquivalenceVisitor visitor, Constructor? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! Constructor) return false;
+ if (other is! Constructor) return false;
+ if (!visitor.matchNamedNodes(node, other)) {
+ return false;
+ }
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkConstructor_startFileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkConstructor_flags(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkConstructor_function(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkConstructor_initializers(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkConstructor_fileEndOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkConstructor_annotations(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkConstructor_name(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkConstructor_fileUri(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkConstructor_transformerFlags(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkConstructor_reference(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkConstructor_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkRedirectingFactory(
+ EquivalenceVisitor visitor, RedirectingFactory? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! RedirectingFactory) return false;
+ if (other is! RedirectingFactory) return false;
+ if (!visitor.matchNamedNodes(node, other)) {
+ return false;
+ }
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkRedirectingFactory_flags(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkRedirectingFactory_typeArguments(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkRedirectingFactory_targetReference(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkRedirectingFactory_function(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkRedirectingFactory_fileEndOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkRedirectingFactory_annotations(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkRedirectingFactory_name(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkRedirectingFactory_fileUri(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkRedirectingFactory_transformerFlags(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkRedirectingFactory_reference(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkRedirectingFactory_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkProcedure(
+ EquivalenceVisitor visitor, Procedure? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! Procedure) return false;
+ if (other is! Procedure) return false;
+ if (!visitor.matchNamedNodes(node, other)) {
+ return false;
+ }
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkProcedure_startFileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkProcedure_kind(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkProcedure_flags(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkProcedure_function(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkProcedure_stubKind(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkProcedure_stubTargetReference(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkProcedure_fileEndOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkProcedure_annotations(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkProcedure_name(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkProcedure_fileUri(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkProcedure_transformerFlags(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkProcedure_reference(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkProcedure_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkLibraryDependency(
+ EquivalenceVisitor visitor, LibraryDependency? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! LibraryDependency) return false;
+ if (other is! LibraryDependency) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkLibraryDependency_flags(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkLibraryDependency_annotations(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkLibraryDependency_importedLibraryReference(
+ visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkLibraryDependency_name(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkLibraryDependency_combinators(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkLibraryDependency_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkLibraryPart(
+ EquivalenceVisitor visitor, LibraryPart? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! LibraryPart) return false;
+ if (other is! LibraryPart) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkLibraryPart_annotations(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkLibraryPart_partUri(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkLibraryPart_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkCombinator(
+ EquivalenceVisitor visitor, Combinator? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! Combinator) return false;
+ if (other is! Combinator) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkCombinator_isShow(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkCombinator_names(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkCombinator_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkInvalidInitializer(
+ EquivalenceVisitor visitor, InvalidInitializer? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! InvalidInitializer) return false;
+ if (other is! InvalidInitializer) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkInvalidInitializer_isSynthetic(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkInvalidInitializer_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkFieldInitializer(
+ EquivalenceVisitor visitor, FieldInitializer? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! FieldInitializer) return false;
+ if (other is! FieldInitializer) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkFieldInitializer_fieldReference(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkFieldInitializer_value(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkFieldInitializer_isSynthetic(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkFieldInitializer_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkSuperInitializer(
+ EquivalenceVisitor visitor, SuperInitializer? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! SuperInitializer) return false;
+ if (other is! SuperInitializer) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkSuperInitializer_targetReference(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkSuperInitializer_arguments(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkSuperInitializer_isSynthetic(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkSuperInitializer_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkRedirectingInitializer(
+ EquivalenceVisitor visitor, RedirectingInitializer? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! RedirectingInitializer) return false;
+ if (other is! RedirectingInitializer) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkRedirectingInitializer_targetReference(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkRedirectingInitializer_arguments(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkRedirectingInitializer_isSynthetic(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkRedirectingInitializer_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkLocalInitializer(
+ EquivalenceVisitor visitor, LocalInitializer? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! LocalInitializer) return false;
+ if (other is! LocalInitializer) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkLocalInitializer_variable(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkLocalInitializer_isSynthetic(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkLocalInitializer_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkAssertInitializer(
+ EquivalenceVisitor visitor, AssertInitializer? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! AssertInitializer) return false;
+ if (other is! AssertInitializer) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkAssertInitializer_statement(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkAssertInitializer_isSynthetic(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkAssertInitializer_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkFunctionNode(
+ EquivalenceVisitor visitor, FunctionNode? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! FunctionNode) return false;
+ if (other is! FunctionNode) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkFunctionNode_fileEndOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkFunctionNode_asyncMarker(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkFunctionNode_dartAsyncMarker(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkFunctionNode_typeParameters(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkFunctionNode_requiredParameterCount(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkFunctionNode_positionalParameters(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkFunctionNode_namedParameters(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkFunctionNode_returnType(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkFunctionNode_body(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkFunctionNode_futureValueType(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkFunctionNode_lazyBuilder(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkFunctionNode_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkInvalidExpression(
+ EquivalenceVisitor visitor, InvalidExpression? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! InvalidExpression) return false;
+ if (other is! InvalidExpression) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkInvalidExpression_message(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkInvalidExpression_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkVariableGet(
+ EquivalenceVisitor visitor, VariableGet? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! VariableGet) return false;
+ if (other is! VariableGet) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkVariableGet_variable(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkVariableGet_promotedType(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkVariableGet_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkVariableSet(
+ EquivalenceVisitor visitor, VariableSet? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! VariableSet) return false;
+ if (other is! VariableSet) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkVariableSet_variable(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkVariableSet_value(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkVariableSet_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkDynamicGet(
+ EquivalenceVisitor visitor, DynamicGet? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! DynamicGet) return false;
+ if (other is! DynamicGet) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkDynamicGet_kind(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkDynamicGet_receiver(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkDynamicGet_name(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkDynamicGet_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkInstanceGet(
+ EquivalenceVisitor visitor, InstanceGet? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! InstanceGet) return false;
+ if (other is! InstanceGet) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkInstanceGet_kind(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkInstanceGet_receiver(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkInstanceGet_name(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkInstanceGet_resultType(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkInstanceGet_interfaceTargetReference(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkInstanceGet_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkFunctionTearOff(
+ EquivalenceVisitor visitor, FunctionTearOff? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! FunctionTearOff) return false;
+ if (other is! FunctionTearOff) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkFunctionTearOff_receiver(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkFunctionTearOff_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkInstanceTearOff(
+ EquivalenceVisitor visitor, InstanceTearOff? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! InstanceTearOff) return false;
+ if (other is! InstanceTearOff) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkInstanceTearOff_kind(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkInstanceTearOff_receiver(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkInstanceTearOff_name(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkInstanceTearOff_resultType(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkInstanceTearOff_interfaceTargetReference(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkInstanceTearOff_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkDynamicSet(
+ EquivalenceVisitor visitor, DynamicSet? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! DynamicSet) return false;
+ if (other is! DynamicSet) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkDynamicSet_kind(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkDynamicSet_receiver(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkDynamicSet_name(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkDynamicSet_value(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkDynamicSet_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkInstanceSet(
+ EquivalenceVisitor visitor, InstanceSet? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! InstanceSet) return false;
+ if (other is! InstanceSet) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkInstanceSet_kind(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkInstanceSet_receiver(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkInstanceSet_name(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkInstanceSet_value(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkInstanceSet_interfaceTargetReference(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkInstanceSet_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkSuperPropertyGet(
+ EquivalenceVisitor visitor, SuperPropertyGet? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! SuperPropertyGet) return false;
+ if (other is! SuperPropertyGet) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkSuperPropertyGet_name(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkSuperPropertyGet_interfaceTargetReference(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkSuperPropertyGet_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkSuperPropertySet(
+ EquivalenceVisitor visitor, SuperPropertySet? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! SuperPropertySet) return false;
+ if (other is! SuperPropertySet) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkSuperPropertySet_name(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkSuperPropertySet_value(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkSuperPropertySet_interfaceTargetReference(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkSuperPropertySet_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkStaticGet(
+ EquivalenceVisitor visitor, StaticGet? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! StaticGet) return false;
+ if (other is! StaticGet) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkStaticGet_targetReference(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkStaticGet_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkStaticTearOff(
+ EquivalenceVisitor visitor, StaticTearOff? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! StaticTearOff) return false;
+ if (other is! StaticTearOff) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkStaticTearOff_targetReference(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkStaticTearOff_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkStaticSet(
+ EquivalenceVisitor visitor, StaticSet? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! StaticSet) return false;
+ if (other is! StaticSet) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkStaticSet_targetReference(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkStaticSet_value(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkStaticSet_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkDynamicInvocation(
+ EquivalenceVisitor visitor, DynamicInvocation? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! DynamicInvocation) return false;
+ if (other is! DynamicInvocation) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkDynamicInvocation_kind(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkDynamicInvocation_receiver(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkDynamicInvocation_name(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkDynamicInvocation_arguments(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkDynamicInvocation_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkInstanceInvocation(
+ EquivalenceVisitor visitor, InstanceInvocation? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! InstanceInvocation) return false;
+ if (other is! InstanceInvocation) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkInstanceInvocation_kind(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkInstanceInvocation_receiver(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkInstanceInvocation_name(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkInstanceInvocation_arguments(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkInstanceInvocation_flags(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkInstanceInvocation_functionType(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkInstanceInvocation_interfaceTargetReference(
+ visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkInstanceInvocation_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkInstanceGetterInvocation(EquivalenceVisitor visitor,
+ InstanceGetterInvocation? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! InstanceGetterInvocation) return false;
+ if (other is! InstanceGetterInvocation) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkInstanceGetterInvocation_kind(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkInstanceGetterInvocation_receiver(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkInstanceGetterInvocation_name(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkInstanceGetterInvocation_arguments(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkInstanceGetterInvocation_flags(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkInstanceGetterInvocation_functionType(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkInstanceGetterInvocation_interfaceTargetReference(
+ visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkInstanceGetterInvocation_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkFunctionInvocation(
+ EquivalenceVisitor visitor, FunctionInvocation? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! FunctionInvocation) return false;
+ if (other is! FunctionInvocation) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkFunctionInvocation_kind(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkFunctionInvocation_receiver(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkFunctionInvocation_arguments(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkFunctionInvocation_functionType(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkFunctionInvocation_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkLocalFunctionInvocation(EquivalenceVisitor visitor,
+ LocalFunctionInvocation? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! LocalFunctionInvocation) return false;
+ if (other is! LocalFunctionInvocation) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkLocalFunctionInvocation_variable(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkLocalFunctionInvocation_arguments(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkLocalFunctionInvocation_functionType(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkLocalFunctionInvocation_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkSuperMethodInvocation(
+ EquivalenceVisitor visitor, SuperMethodInvocation? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! SuperMethodInvocation) return false;
+ if (other is! SuperMethodInvocation) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkSuperMethodInvocation_name(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkSuperMethodInvocation_arguments(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkSuperMethodInvocation_interfaceTargetReference(
+ visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkSuperMethodInvocation_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkStaticInvocation(
+ EquivalenceVisitor visitor, StaticInvocation? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! StaticInvocation) return false;
+ if (other is! StaticInvocation) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkStaticInvocation_targetReference(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkStaticInvocation_arguments(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkStaticInvocation_isConst(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkStaticInvocation_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkConstructorInvocation(
+ EquivalenceVisitor visitor, ConstructorInvocation? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! ConstructorInvocation) return false;
+ if (other is! ConstructorInvocation) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkConstructorInvocation_targetReference(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkConstructorInvocation_arguments(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkConstructorInvocation_isConst(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkConstructorInvocation_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkEqualsNull(
+ EquivalenceVisitor visitor, EqualsNull? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! EqualsNull) return false;
+ if (other is! EqualsNull) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkEqualsNull_expression(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkEqualsNull_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkEqualsCall(
+ EquivalenceVisitor visitor, EqualsCall? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! EqualsCall) return false;
+ if (other is! EqualsCall) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkEqualsCall_left(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkEqualsCall_right(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkEqualsCall_functionType(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkEqualsCall_interfaceTargetReference(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkEqualsCall_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkInstantiation(
+ EquivalenceVisitor visitor, Instantiation? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! Instantiation) return false;
+ if (other is! Instantiation) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkInstantiation_expression(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkInstantiation_typeArguments(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkInstantiation_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkNot(EquivalenceVisitor visitor, Not? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! Not) return false;
+ if (other is! Not) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkNot_operand(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkNot_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkLogicalExpression(
+ EquivalenceVisitor visitor, LogicalExpression? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! LogicalExpression) return false;
+ if (other is! LogicalExpression) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkLogicalExpression_left(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkLogicalExpression_operatorEnum(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkLogicalExpression_right(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkLogicalExpression_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkConditionalExpression(
+ EquivalenceVisitor visitor, ConditionalExpression? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! ConditionalExpression) return false;
+ if (other is! ConditionalExpression) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkConditionalExpression_condition(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkConditionalExpression_then(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkConditionalExpression_otherwise(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkConditionalExpression_staticType(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkConditionalExpression_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkStringConcatenation(
+ EquivalenceVisitor visitor, StringConcatenation? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! StringConcatenation) return false;
+ if (other is! StringConcatenation) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkStringConcatenation_expressions(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkStringConcatenation_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkListConcatenation(
+ EquivalenceVisitor visitor, ListConcatenation? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! ListConcatenation) return false;
+ if (other is! ListConcatenation) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkListConcatenation_typeArgument(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkListConcatenation_lists(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkListConcatenation_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkSetConcatenation(
+ EquivalenceVisitor visitor, SetConcatenation? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! SetConcatenation) return false;
+ if (other is! SetConcatenation) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkSetConcatenation_typeArgument(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkSetConcatenation_sets(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkSetConcatenation_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkMapConcatenation(
+ EquivalenceVisitor visitor, MapConcatenation? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! MapConcatenation) return false;
+ if (other is! MapConcatenation) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkMapConcatenation_keyType(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkMapConcatenation_valueType(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkMapConcatenation_maps(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkMapConcatenation_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkInstanceCreation(
+ EquivalenceVisitor visitor, InstanceCreation? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! InstanceCreation) return false;
+ if (other is! InstanceCreation) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkInstanceCreation_classReference(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkInstanceCreation_typeArguments(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkInstanceCreation_fieldValues(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkInstanceCreation_asserts(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkInstanceCreation_unusedArguments(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkInstanceCreation_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkFileUriExpression(
+ EquivalenceVisitor visitor, FileUriExpression? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! FileUriExpression) return false;
+ if (other is! FileUriExpression) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkFileUriExpression_fileUri(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkFileUriExpression_expression(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkFileUriExpression_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkIsExpression(
+ EquivalenceVisitor visitor, IsExpression? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! IsExpression) return false;
+ if (other is! IsExpression) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkIsExpression_flags(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkIsExpression_operand(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkIsExpression_type(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkIsExpression_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkAsExpression(
+ EquivalenceVisitor visitor, AsExpression? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! AsExpression) return false;
+ if (other is! AsExpression) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkAsExpression_flags(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkAsExpression_operand(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkAsExpression_type(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkAsExpression_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkNullCheck(
+ EquivalenceVisitor visitor, NullCheck? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! NullCheck) return false;
+ if (other is! NullCheck) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkNullCheck_operand(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkNullCheck_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkStringLiteral(
+ EquivalenceVisitor visitor, StringLiteral? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! StringLiteral) return false;
+ if (other is! StringLiteral) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkStringLiteral_value(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkStringLiteral_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkIntLiteral(
+ EquivalenceVisitor visitor, IntLiteral? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! IntLiteral) return false;
+ if (other is! IntLiteral) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkIntLiteral_value(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkIntLiteral_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkDoubleLiteral(
+ EquivalenceVisitor visitor, DoubleLiteral? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! DoubleLiteral) return false;
+ if (other is! DoubleLiteral) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkDoubleLiteral_value(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkDoubleLiteral_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkBoolLiteral(
+ EquivalenceVisitor visitor, BoolLiteral? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! BoolLiteral) return false;
+ if (other is! BoolLiteral) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkBoolLiteral_value(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkBoolLiteral_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkNullLiteral(
+ EquivalenceVisitor visitor, NullLiteral? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! NullLiteral) return false;
+ if (other is! NullLiteral) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkNullLiteral_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkSymbolLiteral(
+ EquivalenceVisitor visitor, SymbolLiteral? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! SymbolLiteral) return false;
+ if (other is! SymbolLiteral) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkSymbolLiteral_value(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkSymbolLiteral_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkTypeLiteral(
+ EquivalenceVisitor visitor, TypeLiteral? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! TypeLiteral) return false;
+ if (other is! TypeLiteral) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkTypeLiteral_type(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkTypeLiteral_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkThisExpression(
+ EquivalenceVisitor visitor, ThisExpression? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! ThisExpression) return false;
+ if (other is! ThisExpression) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkThisExpression_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkRethrow(EquivalenceVisitor visitor, Rethrow? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! Rethrow) return false;
+ if (other is! Rethrow) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkRethrow_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkThrow(EquivalenceVisitor visitor, Throw? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! Throw) return false;
+ if (other is! Throw) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkThrow_expression(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkThrow_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkListLiteral(
+ EquivalenceVisitor visitor, ListLiteral? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! ListLiteral) return false;
+ if (other is! ListLiteral) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkListLiteral_isConst(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkListLiteral_typeArgument(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkListLiteral_expressions(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkListLiteral_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkSetLiteral(
+ EquivalenceVisitor visitor, SetLiteral? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! SetLiteral) return false;
+ if (other is! SetLiteral) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkSetLiteral_isConst(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkSetLiteral_typeArgument(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkSetLiteral_expressions(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkSetLiteral_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkMapLiteral(
+ EquivalenceVisitor visitor, MapLiteral? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! MapLiteral) return false;
+ if (other is! MapLiteral) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkMapLiteral_isConst(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkMapLiteral_keyType(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkMapLiteral_valueType(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkMapLiteral_entries(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkMapLiteral_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkAwaitExpression(
+ EquivalenceVisitor visitor, AwaitExpression? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! AwaitExpression) return false;
+ if (other is! AwaitExpression) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkAwaitExpression_operand(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkAwaitExpression_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkFunctionExpression(
+ EquivalenceVisitor visitor, FunctionExpression? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! FunctionExpression) return false;
+ if (other is! FunctionExpression) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkFunctionExpression_function(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkFunctionExpression_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkConstantExpression(
+ EquivalenceVisitor visitor, ConstantExpression? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! ConstantExpression) return false;
+ if (other is! ConstantExpression) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkConstantExpression_constant(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkConstantExpression_type(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkConstantExpression_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkLet(EquivalenceVisitor visitor, Let? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! Let) return false;
+ if (other is! Let) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkLet_variable(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkLet_body(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkLet_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkBlockExpression(
+ EquivalenceVisitor visitor, BlockExpression? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! BlockExpression) return false;
+ if (other is! BlockExpression) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkBlockExpression_body(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkBlockExpression_value(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkBlockExpression_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkLoadLibrary(
+ EquivalenceVisitor visitor, LoadLibrary? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! LoadLibrary) return false;
+ if (other is! LoadLibrary) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkLoadLibrary_import(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkLoadLibrary_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkCheckLibraryIsLoaded(
+ EquivalenceVisitor visitor, CheckLibraryIsLoaded? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! CheckLibraryIsLoaded) return false;
+ if (other is! CheckLibraryIsLoaded) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkCheckLibraryIsLoaded_import(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkCheckLibraryIsLoaded_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkConstructorTearOff(
+ EquivalenceVisitor visitor, ConstructorTearOff? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! ConstructorTearOff) return false;
+ if (other is! ConstructorTearOff) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkConstructorTearOff_targetReference(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkConstructorTearOff_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkRedirectingFactoryTearOff(EquivalenceVisitor visitor,
+ RedirectingFactoryTearOff? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! RedirectingFactoryTearOff) return false;
+ if (other is! RedirectingFactoryTearOff) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkRedirectingFactoryTearOff_targetReference(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkRedirectingFactoryTearOff_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkTypedefTearOff(
+ EquivalenceVisitor visitor, TypedefTearOff? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! TypedefTearOff) return false;
+ if (other is! TypedefTearOff) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkTypedefTearOff_typeParameters(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkTypedefTearOff_expression(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkTypedefTearOff_typeArguments(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkTypedefTearOff_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkArguments(
+ EquivalenceVisitor visitor, Arguments? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! Arguments) return false;
+ if (other is! Arguments) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkArguments_types(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkArguments_positional(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkArguments_named(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkArguments_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkNamedExpression(
+ EquivalenceVisitor visitor, NamedExpression? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! NamedExpression) return false;
+ if (other is! NamedExpression) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkNamedExpression_name(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkNamedExpression_value(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkNamedExpression_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkMapLiteralEntry(
+ EquivalenceVisitor visitor, MapLiteralEntry? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! MapLiteralEntry) return false;
+ if (other is! MapLiteralEntry) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkMapLiteralEntry_key(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkMapLiteralEntry_value(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkMapLiteralEntry_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkExpressionStatement(
+ EquivalenceVisitor visitor, ExpressionStatement? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! ExpressionStatement) return false;
+ if (other is! ExpressionStatement) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkExpressionStatement_expression(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkExpressionStatement_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkBlock(EquivalenceVisitor visitor, Block? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! Block) return false;
+ if (other is! Block) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkBlock_statements(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkBlock_fileEndOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkBlock_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkAssertBlock(
+ EquivalenceVisitor visitor, AssertBlock? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! AssertBlock) return false;
+ if (other is! AssertBlock) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkAssertBlock_statements(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkAssertBlock_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkEmptyStatement(
+ EquivalenceVisitor visitor, EmptyStatement? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! EmptyStatement) return false;
+ if (other is! EmptyStatement) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkEmptyStatement_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkAssertStatement(
+ EquivalenceVisitor visitor, AssertStatement? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! AssertStatement) return false;
+ if (other is! AssertStatement) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkAssertStatement_condition(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkAssertStatement_message(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkAssertStatement_conditionStartOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkAssertStatement_conditionEndOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkAssertStatement_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkLabeledStatement(
+ EquivalenceVisitor visitor, LabeledStatement? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! LabeledStatement) return false;
+ if (other is! LabeledStatement) return false;
+ if (!visitor.checkDeclarations(node, other, '')) {
+ return false;
+ }
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkLabeledStatement_body(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkLabeledStatement_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkBreakStatement(
+ EquivalenceVisitor visitor, BreakStatement? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! BreakStatement) return false;
+ if (other is! BreakStatement) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkBreakStatement_target(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkBreakStatement_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkWhileStatement(
+ EquivalenceVisitor visitor, WhileStatement? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! WhileStatement) return false;
+ if (other is! WhileStatement) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkWhileStatement_condition(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkWhileStatement_body(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkWhileStatement_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkDoStatement(
+ EquivalenceVisitor visitor, DoStatement? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! DoStatement) return false;
+ if (other is! DoStatement) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkDoStatement_body(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkDoStatement_condition(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkDoStatement_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkForStatement(
+ EquivalenceVisitor visitor, ForStatement? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! ForStatement) return false;
+ if (other is! ForStatement) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkForStatement_variables(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkForStatement_condition(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkForStatement_updates(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkForStatement_body(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkForStatement_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkForInStatement(
+ EquivalenceVisitor visitor, ForInStatement? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! ForInStatement) return false;
+ if (other is! ForInStatement) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkForInStatement_bodyOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkForInStatement_variable(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkForInStatement_iterable(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkForInStatement_body(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkForInStatement_isAsync(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkForInStatement_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkSwitchStatement(
+ EquivalenceVisitor visitor, SwitchStatement? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! SwitchStatement) return false;
+ if (other is! SwitchStatement) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkSwitchStatement_expression(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkSwitchStatement_cases(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkSwitchStatement_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkContinueSwitchStatement(EquivalenceVisitor visitor,
+ ContinueSwitchStatement? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! ContinueSwitchStatement) return false;
+ if (other is! ContinueSwitchStatement) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkContinueSwitchStatement_target(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkContinueSwitchStatement_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkIfStatement(
+ EquivalenceVisitor visitor, IfStatement? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! IfStatement) return false;
+ if (other is! IfStatement) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkIfStatement_condition(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkIfStatement_then(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkIfStatement_otherwise(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkIfStatement_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkReturnStatement(
+ EquivalenceVisitor visitor, ReturnStatement? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! ReturnStatement) return false;
+ if (other is! ReturnStatement) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkReturnStatement_expression(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkReturnStatement_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkTryCatch(
+ EquivalenceVisitor visitor, TryCatch? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! TryCatch) return false;
+ if (other is! TryCatch) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkTryCatch_body(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkTryCatch_catches(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkTryCatch_isSynthetic(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkTryCatch_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkTryFinally(
+ EquivalenceVisitor visitor, TryFinally? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! TryFinally) return false;
+ if (other is! TryFinally) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkTryFinally_body(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkTryFinally_finalizer(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkTryFinally_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkYieldStatement(
+ EquivalenceVisitor visitor, YieldStatement? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! YieldStatement) return false;
+ if (other is! YieldStatement) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkYieldStatement_expression(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkYieldStatement_flags(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkYieldStatement_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkVariableDeclaration(
+ EquivalenceVisitor visitor, VariableDeclaration? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! VariableDeclaration) return false;
+ if (other is! VariableDeclaration) return false;
+ if (!visitor.checkDeclarations(node, other, '')) {
+ return false;
+ }
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkVariableDeclaration_fileEqualsOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkVariableDeclaration_annotations(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkVariableDeclaration_name(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkVariableDeclaration_flags(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkVariableDeclaration_type(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkVariableDeclaration_binaryOffsetNoTag(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkVariableDeclaration_initializer(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkVariableDeclaration_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkFunctionDeclaration(
+ EquivalenceVisitor visitor, FunctionDeclaration? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! FunctionDeclaration) return false;
+ if (other is! FunctionDeclaration) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkFunctionDeclaration_variable(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkFunctionDeclaration_function(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkFunctionDeclaration_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkSwitchCase(
+ EquivalenceVisitor visitor, SwitchCase? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! SwitchCase) return false;
+ if (other is! SwitchCase) return false;
+ if (!visitor.checkDeclarations(node, other, '')) {
+ return false;
+ }
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkSwitchCase_expressions(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkSwitchCase_expressionOffsets(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkSwitchCase_body(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkSwitchCase_isDefault(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkSwitchCase_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkCatch(EquivalenceVisitor visitor, Catch? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! Catch) return false;
+ if (other is! Catch) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkCatch_guard(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkCatch_exception(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkCatch_stackTrace(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkCatch_body(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkCatch_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkTypeParameter(
+ EquivalenceVisitor visitor, TypeParameter? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! TypeParameter) return false;
+ if (other is! TypeParameter) return false;
+ if (!visitor.checkDeclarations(node, other, '')) {
+ return false;
+ }
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkTypeParameter_flags(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkTypeParameter_annotations(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkTypeParameter_name(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkTypeParameter_bound(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkTypeParameter_defaultType(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkTypeParameter_variance(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkTypeParameter_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkSource(EquivalenceVisitor visitor, Source? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! Source) return false;
+ if (other is! Source) return false;
+ bool result = true;
+ if (!checkSource_lineStarts(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkSource_source(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkSource_importUri(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkSource_fileUri(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkSource_constantCoverageConstructors(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkSource_cachedText(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ return result;
+ }
+
+ bool checkMetadataRepository(
+ EquivalenceVisitor visitor, MetadataRepository? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! MetadataRepository) return false;
+ if (other is! MetadataRepository) return false;
+ bool result = true;
+ return result;
+ }
+
+ bool checkComponent(
+ EquivalenceVisitor visitor, Component? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! Component) return false;
+ if (other is! Component) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkComponent_problemsAsJson(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkComponent_libraries(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkComponent_uriToSource(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkComponent_metadata(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkComponent_mainMethodName(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkComponent_mode(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkComponent_fileOffset(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkName(EquivalenceVisitor visitor, Name? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! Name) return false;
+ if (other is! Name) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkName_text(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkInvalidType(
+ EquivalenceVisitor visitor, InvalidType? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! InvalidType) return false;
+ if (other is! InvalidType) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ visitor.popState();
+ return result;
+ }
+
+ bool checkDynamicType(
+ EquivalenceVisitor visitor, DynamicType? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! DynamicType) return false;
+ if (other is! DynamicType) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ visitor.popState();
+ return result;
+ }
+
+ bool checkVoidType(
+ EquivalenceVisitor visitor, VoidType? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! VoidType) return false;
+ if (other is! VoidType) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ visitor.popState();
+ return result;
+ }
+
+ bool checkNeverType(
+ EquivalenceVisitor visitor, NeverType? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! NeverType) return false;
+ if (other is! NeverType) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkNeverType_declaredNullability(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkNullType(
+ EquivalenceVisitor visitor, NullType? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! NullType) return false;
+ if (other is! NullType) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ visitor.popState();
+ return result;
+ }
+
+ bool checkInterfaceType(
+ EquivalenceVisitor visitor, InterfaceType? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! InterfaceType) return false;
+ if (other is! InterfaceType) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkInterfaceType_className(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkInterfaceType_declaredNullability(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkInterfaceType_typeArguments(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkFunctionType(
+ EquivalenceVisitor visitor, FunctionType? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! FunctionType) return false;
+ if (other is! FunctionType) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkFunctionType_typeParameters(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkFunctionType_requiredParameterCount(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkFunctionType_positionalParameters(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkFunctionType_namedParameters(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkFunctionType_declaredNullability(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkFunctionType_typedefType(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkFunctionType_returnType(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkTypedefType(
+ EquivalenceVisitor visitor, TypedefType? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! TypedefType) return false;
+ if (other is! TypedefType) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkTypedefType_declaredNullability(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkTypedefType_typedefReference(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkTypedefType_typeArguments(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkFutureOrType(
+ EquivalenceVisitor visitor, FutureOrType? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! FutureOrType) return false;
+ if (other is! FutureOrType) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkFutureOrType_typeArgument(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkFutureOrType_declaredNullability(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkExtensionType(
+ EquivalenceVisitor visitor, ExtensionType? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! ExtensionType) return false;
+ if (other is! ExtensionType) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkExtensionType_extensionReference(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkExtensionType_declaredNullability(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkExtensionType_typeArguments(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkExtensionType_onType(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkTypeParameterType(
+ EquivalenceVisitor visitor, TypeParameterType? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! TypeParameterType) return false;
+ if (other is! TypeParameterType) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkTypeParameterType_declaredNullability(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkTypeParameterType_parameter(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkTypeParameterType_promotedBound(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkNamedType(
+ EquivalenceVisitor visitor, NamedType? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! NamedType) return false;
+ if (other is! NamedType) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkNamedType_name(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkNamedType_type(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkNamedType_isRequired(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkSupertype(
+ EquivalenceVisitor visitor, Supertype? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! Supertype) return false;
+ if (other is! Supertype) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkSupertype_className(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkSupertype_typeArguments(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkNullConstant(
+ EquivalenceVisitor visitor, NullConstant? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! NullConstant) return false;
+ if (other is! NullConstant) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkNullConstant_value(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkBoolConstant(
+ EquivalenceVisitor visitor, BoolConstant? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! BoolConstant) return false;
+ if (other is! BoolConstant) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkBoolConstant_value(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkIntConstant(
+ EquivalenceVisitor visitor, IntConstant? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! IntConstant) return false;
+ if (other is! IntConstant) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkIntConstant_value(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkDoubleConstant(
+ EquivalenceVisitor visitor, DoubleConstant? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! DoubleConstant) return false;
+ if (other is! DoubleConstant) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkDoubleConstant_value(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkStringConstant(
+ EquivalenceVisitor visitor, StringConstant? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! StringConstant) return false;
+ if (other is! StringConstant) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkStringConstant_value(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkSymbolConstant(
+ EquivalenceVisitor visitor, SymbolConstant? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! SymbolConstant) return false;
+ if (other is! SymbolConstant) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkSymbolConstant_name(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkSymbolConstant_libraryReference(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkConstantMapEntry(
+ EquivalenceVisitor visitor, ConstantMapEntry? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! ConstantMapEntry) return false;
+ if (other is! ConstantMapEntry) return false;
+ bool result = true;
+ if (!checkConstantMapEntry_key(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkConstantMapEntry_value(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ return result;
+ }
+
+ bool checkMapConstant(
+ EquivalenceVisitor visitor, MapConstant? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! MapConstant) return false;
+ if (other is! MapConstant) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkMapConstant_keyType(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkMapConstant_valueType(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkMapConstant_entries(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkListConstant(
+ EquivalenceVisitor visitor, ListConstant? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! ListConstant) return false;
+ if (other is! ListConstant) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkListConstant_typeArgument(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkListConstant_entries(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkSetConstant(
+ EquivalenceVisitor visitor, SetConstant? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! SetConstant) return false;
+ if (other is! SetConstant) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkSetConstant_typeArgument(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkSetConstant_entries(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkInstanceConstant(
+ EquivalenceVisitor visitor, InstanceConstant? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! InstanceConstant) return false;
+ if (other is! InstanceConstant) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkInstanceConstant_classReference(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkInstanceConstant_typeArguments(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkInstanceConstant_fieldValues(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkInstantiationConstant(
+ EquivalenceVisitor visitor, InstantiationConstant? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! InstantiationConstant) return false;
+ if (other is! InstantiationConstant) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkInstantiationConstant_tearOffConstant(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkInstantiationConstant_types(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkStaticTearOffConstant(
+ EquivalenceVisitor visitor, StaticTearOffConstant? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! StaticTearOffConstant) return false;
+ if (other is! StaticTearOffConstant) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkStaticTearOffConstant_targetReference(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkConstructorTearOffConstant(EquivalenceVisitor visitor,
+ ConstructorTearOffConstant? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! ConstructorTearOffConstant) return false;
+ if (other is! ConstructorTearOffConstant) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkConstructorTearOffConstant_targetReference(
+ visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkRedirectingFactoryTearOffConstant(EquivalenceVisitor visitor,
+ RedirectingFactoryTearOffConstant? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! RedirectingFactoryTearOffConstant) return false;
+ if (other is! RedirectingFactoryTearOffConstant) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkRedirectingFactoryTearOffConstant_targetReference(
+ visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkTypedefTearOffConstant(
+ EquivalenceVisitor visitor, TypedefTearOffConstant? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! TypedefTearOffConstant) return false;
+ if (other is! TypedefTearOffConstant) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkTypedefTearOffConstant_parameters(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkTypedefTearOffConstant_tearOffConstant(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ if (!checkTypedefTearOffConstant_types(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkTypeLiteralConstant(
+ EquivalenceVisitor visitor, TypeLiteralConstant? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! TypeLiteralConstant) return false;
+ if (other is! TypeLiteralConstant) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkTypeLiteralConstant_type(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkUnevaluatedConstant(
+ EquivalenceVisitor visitor, UnevaluatedConstant? node, Object? other) {
+ if (identical(node, other)) return true;
+ if (node is! UnevaluatedConstant) return false;
+ if (other is! UnevaluatedConstant) return false;
+ visitor.pushNodeState(node, other);
+ bool result = true;
+ if (!checkUnevaluatedConstant_expression(visitor, node, other)) {
+ result = visitor.resultOnInequivalence;
+ }
+ visitor.popState();
+ return result;
+ }
+
+ bool checkLibrary_importUri(
+ EquivalenceVisitor visitor, Library node, Library other) {
+ return visitor.checkValues(node.importUri, other.importUri, 'importUri');
+ }
+
+ bool checkLibrary_fileUri(
+ EquivalenceVisitor visitor, Library node, Library other) {
+ return visitor.checkValues(node.fileUri, other.fileUri, 'fileUri');
+ }
+
+ bool checkLibrary_languageVersion(
+ EquivalenceVisitor visitor, Library node, Library other) {
+ return visitor.checkValues(
+ node.languageVersion, other.languageVersion, 'languageVersion');
+ }
+
+ bool checkLibrary_flags(
+ EquivalenceVisitor visitor, Library node, Library other) {
+ return visitor.checkValues(node.flags, other.flags, 'flags');
+ }
+
+ bool checkLibrary_name(
+ EquivalenceVisitor visitor, Library node, Library other) {
+ return visitor.checkValues(node.name, other.name, 'name');
+ }
+
+ bool checkLibrary_problemsAsJson(
+ EquivalenceVisitor visitor, Library node, Library other) {
+ return visitor.checkLists(node.problemsAsJson, other.problemsAsJson,
+ visitor.checkValues, 'problemsAsJson');
+ }
+
+ bool checkLibrary_annotations(
+ EquivalenceVisitor visitor, Library node, Library other) {
+ return visitor.checkLists(
+ node.annotations, other.annotations, visitor.checkNodes, 'annotations');
+ }
+
+ bool checkLibrary_dependencies(
+ EquivalenceVisitor visitor, Library node, Library other) {
+ return visitor.checkLists(node.dependencies, other.dependencies,
+ visitor.checkNodes, 'dependencies');
+ }
+
+ bool checkLibrary_additionalExports(
+ EquivalenceVisitor visitor, Library node, Library other) {
+ return visitor.checkLists(node.additionalExports, other.additionalExports,
+ visitor.checkReferences, 'additionalExports');
+ }
+
+ bool checkLibrary_parts(
+ EquivalenceVisitor visitor, Library node, Library other) {
+ return visitor.checkLists(
+ node.parts, other.parts, visitor.checkNodes, 'parts');
+ }
+
+ bool checkLibrary_typedefs(
+ EquivalenceVisitor visitor, Library node, Library other) {
+ return visitor.checkLists(
+ node.typedefs, other.typedefs, visitor.checkNodes, 'typedefs');
+ }
+
+ bool checkLibrary_classes(
+ EquivalenceVisitor visitor, Library node, Library other) {
+ return visitor.checkLists(
+ node.classes, other.classes, visitor.checkNodes, 'classes');
+ }
+
+ bool checkLibrary_extensions(
+ EquivalenceVisitor visitor, Library node, Library other) {
+ return visitor.checkLists(
+ node.extensions, other.extensions, visitor.checkNodes, 'extensions');
+ }
+
+ bool checkLibrary_procedures(
+ EquivalenceVisitor visitor, Library node, Library other) {
+ return visitor.checkLists(
+ node.procedures, other.procedures, visitor.checkNodes, 'procedures');
+ }
+
+ bool checkLibrary_fields(
+ EquivalenceVisitor visitor, Library node, Library other) {
+ return visitor.checkLists(
+ node.fields, other.fields, visitor.checkNodes, 'fields');
+ }
+
+ bool checkLibrary_reference(
+ EquivalenceVisitor visitor, Library node, Library other) {
+ return visitor.checkReferences(
+ node.reference, other.reference, 'reference');
+ }
+
+ bool checkLibrary_fileOffset(
+ EquivalenceVisitor visitor, Library node, Library other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkTypedef_fileUri(
+ EquivalenceVisitor visitor, Typedef node, Typedef other) {
+ return visitor.checkValues(node.fileUri, other.fileUri, 'fileUri');
+ }
+
+ bool checkTypedef_annotations(
+ EquivalenceVisitor visitor, Typedef node, Typedef other) {
+ return visitor.checkLists(
+ node.annotations, other.annotations, visitor.checkNodes, 'annotations');
+ }
+
+ bool checkTypedef_name(
+ EquivalenceVisitor visitor, Typedef node, Typedef other) {
+ return visitor.checkValues(node.name, other.name, 'name');
+ }
+
+ bool checkTypedef_typeParameters(
+ EquivalenceVisitor visitor, Typedef node, Typedef other) {
+ return visitor.checkLists(node.typeParameters, other.typeParameters,
+ visitor.checkNodes, 'typeParameters');
+ }
+
+ bool checkTypedef_type(
+ EquivalenceVisitor visitor, Typedef node, Typedef other) {
+ return visitor.checkNodes(node.type, other.type, 'type');
+ }
+
+ bool checkTypedef_typeParametersOfFunctionType(
+ EquivalenceVisitor visitor, Typedef node, Typedef other) {
+ return visitor.checkLists(
+ node.typeParametersOfFunctionType,
+ other.typeParametersOfFunctionType,
+ visitor.checkDeclarations,
+ 'typeParametersOfFunctionType');
+ }
+
+ bool checkTypedef_positionalParameters(
+ EquivalenceVisitor visitor, Typedef node, Typedef other) {
+ return visitor.checkLists(
+ node.positionalParameters,
+ other.positionalParameters,
+ visitor.checkDeclarations,
+ 'positionalParameters');
+ }
+
+ bool checkTypedef_namedParameters(
+ EquivalenceVisitor visitor, Typedef node, Typedef other) {
+ return visitor.checkLists(node.namedParameters, other.namedParameters,
+ visitor.checkDeclarations, 'namedParameters');
+ }
+
+ bool checkTypedef_reference(
+ EquivalenceVisitor visitor, Typedef node, Typedef other) {
+ return visitor.checkReferences(
+ node.reference, other.reference, 'reference');
+ }
+
+ bool checkTypedef_fileOffset(
+ EquivalenceVisitor visitor, Typedef node, Typedef other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkClass_startFileOffset(
+ EquivalenceVisitor visitor, Class node, Class other) {
+ return visitor.checkValues(
+ node.startFileOffset, other.startFileOffset, 'startFileOffset');
+ }
+
+ bool checkClass_fileEndOffset(
+ EquivalenceVisitor visitor, Class node, Class other) {
+ return visitor.checkValues(
+ node.fileEndOffset, other.fileEndOffset, 'fileEndOffset');
+ }
+
+ bool checkClass_annotations(
+ EquivalenceVisitor visitor, Class node, Class other) {
+ return visitor.checkLists(
+ node.annotations, other.annotations, visitor.checkNodes, 'annotations');
+ }
+
+ bool checkClass_name(EquivalenceVisitor visitor, Class node, Class other) {
+ return visitor.checkValues(node.name, other.name, 'name');
+ }
+
+ bool checkClass_flags(EquivalenceVisitor visitor, Class node, Class other) {
+ return visitor.checkValues(node.flags, other.flags, 'flags');
+ }
+
+ bool checkClass_fileUri(EquivalenceVisitor visitor, Class node, Class other) {
+ return visitor.checkValues(node.fileUri, other.fileUri, 'fileUri');
+ }
+
+ bool checkClass_typeParameters(
+ EquivalenceVisitor visitor, Class node, Class other) {
+ return visitor.checkLists(node.typeParameters, other.typeParameters,
+ visitor.checkNodes, 'typeParameters');
+ }
+
+ bool checkClass_supertype(
+ EquivalenceVisitor visitor, Class node, Class other) {
+ return visitor.checkNodes(node.supertype, other.supertype, 'supertype');
+ }
+
+ bool checkClass_mixedInType(
+ EquivalenceVisitor visitor, Class node, Class other) {
+ return visitor.checkNodes(
+ node.mixedInType, other.mixedInType, 'mixedInType');
+ }
+
+ bool checkClass_implementedTypes(
+ EquivalenceVisitor visitor, Class node, Class other) {
+ return visitor.checkLists(node.implementedTypes, other.implementedTypes,
+ visitor.checkNodes, 'implementedTypes');
+ }
+
+ bool checkClass_fields(EquivalenceVisitor visitor, Class node, Class other) {
+ return visitor.checkLists(
+ node.fields, other.fields, visitor.checkNodes, 'fields');
+ }
+
+ bool checkClass_constructors(
+ EquivalenceVisitor visitor, Class node, Class other) {
+ return visitor.checkLists(node.constructors, other.constructors,
+ visitor.checkNodes, 'constructors');
+ }
+
+ bool checkClass_procedures(
+ EquivalenceVisitor visitor, Class node, Class other) {
+ return visitor.checkLists(
+ node.procedures, other.procedures, visitor.checkNodes, 'procedures');
+ }
+
+ bool checkClass_redirectingFactories(
+ EquivalenceVisitor visitor, Class node, Class other) {
+ return visitor.checkLists(node.redirectingFactories,
+ other.redirectingFactories, visitor.checkNodes, 'redirectingFactories');
+ }
+
+ bool checkClass_reference(
+ EquivalenceVisitor visitor, Class node, Class other) {
+ return visitor.checkReferences(
+ node.reference, other.reference, 'reference');
+ }
+
+ bool checkClass_fileOffset(
+ EquivalenceVisitor visitor, Class node, Class other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkExtension_name(
+ EquivalenceVisitor visitor, Extension node, Extension other) {
+ return visitor.checkValues(node.name, other.name, 'name');
+ }
+
+ bool checkExtension_fileUri(
+ EquivalenceVisitor visitor, Extension node, Extension other) {
+ return visitor.checkValues(node.fileUri, other.fileUri, 'fileUri');
+ }
+
+ bool checkExtension_typeParameters(
+ EquivalenceVisitor visitor, Extension node, Extension other) {
+ return visitor.checkLists(node.typeParameters, other.typeParameters,
+ visitor.checkNodes, 'typeParameters');
+ }
+
+ bool checkExtension_onType(
+ EquivalenceVisitor visitor, Extension node, Extension other) {
+ return visitor.checkNodes(node.onType, other.onType, 'onType');
+ }
+
+ bool checkExtensionMemberDescriptor_name(EquivalenceVisitor visitor,
+ ExtensionMemberDescriptor node, ExtensionMemberDescriptor other) {
+ return visitor.checkNodes(node.name, other.name, 'name');
+ }
+
+ bool checkExtensionMemberDescriptor_kind(EquivalenceVisitor visitor,
+ ExtensionMemberDescriptor node, ExtensionMemberDescriptor other) {
+ return visitor.checkValues(node.kind, other.kind, 'kind');
+ }
+
+ bool checkExtensionMemberDescriptor_flags(EquivalenceVisitor visitor,
+ ExtensionMemberDescriptor node, ExtensionMemberDescriptor other) {
+ return visitor.checkValues(node.flags, other.flags, 'flags');
+ }
+
+ bool checkExtensionMemberDescriptor_member(EquivalenceVisitor visitor,
+ ExtensionMemberDescriptor node, ExtensionMemberDescriptor other) {
+ return visitor.checkReferences(node.member, other.member, 'member');
+ }
+
+ bool checkExtension_members(
+ EquivalenceVisitor visitor, Extension node, Extension other) {
+ return visitor.checkLists(node.members, other.members, (a, b, _) {
+ if (identical(a, b)) return true;
+ if (a is! ExtensionMemberDescriptor) return false;
+ if (b is! ExtensionMemberDescriptor) return false;
+ return checkExtensionMemberDescriptor(visitor, a, b);
+ }, 'members');
+ }
+
+ bool checkExtension_annotations(
+ EquivalenceVisitor visitor, Extension node, Extension other) {
+ return visitor.checkLists(
+ node.annotations, other.annotations, visitor.checkNodes, 'annotations');
+ }
+
+ bool checkExtension_flags(
+ EquivalenceVisitor visitor, Extension node, Extension other) {
+ return visitor.checkValues(node.flags, other.flags, 'flags');
+ }
+
+ bool checkExtension_reference(
+ EquivalenceVisitor visitor, Extension node, Extension other) {
+ return visitor.checkReferences(
+ node.reference, other.reference, 'reference');
+ }
+
+ bool checkExtension_fileOffset(
+ EquivalenceVisitor visitor, Extension node, Extension other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkField_type(EquivalenceVisitor visitor, Field node, Field other) {
+ return visitor.checkNodes(node.type, other.type, 'type');
+ }
+
+ bool checkField_flags(EquivalenceVisitor visitor, Field node, Field other) {
+ return visitor.checkValues(node.flags, other.flags, 'flags');
+ }
+
+ bool checkField_initializer(
+ EquivalenceVisitor visitor, Field node, Field other) {
+ return visitor.checkNodes(
+ node.initializer, other.initializer, 'initializer');
+ }
+
+ bool checkField_setterReference(
+ EquivalenceVisitor visitor, Field node, Field other) {
+ return visitor.checkReferences(
+ node.setterReference, other.setterReference, 'setterReference');
+ }
+
+ bool checkField_fileEndOffset(
+ EquivalenceVisitor visitor, Field node, Field other) {
+ return visitor.checkValues(
+ node.fileEndOffset, other.fileEndOffset, 'fileEndOffset');
+ }
+
+ bool checkField_annotations(
+ EquivalenceVisitor visitor, Field node, Field other) {
+ return visitor.checkLists(
+ node.annotations, other.annotations, visitor.checkNodes, 'annotations');
+ }
+
+ bool checkField_name(EquivalenceVisitor visitor, Field node, Field other) {
+ return visitor.checkNodes(node.name, other.name, 'name');
+ }
+
+ bool checkField_fileUri(EquivalenceVisitor visitor, Field node, Field other) {
+ return visitor.checkValues(node.fileUri, other.fileUri, 'fileUri');
+ }
+
+ bool checkField_transformerFlags(
+ EquivalenceVisitor visitor, Field node, Field other) {
+ return visitor.checkValues(
+ node.transformerFlags, other.transformerFlags, 'transformerFlags');
+ }
+
+ bool checkField_getterReference(
+ EquivalenceVisitor visitor, Field node, Field other) {
+ return visitor.checkReferences(
+ node.getterReference, other.getterReference, 'getterReference');
+ }
+
+ bool checkField_fileOffset(
+ EquivalenceVisitor visitor, Field node, Field other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkConstructor_startFileOffset(
+ EquivalenceVisitor visitor, Constructor node, Constructor other) {
+ return visitor.checkValues(
+ node.startFileOffset, other.startFileOffset, 'startFileOffset');
+ }
+
+ bool checkConstructor_flags(
+ EquivalenceVisitor visitor, Constructor node, Constructor other) {
+ return visitor.checkValues(node.flags, other.flags, 'flags');
+ }
+
+ bool checkConstructor_function(
+ EquivalenceVisitor visitor, Constructor node, Constructor other) {
+ return visitor.checkNodes(node.function, other.function, 'function');
+ }
+
+ bool checkConstructor_initializers(
+ EquivalenceVisitor visitor, Constructor node, Constructor other) {
+ return visitor.checkLists(node.initializers, other.initializers,
+ visitor.checkNodes, 'initializers');
+ }
+
+ bool checkConstructor_fileEndOffset(
+ EquivalenceVisitor visitor, Constructor node, Constructor other) {
+ return visitor.checkValues(
+ node.fileEndOffset, other.fileEndOffset, 'fileEndOffset');
+ }
+
+ bool checkConstructor_annotations(
+ EquivalenceVisitor visitor, Constructor node, Constructor other) {
+ return visitor.checkLists(
+ node.annotations, other.annotations, visitor.checkNodes, 'annotations');
+ }
+
+ bool checkConstructor_name(
+ EquivalenceVisitor visitor, Constructor node, Constructor other) {
+ return visitor.checkNodes(node.name, other.name, 'name');
+ }
+
+ bool checkConstructor_fileUri(
+ EquivalenceVisitor visitor, Constructor node, Constructor other) {
+ return visitor.checkValues(node.fileUri, other.fileUri, 'fileUri');
+ }
+
+ bool checkConstructor_transformerFlags(
+ EquivalenceVisitor visitor, Constructor node, Constructor other) {
+ return visitor.checkValues(
+ node.transformerFlags, other.transformerFlags, 'transformerFlags');
+ }
+
+ bool checkConstructor_reference(
+ EquivalenceVisitor visitor, Constructor node, Constructor other) {
+ return visitor.checkReferences(
+ node.reference, other.reference, 'reference');
+ }
+
+ bool checkConstructor_fileOffset(
+ EquivalenceVisitor visitor, Constructor node, Constructor other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkRedirectingFactory_flags(EquivalenceVisitor visitor,
+ RedirectingFactory node, RedirectingFactory other) {
+ return visitor.checkValues(node.flags, other.flags, 'flags');
+ }
+
+ bool checkRedirectingFactory_typeArguments(EquivalenceVisitor visitor,
+ RedirectingFactory node, RedirectingFactory other) {
+ return visitor.checkLists(node.typeArguments, other.typeArguments,
+ visitor.checkNodes, 'typeArguments');
+ }
+
+ bool checkRedirectingFactory_targetReference(EquivalenceVisitor visitor,
+ RedirectingFactory node, RedirectingFactory other) {
+ return visitor.checkReferences(
+ node.targetReference, other.targetReference, 'targetReference');
+ }
+
+ bool checkRedirectingFactory_function(EquivalenceVisitor visitor,
+ RedirectingFactory node, RedirectingFactory other) {
+ return visitor.checkNodes(node.function, other.function, 'function');
+ }
+
+ bool checkRedirectingFactory_fileEndOffset(EquivalenceVisitor visitor,
+ RedirectingFactory node, RedirectingFactory other) {
+ return visitor.checkValues(
+ node.fileEndOffset, other.fileEndOffset, 'fileEndOffset');
+ }
+
+ bool checkRedirectingFactory_annotations(EquivalenceVisitor visitor,
+ RedirectingFactory node, RedirectingFactory other) {
+ return visitor.checkLists(
+ node.annotations, other.annotations, visitor.checkNodes, 'annotations');
+ }
+
+ bool checkRedirectingFactory_name(EquivalenceVisitor visitor,
+ RedirectingFactory node, RedirectingFactory other) {
+ return visitor.checkNodes(node.name, other.name, 'name');
+ }
+
+ bool checkRedirectingFactory_fileUri(EquivalenceVisitor visitor,
+ RedirectingFactory node, RedirectingFactory other) {
+ return visitor.checkValues(node.fileUri, other.fileUri, 'fileUri');
+ }
+
+ bool checkRedirectingFactory_transformerFlags(EquivalenceVisitor visitor,
+ RedirectingFactory node, RedirectingFactory other) {
+ return visitor.checkValues(
+ node.transformerFlags, other.transformerFlags, 'transformerFlags');
+ }
+
+ bool checkRedirectingFactory_reference(EquivalenceVisitor visitor,
+ RedirectingFactory node, RedirectingFactory other) {
+ return visitor.checkReferences(
+ node.reference, other.reference, 'reference');
+ }
+
+ bool checkRedirectingFactory_fileOffset(EquivalenceVisitor visitor,
+ RedirectingFactory node, RedirectingFactory other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkProcedure_startFileOffset(
+ EquivalenceVisitor visitor, Procedure node, Procedure other) {
+ return visitor.checkValues(
+ node.startFileOffset, other.startFileOffset, 'startFileOffset');
+ }
+
+ bool checkProcedure_kind(
+ EquivalenceVisitor visitor, Procedure node, Procedure other) {
+ return visitor.checkValues(node.kind, other.kind, 'kind');
+ }
+
+ bool checkProcedure_flags(
+ EquivalenceVisitor visitor, Procedure node, Procedure other) {
+ return visitor.checkValues(node.flags, other.flags, 'flags');
+ }
+
+ bool checkProcedure_function(
+ EquivalenceVisitor visitor, Procedure node, Procedure other) {
+ return visitor.checkNodes(node.function, other.function, 'function');
+ }
+
+ bool checkProcedure_stubKind(
+ EquivalenceVisitor visitor, Procedure node, Procedure other) {
+ return visitor.checkValues(node.stubKind, other.stubKind, 'stubKind');
+ }
+
+ bool checkProcedure_stubTargetReference(
+ EquivalenceVisitor visitor, Procedure node, Procedure other) {
+ return visitor.checkReferences(node.stubTargetReference,
+ other.stubTargetReference, 'stubTargetReference');
+ }
+
+ bool checkProcedure_fileEndOffset(
+ EquivalenceVisitor visitor, Procedure node, Procedure other) {
+ return visitor.checkValues(
+ node.fileEndOffset, other.fileEndOffset, 'fileEndOffset');
+ }
+
+ bool checkProcedure_annotations(
+ EquivalenceVisitor visitor, Procedure node, Procedure other) {
+ return visitor.checkLists(
+ node.annotations, other.annotations, visitor.checkNodes, 'annotations');
+ }
+
+ bool checkProcedure_name(
+ EquivalenceVisitor visitor, Procedure node, Procedure other) {
+ return visitor.checkNodes(node.name, other.name, 'name');
+ }
+
+ bool checkProcedure_fileUri(
+ EquivalenceVisitor visitor, Procedure node, Procedure other) {
+ return visitor.checkValues(node.fileUri, other.fileUri, 'fileUri');
+ }
+
+ bool checkProcedure_transformerFlags(
+ EquivalenceVisitor visitor, Procedure node, Procedure other) {
+ return visitor.checkValues(
+ node.transformerFlags, other.transformerFlags, 'transformerFlags');
+ }
+
+ bool checkProcedure_reference(
+ EquivalenceVisitor visitor, Procedure node, Procedure other) {
+ return visitor.checkReferences(
+ node.reference, other.reference, 'reference');
+ }
+
+ bool checkProcedure_fileOffset(
+ EquivalenceVisitor visitor, Procedure node, Procedure other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkLibraryDependency_flags(EquivalenceVisitor visitor,
+ LibraryDependency node, LibraryDependency other) {
+ return visitor.checkValues(node.flags, other.flags, 'flags');
+ }
+
+ bool checkLibraryDependency_annotations(EquivalenceVisitor visitor,
+ LibraryDependency node, LibraryDependency other) {
+ return visitor.checkLists(
+ node.annotations, other.annotations, visitor.checkNodes, 'annotations');
+ }
+
+ bool checkLibraryDependency_importedLibraryReference(
+ EquivalenceVisitor visitor,
+ LibraryDependency node,
+ LibraryDependency other) {
+ return visitor.checkReferences(node.importedLibraryReference,
+ other.importedLibraryReference, 'importedLibraryReference');
+ }
+
+ bool checkLibraryDependency_name(EquivalenceVisitor visitor,
+ LibraryDependency node, LibraryDependency other) {
+ return visitor.checkValues(node.name, other.name, 'name');
+ }
+
+ bool checkLibraryDependency_combinators(EquivalenceVisitor visitor,
+ LibraryDependency node, LibraryDependency other) {
+ return visitor.checkLists(
+ node.combinators, other.combinators, visitor.checkNodes, 'combinators');
+ }
+
+ bool checkLibraryDependency_fileOffset(EquivalenceVisitor visitor,
+ LibraryDependency node, LibraryDependency other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkLibraryPart_annotations(
+ EquivalenceVisitor visitor, LibraryPart node, LibraryPart other) {
+ return visitor.checkLists(
+ node.annotations, other.annotations, visitor.checkNodes, 'annotations');
+ }
+
+ bool checkLibraryPart_partUri(
+ EquivalenceVisitor visitor, LibraryPart node, LibraryPart other) {
+ return visitor.checkValues(node.partUri, other.partUri, 'partUri');
+ }
+
+ bool checkLibraryPart_fileOffset(
+ EquivalenceVisitor visitor, LibraryPart node, LibraryPart other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkCombinator_isShow(
+ EquivalenceVisitor visitor, Combinator node, Combinator other) {
+ return visitor.checkValues(node.isShow, other.isShow, 'isShow');
+ }
+
+ bool checkCombinator_names(
+ EquivalenceVisitor visitor, Combinator node, Combinator other) {
+ return visitor.checkLists(
+ node.names, other.names, visitor.checkValues, 'names');
+ }
+
+ bool checkCombinator_fileOffset(
+ EquivalenceVisitor visitor, Combinator node, Combinator other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkInvalidInitializer_isSynthetic(EquivalenceVisitor visitor,
+ InvalidInitializer node, InvalidInitializer other) {
+ return visitor.checkValues(
+ node.isSynthetic, other.isSynthetic, 'isSynthetic');
+ }
+
+ bool checkInvalidInitializer_fileOffset(EquivalenceVisitor visitor,
+ InvalidInitializer node, InvalidInitializer other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkFieldInitializer_fieldReference(EquivalenceVisitor visitor,
+ FieldInitializer node, FieldInitializer other) {
+ return visitor.checkReferences(
+ node.fieldReference, other.fieldReference, 'fieldReference');
+ }
+
+ bool checkFieldInitializer_value(EquivalenceVisitor visitor,
+ FieldInitializer node, FieldInitializer other) {
+ return visitor.checkNodes(node.value, other.value, 'value');
+ }
+
+ bool checkFieldInitializer_isSynthetic(EquivalenceVisitor visitor,
+ FieldInitializer node, FieldInitializer other) {
+ return visitor.checkValues(
+ node.isSynthetic, other.isSynthetic, 'isSynthetic');
+ }
+
+ bool checkFieldInitializer_fileOffset(EquivalenceVisitor visitor,
+ FieldInitializer node, FieldInitializer other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkSuperInitializer_targetReference(EquivalenceVisitor visitor,
+ SuperInitializer node, SuperInitializer other) {
+ return visitor.checkReferences(
+ node.targetReference, other.targetReference, 'targetReference');
+ }
+
+ bool checkSuperInitializer_arguments(EquivalenceVisitor visitor,
+ SuperInitializer node, SuperInitializer other) {
+ return visitor.checkNodes(node.arguments, other.arguments, 'arguments');
+ }
+
+ bool checkSuperInitializer_isSynthetic(EquivalenceVisitor visitor,
+ SuperInitializer node, SuperInitializer other) {
+ return visitor.checkValues(
+ node.isSynthetic, other.isSynthetic, 'isSynthetic');
+ }
+
+ bool checkSuperInitializer_fileOffset(EquivalenceVisitor visitor,
+ SuperInitializer node, SuperInitializer other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkRedirectingInitializer_targetReference(EquivalenceVisitor visitor,
+ RedirectingInitializer node, RedirectingInitializer other) {
+ return visitor.checkReferences(
+ node.targetReference, other.targetReference, 'targetReference');
+ }
+
+ bool checkRedirectingInitializer_arguments(EquivalenceVisitor visitor,
+ RedirectingInitializer node, RedirectingInitializer other) {
+ return visitor.checkNodes(node.arguments, other.arguments, 'arguments');
+ }
+
+ bool checkRedirectingInitializer_isSynthetic(EquivalenceVisitor visitor,
+ RedirectingInitializer node, RedirectingInitializer other) {
+ return visitor.checkValues(
+ node.isSynthetic, other.isSynthetic, 'isSynthetic');
+ }
+
+ bool checkRedirectingInitializer_fileOffset(EquivalenceVisitor visitor,
+ RedirectingInitializer node, RedirectingInitializer other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkLocalInitializer_variable(EquivalenceVisitor visitor,
+ LocalInitializer node, LocalInitializer other) {
+ return visitor.checkNodes(node.variable, other.variable, 'variable');
+ }
+
+ bool checkLocalInitializer_isSynthetic(EquivalenceVisitor visitor,
+ LocalInitializer node, LocalInitializer other) {
+ return visitor.checkValues(
+ node.isSynthetic, other.isSynthetic, 'isSynthetic');
+ }
+
+ bool checkLocalInitializer_fileOffset(EquivalenceVisitor visitor,
+ LocalInitializer node, LocalInitializer other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkAssertInitializer_statement(EquivalenceVisitor visitor,
+ AssertInitializer node, AssertInitializer other) {
+ return visitor.checkNodes(node.statement, other.statement, 'statement');
+ }
+
+ bool checkAssertInitializer_isSynthetic(EquivalenceVisitor visitor,
+ AssertInitializer node, AssertInitializer other) {
+ return visitor.checkValues(
+ node.isSynthetic, other.isSynthetic, 'isSynthetic');
+ }
+
+ bool checkAssertInitializer_fileOffset(EquivalenceVisitor visitor,
+ AssertInitializer node, AssertInitializer other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkFunctionNode_fileEndOffset(
+ EquivalenceVisitor visitor, FunctionNode node, FunctionNode other) {
+ return visitor.checkValues(
+ node.fileEndOffset, other.fileEndOffset, 'fileEndOffset');
+ }
+
+ bool checkFunctionNode_asyncMarker(
+ EquivalenceVisitor visitor, FunctionNode node, FunctionNode other) {
+ return visitor.checkValues(
+ node.asyncMarker, other.asyncMarker, 'asyncMarker');
+ }
+
+ bool checkFunctionNode_dartAsyncMarker(
+ EquivalenceVisitor visitor, FunctionNode node, FunctionNode other) {
+ return visitor.checkValues(
+ node.dartAsyncMarker, other.dartAsyncMarker, 'dartAsyncMarker');
+ }
+
+ bool checkFunctionNode_typeParameters(
+ EquivalenceVisitor visitor, FunctionNode node, FunctionNode other) {
+ return visitor.checkLists(node.typeParameters, other.typeParameters,
+ visitor.checkNodes, 'typeParameters');
+ }
+
+ bool checkFunctionNode_requiredParameterCount(
+ EquivalenceVisitor visitor, FunctionNode node, FunctionNode other) {
+ return visitor.checkValues(node.requiredParameterCount,
+ other.requiredParameterCount, 'requiredParameterCount');
+ }
+
+ bool checkFunctionNode_positionalParameters(
+ EquivalenceVisitor visitor, FunctionNode node, FunctionNode other) {
+ return visitor.checkLists(node.positionalParameters,
+ other.positionalParameters, visitor.checkNodes, 'positionalParameters');
+ }
+
+ bool checkFunctionNode_namedParameters(
+ EquivalenceVisitor visitor, FunctionNode node, FunctionNode other) {
+ return visitor.checkLists(node.namedParameters, other.namedParameters,
+ visitor.checkNodes, 'namedParameters');
+ }
+
+ bool checkFunctionNode_returnType(
+ EquivalenceVisitor visitor, FunctionNode node, FunctionNode other) {
+ return visitor.checkNodes(node.returnType, other.returnType, 'returnType');
+ }
+
+ bool checkFunctionNode_body(
+ EquivalenceVisitor visitor, FunctionNode node, FunctionNode other) {
+ return visitor.checkNodes(node.body, other.body, 'body');
+ }
+
+ bool checkFunctionNode_futureValueType(
+ EquivalenceVisitor visitor, FunctionNode node, FunctionNode other) {
+ return visitor.checkNodes(
+ node.futureValueType, other.futureValueType, 'futureValueType');
+ }
+
+ bool checkFunctionNode_lazyBuilder(
+ EquivalenceVisitor visitor, FunctionNode node, FunctionNode other) {
+ return visitor.checkValues(
+ node.lazyBuilder, other.lazyBuilder, 'lazyBuilder');
+ }
+
+ bool checkFunctionNode_fileOffset(
+ EquivalenceVisitor visitor, FunctionNode node, FunctionNode other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkInvalidExpression_message(EquivalenceVisitor visitor,
+ InvalidExpression node, InvalidExpression other) {
+ return visitor.checkValues(node.message, other.message, 'message');
+ }
+
+ bool checkInvalidExpression_fileOffset(EquivalenceVisitor visitor,
+ InvalidExpression node, InvalidExpression other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkVariableGet_variable(
+ EquivalenceVisitor visitor, VariableGet node, VariableGet other) {
+ return visitor.checkDeclarations(node.variable, other.variable, 'variable');
+ }
+
+ bool checkVariableGet_promotedType(
+ EquivalenceVisitor visitor, VariableGet node, VariableGet other) {
+ return visitor.checkNodes(
+ node.promotedType, other.promotedType, 'promotedType');
+ }
+
+ bool checkVariableGet_fileOffset(
+ EquivalenceVisitor visitor, VariableGet node, VariableGet other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkVariableSet_variable(
+ EquivalenceVisitor visitor, VariableSet node, VariableSet other) {
+ return visitor.checkDeclarations(node.variable, other.variable, 'variable');
+ }
+
+ bool checkVariableSet_value(
+ EquivalenceVisitor visitor, VariableSet node, VariableSet other) {
+ return visitor.checkNodes(node.value, other.value, 'value');
+ }
+
+ bool checkVariableSet_fileOffset(
+ EquivalenceVisitor visitor, VariableSet node, VariableSet other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkDynamicGet_kind(
+ EquivalenceVisitor visitor, DynamicGet node, DynamicGet other) {
+ return visitor.checkValues(node.kind, other.kind, 'kind');
+ }
+
+ bool checkDynamicGet_receiver(
+ EquivalenceVisitor visitor, DynamicGet node, DynamicGet other) {
+ return visitor.checkNodes(node.receiver, other.receiver, 'receiver');
+ }
+
+ bool checkDynamicGet_name(
+ EquivalenceVisitor visitor, DynamicGet node, DynamicGet other) {
+ return visitor.checkNodes(node.name, other.name, 'name');
+ }
+
+ bool checkDynamicGet_fileOffset(
+ EquivalenceVisitor visitor, DynamicGet node, DynamicGet other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkInstanceGet_kind(
+ EquivalenceVisitor visitor, InstanceGet node, InstanceGet other) {
+ return visitor.checkValues(node.kind, other.kind, 'kind');
+ }
+
+ bool checkInstanceGet_receiver(
+ EquivalenceVisitor visitor, InstanceGet node, InstanceGet other) {
+ return visitor.checkNodes(node.receiver, other.receiver, 'receiver');
+ }
+
+ bool checkInstanceGet_name(
+ EquivalenceVisitor visitor, InstanceGet node, InstanceGet other) {
+ return visitor.checkNodes(node.name, other.name, 'name');
+ }
+
+ bool checkInstanceGet_resultType(
+ EquivalenceVisitor visitor, InstanceGet node, InstanceGet other) {
+ return visitor.checkNodes(node.resultType, other.resultType, 'resultType');
+ }
+
+ bool checkInstanceGet_interfaceTargetReference(
+ EquivalenceVisitor visitor, InstanceGet node, InstanceGet other) {
+ return visitor.checkReferences(node.interfaceTargetReference,
+ other.interfaceTargetReference, 'interfaceTargetReference');
+ }
+
+ bool checkInstanceGet_fileOffset(
+ EquivalenceVisitor visitor, InstanceGet node, InstanceGet other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkFunctionTearOff_receiver(
+ EquivalenceVisitor visitor, FunctionTearOff node, FunctionTearOff other) {
+ return visitor.checkNodes(node.receiver, other.receiver, 'receiver');
+ }
+
+ bool checkFunctionTearOff_fileOffset(
+ EquivalenceVisitor visitor, FunctionTearOff node, FunctionTearOff other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkInstanceTearOff_kind(
+ EquivalenceVisitor visitor, InstanceTearOff node, InstanceTearOff other) {
+ return visitor.checkValues(node.kind, other.kind, 'kind');
+ }
+
+ bool checkInstanceTearOff_receiver(
+ EquivalenceVisitor visitor, InstanceTearOff node, InstanceTearOff other) {
+ return visitor.checkNodes(node.receiver, other.receiver, 'receiver');
+ }
+
+ bool checkInstanceTearOff_name(
+ EquivalenceVisitor visitor, InstanceTearOff node, InstanceTearOff other) {
+ return visitor.checkNodes(node.name, other.name, 'name');
+ }
+
+ bool checkInstanceTearOff_resultType(
+ EquivalenceVisitor visitor, InstanceTearOff node, InstanceTearOff other) {
+ return visitor.checkNodes(node.resultType, other.resultType, 'resultType');
+ }
+
+ bool checkInstanceTearOff_interfaceTargetReference(
+ EquivalenceVisitor visitor, InstanceTearOff node, InstanceTearOff other) {
+ return visitor.checkReferences(node.interfaceTargetReference,
+ other.interfaceTargetReference, 'interfaceTargetReference');
+ }
+
+ bool checkInstanceTearOff_fileOffset(
+ EquivalenceVisitor visitor, InstanceTearOff node, InstanceTearOff other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkDynamicSet_kind(
+ EquivalenceVisitor visitor, DynamicSet node, DynamicSet other) {
+ return visitor.checkValues(node.kind, other.kind, 'kind');
+ }
+
+ bool checkDynamicSet_receiver(
+ EquivalenceVisitor visitor, DynamicSet node, DynamicSet other) {
+ return visitor.checkNodes(node.receiver, other.receiver, 'receiver');
+ }
+
+ bool checkDynamicSet_name(
+ EquivalenceVisitor visitor, DynamicSet node, DynamicSet other) {
+ return visitor.checkNodes(node.name, other.name, 'name');
+ }
+
+ bool checkDynamicSet_value(
+ EquivalenceVisitor visitor, DynamicSet node, DynamicSet other) {
+ return visitor.checkNodes(node.value, other.value, 'value');
+ }
+
+ bool checkDynamicSet_fileOffset(
+ EquivalenceVisitor visitor, DynamicSet node, DynamicSet other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkInstanceSet_kind(
+ EquivalenceVisitor visitor, InstanceSet node, InstanceSet other) {
+ return visitor.checkValues(node.kind, other.kind, 'kind');
+ }
+
+ bool checkInstanceSet_receiver(
+ EquivalenceVisitor visitor, InstanceSet node, InstanceSet other) {
+ return visitor.checkNodes(node.receiver, other.receiver, 'receiver');
+ }
+
+ bool checkInstanceSet_name(
+ EquivalenceVisitor visitor, InstanceSet node, InstanceSet other) {
+ return visitor.checkNodes(node.name, other.name, 'name');
+ }
+
+ bool checkInstanceSet_value(
+ EquivalenceVisitor visitor, InstanceSet node, InstanceSet other) {
+ return visitor.checkNodes(node.value, other.value, 'value');
+ }
+
+ bool checkInstanceSet_interfaceTargetReference(
+ EquivalenceVisitor visitor, InstanceSet node, InstanceSet other) {
+ return visitor.checkReferences(node.interfaceTargetReference,
+ other.interfaceTargetReference, 'interfaceTargetReference');
+ }
+
+ bool checkInstanceSet_fileOffset(
+ EquivalenceVisitor visitor, InstanceSet node, InstanceSet other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkSuperPropertyGet_name(EquivalenceVisitor visitor,
+ SuperPropertyGet node, SuperPropertyGet other) {
+ return visitor.checkNodes(node.name, other.name, 'name');
+ }
+
+ bool checkSuperPropertyGet_interfaceTargetReference(
+ EquivalenceVisitor visitor,
+ SuperPropertyGet node,
+ SuperPropertyGet other) {
+ return visitor.checkReferences(node.interfaceTargetReference,
+ other.interfaceTargetReference, 'interfaceTargetReference');
+ }
+
+ bool checkSuperPropertyGet_fileOffset(EquivalenceVisitor visitor,
+ SuperPropertyGet node, SuperPropertyGet other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkSuperPropertySet_name(EquivalenceVisitor visitor,
+ SuperPropertySet node, SuperPropertySet other) {
+ return visitor.checkNodes(node.name, other.name, 'name');
+ }
+
+ bool checkSuperPropertySet_value(EquivalenceVisitor visitor,
+ SuperPropertySet node, SuperPropertySet other) {
+ return visitor.checkNodes(node.value, other.value, 'value');
+ }
+
+ bool checkSuperPropertySet_interfaceTargetReference(
+ EquivalenceVisitor visitor,
+ SuperPropertySet node,
+ SuperPropertySet other) {
+ return visitor.checkReferences(node.interfaceTargetReference,
+ other.interfaceTargetReference, 'interfaceTargetReference');
+ }
+
+ bool checkSuperPropertySet_fileOffset(EquivalenceVisitor visitor,
+ SuperPropertySet node, SuperPropertySet other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkStaticGet_targetReference(
+ EquivalenceVisitor visitor, StaticGet node, StaticGet other) {
+ return visitor.checkReferences(
+ node.targetReference, other.targetReference, 'targetReference');
+ }
+
+ bool checkStaticGet_fileOffset(
+ EquivalenceVisitor visitor, StaticGet node, StaticGet other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkStaticTearOff_targetReference(
+ EquivalenceVisitor visitor, StaticTearOff node, StaticTearOff other) {
+ return visitor.checkReferences(
+ node.targetReference, other.targetReference, 'targetReference');
+ }
+
+ bool checkStaticTearOff_fileOffset(
+ EquivalenceVisitor visitor, StaticTearOff node, StaticTearOff other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkStaticSet_targetReference(
+ EquivalenceVisitor visitor, StaticSet node, StaticSet other) {
+ return visitor.checkReferences(
+ node.targetReference, other.targetReference, 'targetReference');
+ }
+
+ bool checkStaticSet_value(
+ EquivalenceVisitor visitor, StaticSet node, StaticSet other) {
+ return visitor.checkNodes(node.value, other.value, 'value');
+ }
+
+ bool checkStaticSet_fileOffset(
+ EquivalenceVisitor visitor, StaticSet node, StaticSet other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkDynamicInvocation_kind(EquivalenceVisitor visitor,
+ DynamicInvocation node, DynamicInvocation other) {
+ return visitor.checkValues(node.kind, other.kind, 'kind');
+ }
+
+ bool checkDynamicInvocation_receiver(EquivalenceVisitor visitor,
+ DynamicInvocation node, DynamicInvocation other) {
+ return visitor.checkNodes(node.receiver, other.receiver, 'receiver');
+ }
+
+ bool checkDynamicInvocation_name(EquivalenceVisitor visitor,
+ DynamicInvocation node, DynamicInvocation other) {
+ return visitor.checkNodes(node.name, other.name, 'name');
+ }
+
+ bool checkDynamicInvocation_arguments(EquivalenceVisitor visitor,
+ DynamicInvocation node, DynamicInvocation other) {
+ return visitor.checkNodes(node.arguments, other.arguments, 'arguments');
+ }
+
+ bool checkDynamicInvocation_fileOffset(EquivalenceVisitor visitor,
+ DynamicInvocation node, DynamicInvocation other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkInstanceInvocation_kind(EquivalenceVisitor visitor,
+ InstanceInvocation node, InstanceInvocation other) {
+ return visitor.checkValues(node.kind, other.kind, 'kind');
+ }
+
+ bool checkInstanceInvocation_receiver(EquivalenceVisitor visitor,
+ InstanceInvocation node, InstanceInvocation other) {
+ return visitor.checkNodes(node.receiver, other.receiver, 'receiver');
+ }
+
+ bool checkInstanceInvocation_name(EquivalenceVisitor visitor,
+ InstanceInvocation node, InstanceInvocation other) {
+ return visitor.checkNodes(node.name, other.name, 'name');
+ }
+
+ bool checkInstanceInvocation_arguments(EquivalenceVisitor visitor,
+ InstanceInvocation node, InstanceInvocation other) {
+ return visitor.checkNodes(node.arguments, other.arguments, 'arguments');
+ }
+
+ bool checkInstanceInvocation_flags(EquivalenceVisitor visitor,
+ InstanceInvocation node, InstanceInvocation other) {
+ return visitor.checkValues(node.flags, other.flags, 'flags');
+ }
+
+ bool checkInstanceInvocation_functionType(EquivalenceVisitor visitor,
+ InstanceInvocation node, InstanceInvocation other) {
+ return visitor.checkNodes(
+ node.functionType, other.functionType, 'functionType');
+ }
+
+ bool checkInstanceInvocation_interfaceTargetReference(
+ EquivalenceVisitor visitor,
+ InstanceInvocation node,
+ InstanceInvocation other) {
+ return visitor.checkReferences(node.interfaceTargetReference,
+ other.interfaceTargetReference, 'interfaceTargetReference');
+ }
+
+ bool checkInstanceInvocation_fileOffset(EquivalenceVisitor visitor,
+ InstanceInvocation node, InstanceInvocation other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkInstanceGetterInvocation_kind(EquivalenceVisitor visitor,
+ InstanceGetterInvocation node, InstanceGetterInvocation other) {
+ return visitor.checkValues(node.kind, other.kind, 'kind');
+ }
+
+ bool checkInstanceGetterInvocation_receiver(EquivalenceVisitor visitor,
+ InstanceGetterInvocation node, InstanceGetterInvocation other) {
+ return visitor.checkNodes(node.receiver, other.receiver, 'receiver');
+ }
+
+ bool checkInstanceGetterInvocation_name(EquivalenceVisitor visitor,
+ InstanceGetterInvocation node, InstanceGetterInvocation other) {
+ return visitor.checkNodes(node.name, other.name, 'name');
+ }
+
+ bool checkInstanceGetterInvocation_arguments(EquivalenceVisitor visitor,
+ InstanceGetterInvocation node, InstanceGetterInvocation other) {
+ return visitor.checkNodes(node.arguments, other.arguments, 'arguments');
+ }
+
+ bool checkInstanceGetterInvocation_flags(EquivalenceVisitor visitor,
+ InstanceGetterInvocation node, InstanceGetterInvocation other) {
+ return visitor.checkValues(node.flags, other.flags, 'flags');
+ }
+
+ bool checkInstanceGetterInvocation_functionType(EquivalenceVisitor visitor,
+ InstanceGetterInvocation node, InstanceGetterInvocation other) {
+ return visitor.checkNodes(
+ node.functionType, other.functionType, 'functionType');
+ }
+
+ bool checkInstanceGetterInvocation_interfaceTargetReference(
+ EquivalenceVisitor visitor,
+ InstanceGetterInvocation node,
+ InstanceGetterInvocation other) {
+ return visitor.checkReferences(node.interfaceTargetReference,
+ other.interfaceTargetReference, 'interfaceTargetReference');
+ }
+
+ bool checkInstanceGetterInvocation_fileOffset(EquivalenceVisitor visitor,
+ InstanceGetterInvocation node, InstanceGetterInvocation other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkFunctionInvocation_kind(EquivalenceVisitor visitor,
+ FunctionInvocation node, FunctionInvocation other) {
+ return visitor.checkValues(node.kind, other.kind, 'kind');
+ }
+
+ bool checkFunctionInvocation_receiver(EquivalenceVisitor visitor,
+ FunctionInvocation node, FunctionInvocation other) {
+ return visitor.checkNodes(node.receiver, other.receiver, 'receiver');
+ }
+
+ bool checkFunctionInvocation_arguments(EquivalenceVisitor visitor,
+ FunctionInvocation node, FunctionInvocation other) {
+ return visitor.checkNodes(node.arguments, other.arguments, 'arguments');
+ }
+
+ bool checkFunctionInvocation_functionType(EquivalenceVisitor visitor,
+ FunctionInvocation node, FunctionInvocation other) {
+ return visitor.checkNodes(
+ node.functionType, other.functionType, 'functionType');
+ }
+
+ bool checkFunctionInvocation_fileOffset(EquivalenceVisitor visitor,
+ FunctionInvocation node, FunctionInvocation other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkLocalFunctionInvocation_variable(EquivalenceVisitor visitor,
+ LocalFunctionInvocation node, LocalFunctionInvocation other) {
+ return visitor.checkDeclarations(node.variable, other.variable, 'variable');
+ }
+
+ bool checkLocalFunctionInvocation_arguments(EquivalenceVisitor visitor,
+ LocalFunctionInvocation node, LocalFunctionInvocation other) {
+ return visitor.checkNodes(node.arguments, other.arguments, 'arguments');
+ }
+
+ bool checkLocalFunctionInvocation_functionType(EquivalenceVisitor visitor,
+ LocalFunctionInvocation node, LocalFunctionInvocation other) {
+ return visitor.checkNodes(
+ node.functionType, other.functionType, 'functionType');
+ }
+
+ bool checkLocalFunctionInvocation_fileOffset(EquivalenceVisitor visitor,
+ LocalFunctionInvocation node, LocalFunctionInvocation other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkSuperMethodInvocation_name(EquivalenceVisitor visitor,
+ SuperMethodInvocation node, SuperMethodInvocation other) {
+ return visitor.checkNodes(node.name, other.name, 'name');
+ }
+
+ bool checkSuperMethodInvocation_arguments(EquivalenceVisitor visitor,
+ SuperMethodInvocation node, SuperMethodInvocation other) {
+ return visitor.checkNodes(node.arguments, other.arguments, 'arguments');
+ }
+
+ bool checkSuperMethodInvocation_interfaceTargetReference(
+ EquivalenceVisitor visitor,
+ SuperMethodInvocation node,
+ SuperMethodInvocation other) {
+ return visitor.checkReferences(node.interfaceTargetReference,
+ other.interfaceTargetReference, 'interfaceTargetReference');
+ }
+
+ bool checkSuperMethodInvocation_fileOffset(EquivalenceVisitor visitor,
+ SuperMethodInvocation node, SuperMethodInvocation other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkStaticInvocation_targetReference(EquivalenceVisitor visitor,
+ StaticInvocation node, StaticInvocation other) {
+ return visitor.checkReferences(
+ node.targetReference, other.targetReference, 'targetReference');
+ }
+
+ bool checkStaticInvocation_arguments(EquivalenceVisitor visitor,
+ StaticInvocation node, StaticInvocation other) {
+ return visitor.checkNodes(node.arguments, other.arguments, 'arguments');
+ }
+
+ bool checkStaticInvocation_isConst(EquivalenceVisitor visitor,
+ StaticInvocation node, StaticInvocation other) {
+ return visitor.checkValues(node.isConst, other.isConst, 'isConst');
+ }
+
+ bool checkStaticInvocation_fileOffset(EquivalenceVisitor visitor,
+ StaticInvocation node, StaticInvocation other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkConstructorInvocation_targetReference(EquivalenceVisitor visitor,
+ ConstructorInvocation node, ConstructorInvocation other) {
+ return visitor.checkReferences(
+ node.targetReference, other.targetReference, 'targetReference');
+ }
+
+ bool checkConstructorInvocation_arguments(EquivalenceVisitor visitor,
+ ConstructorInvocation node, ConstructorInvocation other) {
+ return visitor.checkNodes(node.arguments, other.arguments, 'arguments');
+ }
+
+ bool checkConstructorInvocation_isConst(EquivalenceVisitor visitor,
+ ConstructorInvocation node, ConstructorInvocation other) {
+ return visitor.checkValues(node.isConst, other.isConst, 'isConst');
+ }
+
+ bool checkConstructorInvocation_fileOffset(EquivalenceVisitor visitor,
+ ConstructorInvocation node, ConstructorInvocation other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkEqualsNull_expression(
+ EquivalenceVisitor visitor, EqualsNull node, EqualsNull other) {
+ return visitor.checkNodes(node.expression, other.expression, 'expression');
+ }
+
+ bool checkEqualsNull_fileOffset(
+ EquivalenceVisitor visitor, EqualsNull node, EqualsNull other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkEqualsCall_left(
+ EquivalenceVisitor visitor, EqualsCall node, EqualsCall other) {
+ return visitor.checkNodes(node.left, other.left, 'left');
+ }
+
+ bool checkEqualsCall_right(
+ EquivalenceVisitor visitor, EqualsCall node, EqualsCall other) {
+ return visitor.checkNodes(node.right, other.right, 'right');
+ }
+
+ bool checkEqualsCall_functionType(
+ EquivalenceVisitor visitor, EqualsCall node, EqualsCall other) {
+ return visitor.checkNodes(
+ node.functionType, other.functionType, 'functionType');
+ }
+
+ bool checkEqualsCall_interfaceTargetReference(
+ EquivalenceVisitor visitor, EqualsCall node, EqualsCall other) {
+ return visitor.checkReferences(node.interfaceTargetReference,
+ other.interfaceTargetReference, 'interfaceTargetReference');
+ }
+
+ bool checkEqualsCall_fileOffset(
+ EquivalenceVisitor visitor, EqualsCall node, EqualsCall other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkInstantiation_expression(
+ EquivalenceVisitor visitor, Instantiation node, Instantiation other) {
+ return visitor.checkNodes(node.expression, other.expression, 'expression');
+ }
+
+ bool checkInstantiation_typeArguments(
+ EquivalenceVisitor visitor, Instantiation node, Instantiation other) {
+ return visitor.checkLists(node.typeArguments, other.typeArguments,
+ visitor.checkNodes, 'typeArguments');
+ }
+
+ bool checkInstantiation_fileOffset(
+ EquivalenceVisitor visitor, Instantiation node, Instantiation other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkNot_operand(EquivalenceVisitor visitor, Not node, Not other) {
+ return visitor.checkNodes(node.operand, other.operand, 'operand');
+ }
+
+ bool checkNot_fileOffset(EquivalenceVisitor visitor, Not node, Not other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkLogicalExpression_left(EquivalenceVisitor visitor,
+ LogicalExpression node, LogicalExpression other) {
+ return visitor.checkNodes(node.left, other.left, 'left');
+ }
+
+ bool checkLogicalExpression_operatorEnum(EquivalenceVisitor visitor,
+ LogicalExpression node, LogicalExpression other) {
+ return visitor.checkValues(
+ node.operatorEnum, other.operatorEnum, 'operatorEnum');
+ }
+
+ bool checkLogicalExpression_right(EquivalenceVisitor visitor,
+ LogicalExpression node, LogicalExpression other) {
+ return visitor.checkNodes(node.right, other.right, 'right');
+ }
+
+ bool checkLogicalExpression_fileOffset(EquivalenceVisitor visitor,
+ LogicalExpression node, LogicalExpression other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkConditionalExpression_condition(EquivalenceVisitor visitor,
+ ConditionalExpression node, ConditionalExpression other) {
+ return visitor.checkNodes(node.condition, other.condition, 'condition');
+ }
+
+ bool checkConditionalExpression_then(EquivalenceVisitor visitor,
+ ConditionalExpression node, ConditionalExpression other) {
+ return visitor.checkNodes(node.then, other.then, 'then');
+ }
+
+ bool checkConditionalExpression_otherwise(EquivalenceVisitor visitor,
+ ConditionalExpression node, ConditionalExpression other) {
+ return visitor.checkNodes(node.otherwise, other.otherwise, 'otherwise');
+ }
+
+ bool checkConditionalExpression_staticType(EquivalenceVisitor visitor,
+ ConditionalExpression node, ConditionalExpression other) {
+ return visitor.checkNodes(node.staticType, other.staticType, 'staticType');
+ }
+
+ bool checkConditionalExpression_fileOffset(EquivalenceVisitor visitor,
+ ConditionalExpression node, ConditionalExpression other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkStringConcatenation_expressions(EquivalenceVisitor visitor,
+ StringConcatenation node, StringConcatenation other) {
+ return visitor.checkLists(
+ node.expressions, other.expressions, visitor.checkNodes, 'expressions');
+ }
+
+ bool checkStringConcatenation_fileOffset(EquivalenceVisitor visitor,
+ StringConcatenation node, StringConcatenation other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkListConcatenation_typeArgument(EquivalenceVisitor visitor,
+ ListConcatenation node, ListConcatenation other) {
+ return visitor.checkNodes(
+ node.typeArgument, other.typeArgument, 'typeArgument');
+ }
+
+ bool checkListConcatenation_lists(EquivalenceVisitor visitor,
+ ListConcatenation node, ListConcatenation other) {
+ return visitor.checkLists(
+ node.lists, other.lists, visitor.checkNodes, 'lists');
+ }
+
+ bool checkListConcatenation_fileOffset(EquivalenceVisitor visitor,
+ ListConcatenation node, ListConcatenation other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkSetConcatenation_typeArgument(EquivalenceVisitor visitor,
+ SetConcatenation node, SetConcatenation other) {
+ return visitor.checkNodes(
+ node.typeArgument, other.typeArgument, 'typeArgument');
+ }
+
+ bool checkSetConcatenation_sets(EquivalenceVisitor visitor,
+ SetConcatenation node, SetConcatenation other) {
+ return visitor.checkLists(
+ node.sets, other.sets, visitor.checkNodes, 'sets');
+ }
+
+ bool checkSetConcatenation_fileOffset(EquivalenceVisitor visitor,
+ SetConcatenation node, SetConcatenation other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkMapConcatenation_keyType(EquivalenceVisitor visitor,
+ MapConcatenation node, MapConcatenation other) {
+ return visitor.checkNodes(node.keyType, other.keyType, 'keyType');
+ }
+
+ bool checkMapConcatenation_valueType(EquivalenceVisitor visitor,
+ MapConcatenation node, MapConcatenation other) {
+ return visitor.checkNodes(node.valueType, other.valueType, 'valueType');
+ }
+
+ bool checkMapConcatenation_maps(EquivalenceVisitor visitor,
+ MapConcatenation node, MapConcatenation other) {
+ return visitor.checkLists(
+ node.maps, other.maps, visitor.checkNodes, 'maps');
+ }
+
+ bool checkMapConcatenation_fileOffset(EquivalenceVisitor visitor,
+ MapConcatenation node, MapConcatenation other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkInstanceCreation_classReference(EquivalenceVisitor visitor,
+ InstanceCreation node, InstanceCreation other) {
+ return visitor.checkReferences(
+ node.classReference, other.classReference, 'classReference');
+ }
+
+ bool checkInstanceCreation_typeArguments(EquivalenceVisitor visitor,
+ InstanceCreation node, InstanceCreation other) {
+ return visitor.checkLists(node.typeArguments, other.typeArguments,
+ visitor.checkNodes, 'typeArguments');
+ }
+
+ bool checkInstanceCreation_fieldValues(EquivalenceVisitor visitor,
+ InstanceCreation node, InstanceCreation other) {
+ return visitor.checkMaps(
+ node.fieldValues,
+ other.fieldValues,
+ visitor.matchReferences,
+ visitor.checkReferences,
+ visitor.checkNodes,
+ 'fieldValues');
+ }
+
+ bool checkInstanceCreation_asserts(EquivalenceVisitor visitor,
+ InstanceCreation node, InstanceCreation other) {
+ return visitor.checkLists(
+ node.asserts, other.asserts, visitor.checkNodes, 'asserts');
+ }
+
+ bool checkInstanceCreation_unusedArguments(EquivalenceVisitor visitor,
+ InstanceCreation node, InstanceCreation other) {
+ return visitor.checkLists(node.unusedArguments, other.unusedArguments,
+ visitor.checkNodes, 'unusedArguments');
+ }
+
+ bool checkInstanceCreation_fileOffset(EquivalenceVisitor visitor,
+ InstanceCreation node, InstanceCreation other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkFileUriExpression_fileUri(EquivalenceVisitor visitor,
+ FileUriExpression node, FileUriExpression other) {
+ return visitor.checkValues(node.fileUri, other.fileUri, 'fileUri');
+ }
+
+ bool checkFileUriExpression_expression(EquivalenceVisitor visitor,
+ FileUriExpression node, FileUriExpression other) {
+ return visitor.checkNodes(node.expression, other.expression, 'expression');
+ }
+
+ bool checkFileUriExpression_fileOffset(EquivalenceVisitor visitor,
+ FileUriExpression node, FileUriExpression other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkIsExpression_flags(
+ EquivalenceVisitor visitor, IsExpression node, IsExpression other) {
+ return visitor.checkValues(node.flags, other.flags, 'flags');
+ }
+
+ bool checkIsExpression_operand(
+ EquivalenceVisitor visitor, IsExpression node, IsExpression other) {
+ return visitor.checkNodes(node.operand, other.operand, 'operand');
+ }
+
+ bool checkIsExpression_type(
+ EquivalenceVisitor visitor, IsExpression node, IsExpression other) {
+ return visitor.checkNodes(node.type, other.type, 'type');
+ }
+
+ bool checkIsExpression_fileOffset(
+ EquivalenceVisitor visitor, IsExpression node, IsExpression other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkAsExpression_flags(
+ EquivalenceVisitor visitor, AsExpression node, AsExpression other) {
+ return visitor.checkValues(node.flags, other.flags, 'flags');
+ }
+
+ bool checkAsExpression_operand(
+ EquivalenceVisitor visitor, AsExpression node, AsExpression other) {
+ return visitor.checkNodes(node.operand, other.operand, 'operand');
+ }
+
+ bool checkAsExpression_type(
+ EquivalenceVisitor visitor, AsExpression node, AsExpression other) {
+ return visitor.checkNodes(node.type, other.type, 'type');
+ }
+
+ bool checkAsExpression_fileOffset(
+ EquivalenceVisitor visitor, AsExpression node, AsExpression other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkNullCheck_operand(
+ EquivalenceVisitor visitor, NullCheck node, NullCheck other) {
+ return visitor.checkNodes(node.operand, other.operand, 'operand');
+ }
+
+ bool checkNullCheck_fileOffset(
+ EquivalenceVisitor visitor, NullCheck node, NullCheck other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkStringLiteral_value(
+ EquivalenceVisitor visitor, StringLiteral node, StringLiteral other) {
+ return visitor.checkValues(node.value, other.value, 'value');
+ }
+
+ bool checkStringLiteral_fileOffset(
+ EquivalenceVisitor visitor, StringLiteral node, StringLiteral other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkIntLiteral_value(
+ EquivalenceVisitor visitor, IntLiteral node, IntLiteral other) {
+ return visitor.checkValues(node.value, other.value, 'value');
+ }
+
+ bool checkIntLiteral_fileOffset(
+ EquivalenceVisitor visitor, IntLiteral node, IntLiteral other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkDoubleLiteral_value(
+ EquivalenceVisitor visitor, DoubleLiteral node, DoubleLiteral other) {
+ return visitor.checkValues(node.value, other.value, 'value');
+ }
+
+ bool checkDoubleLiteral_fileOffset(
+ EquivalenceVisitor visitor, DoubleLiteral node, DoubleLiteral other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkBoolLiteral_value(
+ EquivalenceVisitor visitor, BoolLiteral node, BoolLiteral other) {
+ return visitor.checkValues(node.value, other.value, 'value');
+ }
+
+ bool checkBoolLiteral_fileOffset(
+ EquivalenceVisitor visitor, BoolLiteral node, BoolLiteral other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkNullLiteral_fileOffset(
+ EquivalenceVisitor visitor, NullLiteral node, NullLiteral other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkSymbolLiteral_value(
+ EquivalenceVisitor visitor, SymbolLiteral node, SymbolLiteral other) {
+ return visitor.checkValues(node.value, other.value, 'value');
+ }
+
+ bool checkSymbolLiteral_fileOffset(
+ EquivalenceVisitor visitor, SymbolLiteral node, SymbolLiteral other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkTypeLiteral_type(
+ EquivalenceVisitor visitor, TypeLiteral node, TypeLiteral other) {
+ return visitor.checkNodes(node.type, other.type, 'type');
+ }
+
+ bool checkTypeLiteral_fileOffset(
+ EquivalenceVisitor visitor, TypeLiteral node, TypeLiteral other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkThisExpression_fileOffset(
+ EquivalenceVisitor visitor, ThisExpression node, ThisExpression other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkRethrow_fileOffset(
+ EquivalenceVisitor visitor, Rethrow node, Rethrow other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkThrow_expression(
+ EquivalenceVisitor visitor, Throw node, Throw other) {
+ return visitor.checkNodes(node.expression, other.expression, 'expression');
+ }
+
+ bool checkThrow_fileOffset(
+ EquivalenceVisitor visitor, Throw node, Throw other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkListLiteral_isConst(
+ EquivalenceVisitor visitor, ListLiteral node, ListLiteral other) {
+ return visitor.checkValues(node.isConst, other.isConst, 'isConst');
+ }
+
+ bool checkListLiteral_typeArgument(
+ EquivalenceVisitor visitor, ListLiteral node, ListLiteral other) {
+ return visitor.checkNodes(
+ node.typeArgument, other.typeArgument, 'typeArgument');
+ }
+
+ bool checkListLiteral_expressions(
+ EquivalenceVisitor visitor, ListLiteral node, ListLiteral other) {
+ return visitor.checkLists(
+ node.expressions, other.expressions, visitor.checkNodes, 'expressions');
+ }
+
+ bool checkListLiteral_fileOffset(
+ EquivalenceVisitor visitor, ListLiteral node, ListLiteral other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkSetLiteral_isConst(
+ EquivalenceVisitor visitor, SetLiteral node, SetLiteral other) {
+ return visitor.checkValues(node.isConst, other.isConst, 'isConst');
+ }
+
+ bool checkSetLiteral_typeArgument(
+ EquivalenceVisitor visitor, SetLiteral node, SetLiteral other) {
+ return visitor.checkNodes(
+ node.typeArgument, other.typeArgument, 'typeArgument');
+ }
+
+ bool checkSetLiteral_expressions(
+ EquivalenceVisitor visitor, SetLiteral node, SetLiteral other) {
+ return visitor.checkLists(
+ node.expressions, other.expressions, visitor.checkNodes, 'expressions');
+ }
+
+ bool checkSetLiteral_fileOffset(
+ EquivalenceVisitor visitor, SetLiteral node, SetLiteral other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkMapLiteral_isConst(
+ EquivalenceVisitor visitor, MapLiteral node, MapLiteral other) {
+ return visitor.checkValues(node.isConst, other.isConst, 'isConst');
+ }
+
+ bool checkMapLiteral_keyType(
+ EquivalenceVisitor visitor, MapLiteral node, MapLiteral other) {
+ return visitor.checkNodes(node.keyType, other.keyType, 'keyType');
+ }
+
+ bool checkMapLiteral_valueType(
+ EquivalenceVisitor visitor, MapLiteral node, MapLiteral other) {
+ return visitor.checkNodes(node.valueType, other.valueType, 'valueType');
+ }
+
+ bool checkMapLiteral_entries(
+ EquivalenceVisitor visitor, MapLiteral node, MapLiteral other) {
+ return visitor.checkLists(
+ node.entries, other.entries, visitor.checkNodes, 'entries');
+ }
+
+ bool checkMapLiteral_fileOffset(
+ EquivalenceVisitor visitor, MapLiteral node, MapLiteral other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkAwaitExpression_operand(
+ EquivalenceVisitor visitor, AwaitExpression node, AwaitExpression other) {
+ return visitor.checkNodes(node.operand, other.operand, 'operand');
+ }
+
+ bool checkAwaitExpression_fileOffset(
+ EquivalenceVisitor visitor, AwaitExpression node, AwaitExpression other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkFunctionExpression_function(EquivalenceVisitor visitor,
+ FunctionExpression node, FunctionExpression other) {
+ return visitor.checkNodes(node.function, other.function, 'function');
+ }
+
+ bool checkFunctionExpression_fileOffset(EquivalenceVisitor visitor,
+ FunctionExpression node, FunctionExpression other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkConstantExpression_constant(EquivalenceVisitor visitor,
+ ConstantExpression node, ConstantExpression other) {
+ return visitor.checkNodes(node.constant, other.constant, 'constant');
+ }
+
+ bool checkConstantExpression_type(EquivalenceVisitor visitor,
+ ConstantExpression node, ConstantExpression other) {
+ return visitor.checkNodes(node.type, other.type, 'type');
+ }
+
+ bool checkConstantExpression_fileOffset(EquivalenceVisitor visitor,
+ ConstantExpression node, ConstantExpression other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkLet_variable(EquivalenceVisitor visitor, Let node, Let other) {
+ return visitor.checkNodes(node.variable, other.variable, 'variable');
+ }
+
+ bool checkLet_body(EquivalenceVisitor visitor, Let node, Let other) {
+ return visitor.checkNodes(node.body, other.body, 'body');
+ }
+
+ bool checkLet_fileOffset(EquivalenceVisitor visitor, Let node, Let other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkBlockExpression_body(
+ EquivalenceVisitor visitor, BlockExpression node, BlockExpression other) {
+ return visitor.checkNodes(node.body, other.body, 'body');
+ }
+
+ bool checkBlockExpression_value(
+ EquivalenceVisitor visitor, BlockExpression node, BlockExpression other) {
+ return visitor.checkNodes(node.value, other.value, 'value');
+ }
+
+ bool checkBlockExpression_fileOffset(
+ EquivalenceVisitor visitor, BlockExpression node, BlockExpression other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkLoadLibrary_import(
+ EquivalenceVisitor visitor, LoadLibrary node, LoadLibrary other) {
+ return visitor.checkNodes(node.import, other.import, 'import');
+ }
+
+ bool checkLoadLibrary_fileOffset(
+ EquivalenceVisitor visitor, LoadLibrary node, LoadLibrary other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkCheckLibraryIsLoaded_import(EquivalenceVisitor visitor,
+ CheckLibraryIsLoaded node, CheckLibraryIsLoaded other) {
+ return visitor.checkNodes(node.import, other.import, 'import');
+ }
+
+ bool checkCheckLibraryIsLoaded_fileOffset(EquivalenceVisitor visitor,
+ CheckLibraryIsLoaded node, CheckLibraryIsLoaded other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkConstructorTearOff_targetReference(EquivalenceVisitor visitor,
+ ConstructorTearOff node, ConstructorTearOff other) {
+ return visitor.checkReferences(
+ node.targetReference, other.targetReference, 'targetReference');
+ }
+
+ bool checkConstructorTearOff_fileOffset(EquivalenceVisitor visitor,
+ ConstructorTearOff node, ConstructorTearOff other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkRedirectingFactoryTearOff_targetReference(
+ EquivalenceVisitor visitor,
+ RedirectingFactoryTearOff node,
+ RedirectingFactoryTearOff other) {
+ return visitor.checkReferences(
+ node.targetReference, other.targetReference, 'targetReference');
+ }
+
+ bool checkRedirectingFactoryTearOff_fileOffset(EquivalenceVisitor visitor,
+ RedirectingFactoryTearOff node, RedirectingFactoryTearOff other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkTypedefTearOff_typeParameters(
+ EquivalenceVisitor visitor, TypedefTearOff node, TypedefTearOff other) {
+ return visitor.checkLists(node.typeParameters, other.typeParameters,
+ visitor.checkNodes, 'typeParameters');
+ }
+
+ bool checkTypedefTearOff_expression(
+ EquivalenceVisitor visitor, TypedefTearOff node, TypedefTearOff other) {
+ return visitor.checkNodes(node.expression, other.expression, 'expression');
+ }
+
+ bool checkTypedefTearOff_typeArguments(
+ EquivalenceVisitor visitor, TypedefTearOff node, TypedefTearOff other) {
+ return visitor.checkLists(node.typeArguments, other.typeArguments,
+ visitor.checkNodes, 'typeArguments');
+ }
+
+ bool checkTypedefTearOff_fileOffset(
+ EquivalenceVisitor visitor, TypedefTearOff node, TypedefTearOff other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkArguments_types(
+ EquivalenceVisitor visitor, Arguments node, Arguments other) {
+ return visitor.checkLists(
+ node.types, other.types, visitor.checkNodes, 'types');
+ }
+
+ bool checkArguments_positional(
+ EquivalenceVisitor visitor, Arguments node, Arguments other) {
+ return visitor.checkLists(
+ node.positional, other.positional, visitor.checkNodes, 'positional');
+ }
+
+ bool checkArguments_named(
+ EquivalenceVisitor visitor, Arguments node, Arguments other) {
+ return visitor.checkLists(
+ node.named, other.named, visitor.checkNodes, 'named');
+ }
+
+ bool checkArguments_fileOffset(
+ EquivalenceVisitor visitor, Arguments node, Arguments other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkNamedExpression_name(
+ EquivalenceVisitor visitor, NamedExpression node, NamedExpression other) {
+ return visitor.checkValues(node.name, other.name, 'name');
+ }
+
+ bool checkNamedExpression_value(
+ EquivalenceVisitor visitor, NamedExpression node, NamedExpression other) {
+ return visitor.checkNodes(node.value, other.value, 'value');
+ }
+
+ bool checkNamedExpression_fileOffset(
+ EquivalenceVisitor visitor, NamedExpression node, NamedExpression other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkMapLiteralEntry_key(
+ EquivalenceVisitor visitor, MapLiteralEntry node, MapLiteralEntry other) {
+ return visitor.checkNodes(node.key, other.key, 'key');
+ }
+
+ bool checkMapLiteralEntry_value(
+ EquivalenceVisitor visitor, MapLiteralEntry node, MapLiteralEntry other) {
+ return visitor.checkNodes(node.value, other.value, 'value');
+ }
+
+ bool checkMapLiteralEntry_fileOffset(
+ EquivalenceVisitor visitor, MapLiteralEntry node, MapLiteralEntry other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkExpressionStatement_expression(EquivalenceVisitor visitor,
+ ExpressionStatement node, ExpressionStatement other) {
+ return visitor.checkNodes(node.expression, other.expression, 'expression');
+ }
+
+ bool checkExpressionStatement_fileOffset(EquivalenceVisitor visitor,
+ ExpressionStatement node, ExpressionStatement other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkBlock_statements(
+ EquivalenceVisitor visitor, Block node, Block other) {
+ return visitor.checkLists(
+ node.statements, other.statements, visitor.checkNodes, 'statements');
+ }
+
+ bool checkBlock_fileEndOffset(
+ EquivalenceVisitor visitor, Block node, Block other) {
+ return visitor.checkValues(
+ node.fileEndOffset, other.fileEndOffset, 'fileEndOffset');
+ }
+
+ bool checkBlock_fileOffset(
+ EquivalenceVisitor visitor, Block node, Block other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkAssertBlock_statements(
+ EquivalenceVisitor visitor, AssertBlock node, AssertBlock other) {
+ return visitor.checkLists(
+ node.statements, other.statements, visitor.checkNodes, 'statements');
+ }
+
+ bool checkAssertBlock_fileOffset(
+ EquivalenceVisitor visitor, AssertBlock node, AssertBlock other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkEmptyStatement_fileOffset(
+ EquivalenceVisitor visitor, EmptyStatement node, EmptyStatement other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkAssertStatement_condition(
+ EquivalenceVisitor visitor, AssertStatement node, AssertStatement other) {
+ return visitor.checkNodes(node.condition, other.condition, 'condition');
+ }
+
+ bool checkAssertStatement_message(
+ EquivalenceVisitor visitor, AssertStatement node, AssertStatement other) {
+ return visitor.checkNodes(node.message, other.message, 'message');
+ }
+
+ bool checkAssertStatement_conditionStartOffset(
+ EquivalenceVisitor visitor, AssertStatement node, AssertStatement other) {
+ return visitor.checkValues(node.conditionStartOffset,
+ other.conditionStartOffset, 'conditionStartOffset');
+ }
+
+ bool checkAssertStatement_conditionEndOffset(
+ EquivalenceVisitor visitor, AssertStatement node, AssertStatement other) {
+ return visitor.checkValues(node.conditionEndOffset,
+ other.conditionEndOffset, 'conditionEndOffset');
+ }
+
+ bool checkAssertStatement_fileOffset(
+ EquivalenceVisitor visitor, AssertStatement node, AssertStatement other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkLabeledStatement_body(EquivalenceVisitor visitor,
+ LabeledStatement node, LabeledStatement other) {
+ return visitor.checkNodes(node.body, other.body, 'body');
+ }
+
+ bool checkLabeledStatement_fileOffset(EquivalenceVisitor visitor,
+ LabeledStatement node, LabeledStatement other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkBreakStatement_target(
+ EquivalenceVisitor visitor, BreakStatement node, BreakStatement other) {
+ return visitor.checkDeclarations(node.target, other.target, 'target');
+ }
+
+ bool checkBreakStatement_fileOffset(
+ EquivalenceVisitor visitor, BreakStatement node, BreakStatement other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkWhileStatement_condition(
+ EquivalenceVisitor visitor, WhileStatement node, WhileStatement other) {
+ return visitor.checkNodes(node.condition, other.condition, 'condition');
+ }
+
+ bool checkWhileStatement_body(
+ EquivalenceVisitor visitor, WhileStatement node, WhileStatement other) {
+ return visitor.checkNodes(node.body, other.body, 'body');
+ }
+
+ bool checkWhileStatement_fileOffset(
+ EquivalenceVisitor visitor, WhileStatement node, WhileStatement other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkDoStatement_body(
+ EquivalenceVisitor visitor, DoStatement node, DoStatement other) {
+ return visitor.checkNodes(node.body, other.body, 'body');
+ }
+
+ bool checkDoStatement_condition(
+ EquivalenceVisitor visitor, DoStatement node, DoStatement other) {
+ return visitor.checkNodes(node.condition, other.condition, 'condition');
+ }
+
+ bool checkDoStatement_fileOffset(
+ EquivalenceVisitor visitor, DoStatement node, DoStatement other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkForStatement_variables(
+ EquivalenceVisitor visitor, ForStatement node, ForStatement other) {
+ return visitor.checkLists(
+ node.variables, other.variables, visitor.checkNodes, 'variables');
+ }
+
+ bool checkForStatement_condition(
+ EquivalenceVisitor visitor, ForStatement node, ForStatement other) {
+ return visitor.checkNodes(node.condition, other.condition, 'condition');
+ }
+
+ bool checkForStatement_updates(
+ EquivalenceVisitor visitor, ForStatement node, ForStatement other) {
+ return visitor.checkLists(
+ node.updates, other.updates, visitor.checkNodes, 'updates');
+ }
+
+ bool checkForStatement_body(
+ EquivalenceVisitor visitor, ForStatement node, ForStatement other) {
+ return visitor.checkNodes(node.body, other.body, 'body');
+ }
+
+ bool checkForStatement_fileOffset(
+ EquivalenceVisitor visitor, ForStatement node, ForStatement other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkForInStatement_bodyOffset(
+ EquivalenceVisitor visitor, ForInStatement node, ForInStatement other) {
+ return visitor.checkValues(node.bodyOffset, other.bodyOffset, 'bodyOffset');
+ }
+
+ bool checkForInStatement_variable(
+ EquivalenceVisitor visitor, ForInStatement node, ForInStatement other) {
+ return visitor.checkNodes(node.variable, other.variable, 'variable');
+ }
+
+ bool checkForInStatement_iterable(
+ EquivalenceVisitor visitor, ForInStatement node, ForInStatement other) {
+ return visitor.checkNodes(node.iterable, other.iterable, 'iterable');
+ }
+
+ bool checkForInStatement_body(
+ EquivalenceVisitor visitor, ForInStatement node, ForInStatement other) {
+ return visitor.checkNodes(node.body, other.body, 'body');
+ }
+
+ bool checkForInStatement_isAsync(
+ EquivalenceVisitor visitor, ForInStatement node, ForInStatement other) {
+ return visitor.checkValues(node.isAsync, other.isAsync, 'isAsync');
+ }
+
+ bool checkForInStatement_fileOffset(
+ EquivalenceVisitor visitor, ForInStatement node, ForInStatement other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkSwitchStatement_expression(
+ EquivalenceVisitor visitor, SwitchStatement node, SwitchStatement other) {
+ return visitor.checkNodes(node.expression, other.expression, 'expression');
+ }
+
+ bool checkSwitchStatement_cases(
+ EquivalenceVisitor visitor, SwitchStatement node, SwitchStatement other) {
+ return visitor.checkLists(
+ node.cases, other.cases, visitor.checkNodes, 'cases');
+ }
+
+ bool checkSwitchStatement_fileOffset(
+ EquivalenceVisitor visitor, SwitchStatement node, SwitchStatement other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkContinueSwitchStatement_target(EquivalenceVisitor visitor,
+ ContinueSwitchStatement node, ContinueSwitchStatement other) {
+ return visitor.checkDeclarations(node.target, other.target, 'target');
+ }
+
+ bool checkContinueSwitchStatement_fileOffset(EquivalenceVisitor visitor,
+ ContinueSwitchStatement node, ContinueSwitchStatement other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkIfStatement_condition(
+ EquivalenceVisitor visitor, IfStatement node, IfStatement other) {
+ return visitor.checkNodes(node.condition, other.condition, 'condition');
+ }
+
+ bool checkIfStatement_then(
+ EquivalenceVisitor visitor, IfStatement node, IfStatement other) {
+ return visitor.checkNodes(node.then, other.then, 'then');
+ }
+
+ bool checkIfStatement_otherwise(
+ EquivalenceVisitor visitor, IfStatement node, IfStatement other) {
+ return visitor.checkNodes(node.otherwise, other.otherwise, 'otherwise');
+ }
+
+ bool checkIfStatement_fileOffset(
+ EquivalenceVisitor visitor, IfStatement node, IfStatement other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkReturnStatement_expression(
+ EquivalenceVisitor visitor, ReturnStatement node, ReturnStatement other) {
+ return visitor.checkNodes(node.expression, other.expression, 'expression');
+ }
+
+ bool checkReturnStatement_fileOffset(
+ EquivalenceVisitor visitor, ReturnStatement node, ReturnStatement other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkTryCatch_body(
+ EquivalenceVisitor visitor, TryCatch node, TryCatch other) {
+ return visitor.checkNodes(node.body, other.body, 'body');
+ }
+
+ bool checkTryCatch_catches(
+ EquivalenceVisitor visitor, TryCatch node, TryCatch other) {
+ return visitor.checkLists(
+ node.catches, other.catches, visitor.checkNodes, 'catches');
+ }
+
+ bool checkTryCatch_isSynthetic(
+ EquivalenceVisitor visitor, TryCatch node, TryCatch other) {
+ return visitor.checkValues(
+ node.isSynthetic, other.isSynthetic, 'isSynthetic');
+ }
+
+ bool checkTryCatch_fileOffset(
+ EquivalenceVisitor visitor, TryCatch node, TryCatch other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkTryFinally_body(
+ EquivalenceVisitor visitor, TryFinally node, TryFinally other) {
+ return visitor.checkNodes(node.body, other.body, 'body');
+ }
+
+ bool checkTryFinally_finalizer(
+ EquivalenceVisitor visitor, TryFinally node, TryFinally other) {
+ return visitor.checkNodes(node.finalizer, other.finalizer, 'finalizer');
+ }
+
+ bool checkTryFinally_fileOffset(
+ EquivalenceVisitor visitor, TryFinally node, TryFinally other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkYieldStatement_expression(
+ EquivalenceVisitor visitor, YieldStatement node, YieldStatement other) {
+ return visitor.checkNodes(node.expression, other.expression, 'expression');
+ }
+
+ bool checkYieldStatement_flags(
+ EquivalenceVisitor visitor, YieldStatement node, YieldStatement other) {
+ return visitor.checkValues(node.flags, other.flags, 'flags');
+ }
+
+ bool checkYieldStatement_fileOffset(
+ EquivalenceVisitor visitor, YieldStatement node, YieldStatement other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkVariableDeclaration_fileEqualsOffset(EquivalenceVisitor visitor,
+ VariableDeclaration node, VariableDeclaration other) {
+ return visitor.checkValues(
+ node.fileEqualsOffset, other.fileEqualsOffset, 'fileEqualsOffset');
+ }
+
+ bool checkVariableDeclaration_annotations(EquivalenceVisitor visitor,
+ VariableDeclaration node, VariableDeclaration other) {
+ return visitor.checkLists(
+ node.annotations, other.annotations, visitor.checkNodes, 'annotations');
+ }
+
+ bool checkVariableDeclaration_name(EquivalenceVisitor visitor,
+ VariableDeclaration node, VariableDeclaration other) {
+ return visitor.checkValues(node.name, other.name, 'name');
+ }
+
+ bool checkVariableDeclaration_flags(EquivalenceVisitor visitor,
+ VariableDeclaration node, VariableDeclaration other) {
+ return visitor.checkValues(node.flags, other.flags, 'flags');
+ }
+
+ bool checkVariableDeclaration_type(EquivalenceVisitor visitor,
+ VariableDeclaration node, VariableDeclaration other) {
+ return visitor.checkNodes(node.type, other.type, 'type');
+ }
+
+ bool checkVariableDeclaration_binaryOffsetNoTag(EquivalenceVisitor visitor,
+ VariableDeclaration node, VariableDeclaration other) {
+ return visitor.checkValues(
+ node.binaryOffsetNoTag, other.binaryOffsetNoTag, 'binaryOffsetNoTag');
+ }
+
+ bool checkVariableDeclaration_initializer(EquivalenceVisitor visitor,
+ VariableDeclaration node, VariableDeclaration other) {
+ return visitor.checkNodes(
+ node.initializer, other.initializer, 'initializer');
+ }
+
+ bool checkVariableDeclaration_fileOffset(EquivalenceVisitor visitor,
+ VariableDeclaration node, VariableDeclaration other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkFunctionDeclaration_variable(EquivalenceVisitor visitor,
+ FunctionDeclaration node, FunctionDeclaration other) {
+ return visitor.checkNodes(node.variable, other.variable, 'variable');
+ }
+
+ bool checkFunctionDeclaration_function(EquivalenceVisitor visitor,
+ FunctionDeclaration node, FunctionDeclaration other) {
+ return visitor.checkNodes(node.function, other.function, 'function');
+ }
+
+ bool checkFunctionDeclaration_fileOffset(EquivalenceVisitor visitor,
+ FunctionDeclaration node, FunctionDeclaration other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkSwitchCase_expressions(
+ EquivalenceVisitor visitor, SwitchCase node, SwitchCase other) {
+ return visitor.checkLists(
+ node.expressions, other.expressions, visitor.checkNodes, 'expressions');
+ }
+
+ bool checkSwitchCase_expressionOffsets(
+ EquivalenceVisitor visitor, SwitchCase node, SwitchCase other) {
+ return visitor.checkLists(node.expressionOffsets, other.expressionOffsets,
+ visitor.checkValues, 'expressionOffsets');
+ }
+
+ bool checkSwitchCase_body(
+ EquivalenceVisitor visitor, SwitchCase node, SwitchCase other) {
+ return visitor.checkNodes(node.body, other.body, 'body');
+ }
+
+ bool checkSwitchCase_isDefault(
+ EquivalenceVisitor visitor, SwitchCase node, SwitchCase other) {
+ return visitor.checkValues(node.isDefault, other.isDefault, 'isDefault');
+ }
+
+ bool checkSwitchCase_fileOffset(
+ EquivalenceVisitor visitor, SwitchCase node, SwitchCase other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkCatch_guard(EquivalenceVisitor visitor, Catch node, Catch other) {
+ return visitor.checkNodes(node.guard, other.guard, 'guard');
+ }
+
+ bool checkCatch_exception(
+ EquivalenceVisitor visitor, Catch node, Catch other) {
+ return visitor.checkNodes(node.exception, other.exception, 'exception');
+ }
+
+ bool checkCatch_stackTrace(
+ EquivalenceVisitor visitor, Catch node, Catch other) {
+ return visitor.checkNodes(node.stackTrace, other.stackTrace, 'stackTrace');
+ }
+
+ bool checkCatch_body(EquivalenceVisitor visitor, Catch node, Catch other) {
+ return visitor.checkNodes(node.body, other.body, 'body');
+ }
+
+ bool checkCatch_fileOffset(
+ EquivalenceVisitor visitor, Catch node, Catch other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkTypeParameter_flags(
+ EquivalenceVisitor visitor, TypeParameter node, TypeParameter other) {
+ return visitor.checkValues(node.flags, other.flags, 'flags');
+ }
+
+ bool checkTypeParameter_annotations(
+ EquivalenceVisitor visitor, TypeParameter node, TypeParameter other) {
+ return visitor.checkLists(
+ node.annotations, other.annotations, visitor.checkNodes, 'annotations');
+ }
+
+ bool checkTypeParameter_name(
+ EquivalenceVisitor visitor, TypeParameter node, TypeParameter other) {
+ return visitor.checkValues(node.name, other.name, 'name');
+ }
+
+ bool checkTypeParameter_bound(
+ EquivalenceVisitor visitor, TypeParameter node, TypeParameter other) {
+ return visitor.checkNodes(node.bound, other.bound, 'bound');
+ }
+
+ bool checkTypeParameter_defaultType(
+ EquivalenceVisitor visitor, TypeParameter node, TypeParameter other) {
+ return visitor.checkNodes(
+ node.defaultType, other.defaultType, 'defaultType');
+ }
+
+ bool checkTypeParameter_variance(
+ EquivalenceVisitor visitor, TypeParameter node, TypeParameter other) {
+ return visitor.checkValues(node.variance, other.variance, 'variance');
+ }
+
+ bool checkTypeParameter_fileOffset(
+ EquivalenceVisitor visitor, TypeParameter node, TypeParameter other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkComponent_problemsAsJson(
+ EquivalenceVisitor visitor, Component node, Component other) {
+ return visitor.checkLists(node.problemsAsJson, other.problemsAsJson,
+ visitor.checkValues, 'problemsAsJson');
+ }
+
+ bool checkComponent_libraries(
+ EquivalenceVisitor visitor, Component node, Component other) {
+ return visitor.checkLists(
+ node.libraries, other.libraries, visitor.checkNodes, 'libraries');
+ }
+
+ bool checkSource_lineStarts(
+ EquivalenceVisitor visitor, Source node, Source other) {
+ return visitor.checkLists(
+ node.lineStarts, other.lineStarts, visitor.checkValues, 'lineStarts');
+ }
+
+ bool checkSource_source(
+ EquivalenceVisitor visitor, Source node, Source other) {
+ return visitor.checkLists(
+ node.source, other.source, visitor.checkValues, 'source');
+ }
+
+ bool checkSource_importUri(
+ EquivalenceVisitor visitor, Source node, Source other) {
+ return visitor.checkValues(node.importUri, other.importUri, 'importUri');
+ }
+
+ bool checkSource_fileUri(
+ EquivalenceVisitor visitor, Source node, Source other) {
+ return visitor.checkValues(node.fileUri, other.fileUri, 'fileUri');
+ }
+
+ bool checkSource_constantCoverageConstructors(
+ EquivalenceVisitor visitor, Source node, Source other) {
+ return visitor.checkSets(
+ node.constantCoverageConstructors,
+ other.constantCoverageConstructors,
+ visitor.matchReferences,
+ visitor.checkReferences,
+ 'constantCoverageConstructors');
+ }
+
+ bool checkSource_cachedText(
+ EquivalenceVisitor visitor, Source node, Source other) {
+ return visitor.checkValues(node.cachedText, other.cachedText, 'cachedText');
+ }
+
+ bool checkComponent_uriToSource(
+ EquivalenceVisitor visitor, Component node, Component other) {
+ return visitor.checkMaps(node.uriToSource, other.uriToSource,
+ visitor.matchValues, visitor.checkValues, (a, b, _) {
+ if (identical(a, b)) return true;
+ if (a is! Source) return false;
+ if (b is! Source) return false;
+ return checkSource(visitor, a, b);
+ }, 'uriToSource');
+ }
+
+ bool checkComponent_metadata(
+ EquivalenceVisitor visitor, Component node, Component other) {
+ return visitor.checkMaps(
+ node.metadata, other.metadata, visitor.matchValues, visitor.checkValues,
+ (a, b, _) {
+ if (identical(a, b)) return true;
+ if (a is! MetadataRepository) return false;
+ if (b is! MetadataRepository) return false;
+ return checkMetadataRepository(visitor, a, b);
+ }, 'metadata');
+ }
+
+ bool checkComponent_mainMethodName(
+ EquivalenceVisitor visitor, Component node, Component other) {
+ return visitor.checkReferences(
+ node.mainMethodName, other.mainMethodName, 'mainMethodName');
+ }
+
+ bool checkComponent_mode(
+ EquivalenceVisitor visitor, Component node, Component other) {
+ return visitor.checkValues(node.mode, other.mode, 'mode');
+ }
+
+ bool checkComponent_fileOffset(
+ EquivalenceVisitor visitor, Component node, Component other) {
+ return visitor.checkValues(node.fileOffset, other.fileOffset, 'fileOffset');
+ }
+
+ bool checkName_text(EquivalenceVisitor visitor, Name node, Name other) {
+ return visitor.checkValues(node.text, other.text, 'text');
+ }
+
+ bool checkNeverType_declaredNullability(
+ EquivalenceVisitor visitor, NeverType node, NeverType other) {
+ return visitor.checkValues(node.declaredNullability,
+ other.declaredNullability, 'declaredNullability');
+ }
+
+ bool checkInterfaceType_className(
+ EquivalenceVisitor visitor, InterfaceType node, InterfaceType other) {
+ return visitor.checkReferences(
+ node.className, other.className, 'className');
+ }
+
+ bool checkInterfaceType_declaredNullability(
+ EquivalenceVisitor visitor, InterfaceType node, InterfaceType other) {
+ return visitor.checkValues(node.declaredNullability,
+ other.declaredNullability, 'declaredNullability');
+ }
+
+ bool checkInterfaceType_typeArguments(
+ EquivalenceVisitor visitor, InterfaceType node, InterfaceType other) {
+ return visitor.checkLists(node.typeArguments, other.typeArguments,
+ visitor.checkNodes, 'typeArguments');
+ }
+
+ bool checkFunctionType_typeParameters(
+ EquivalenceVisitor visitor, FunctionType node, FunctionType other) {
+ return visitor.checkLists(node.typeParameters, other.typeParameters,
+ visitor.checkNodes, 'typeParameters');
+ }
+
+ bool checkFunctionType_requiredParameterCount(
+ EquivalenceVisitor visitor, FunctionType node, FunctionType other) {
+ return visitor.checkValues(node.requiredParameterCount,
+ other.requiredParameterCount, 'requiredParameterCount');
+ }
+
+ bool checkFunctionType_positionalParameters(
+ EquivalenceVisitor visitor, FunctionType node, FunctionType other) {
+ return visitor.checkLists(node.positionalParameters,
+ other.positionalParameters, visitor.checkNodes, 'positionalParameters');
+ }
+
+ bool checkFunctionType_namedParameters(
+ EquivalenceVisitor visitor, FunctionType node, FunctionType other) {
+ return visitor.checkLists(node.namedParameters, other.namedParameters,
+ visitor.checkNodes, 'namedParameters');
+ }
+
+ bool checkFunctionType_declaredNullability(
+ EquivalenceVisitor visitor, FunctionType node, FunctionType other) {
+ return visitor.checkValues(node.declaredNullability,
+ other.declaredNullability, 'declaredNullability');
+ }
+
+ bool checkFunctionType_typedefType(
+ EquivalenceVisitor visitor, FunctionType node, FunctionType other) {
+ return visitor.checkNodes(
+ node.typedefType, other.typedefType, 'typedefType');
+ }
+
+ bool checkFunctionType_returnType(
+ EquivalenceVisitor visitor, FunctionType node, FunctionType other) {
+ return visitor.checkNodes(node.returnType, other.returnType, 'returnType');
+ }
+
+ bool checkTypedefType_declaredNullability(
+ EquivalenceVisitor visitor, TypedefType node, TypedefType other) {
+ return visitor.checkValues(node.declaredNullability,
+ other.declaredNullability, 'declaredNullability');
+ }
+
+ bool checkTypedefType_typedefReference(
+ EquivalenceVisitor visitor, TypedefType node, TypedefType other) {
+ return visitor.checkReferences(
+ node.typedefReference, other.typedefReference, 'typedefReference');
+ }
+
+ bool checkTypedefType_typeArguments(
+ EquivalenceVisitor visitor, TypedefType node, TypedefType other) {
+ return visitor.checkLists(node.typeArguments, other.typeArguments,
+ visitor.checkNodes, 'typeArguments');
+ }
+
+ bool checkFutureOrType_typeArgument(
+ EquivalenceVisitor visitor, FutureOrType node, FutureOrType other) {
+ return visitor.checkNodes(
+ node.typeArgument, other.typeArgument, 'typeArgument');
+ }
+
+ bool checkFutureOrType_declaredNullability(
+ EquivalenceVisitor visitor, FutureOrType node, FutureOrType other) {
+ return visitor.checkValues(node.declaredNullability,
+ other.declaredNullability, 'declaredNullability');
+ }
+
+ bool checkExtensionType_extensionReference(
+ EquivalenceVisitor visitor, ExtensionType node, ExtensionType other) {
+ return visitor.checkReferences(node.extensionReference,
+ other.extensionReference, 'extensionReference');
+ }
+
+ bool checkExtensionType_declaredNullability(
+ EquivalenceVisitor visitor, ExtensionType node, ExtensionType other) {
+ return visitor.checkValues(node.declaredNullability,
+ other.declaredNullability, 'declaredNullability');
+ }
+
+ bool checkExtensionType_typeArguments(
+ EquivalenceVisitor visitor, ExtensionType node, ExtensionType other) {
+ return visitor.checkLists(node.typeArguments, other.typeArguments,
+ visitor.checkNodes, 'typeArguments');
+ }
+
+ bool checkExtensionType_onType(
+ EquivalenceVisitor visitor, ExtensionType node, ExtensionType other) {
+ return visitor.checkNodes(node.onType, other.onType, 'onType');
+ }
+
+ bool checkTypeParameterType_declaredNullability(EquivalenceVisitor visitor,
+ TypeParameterType node, TypeParameterType other) {
+ return visitor.checkValues(node.declaredNullability,
+ other.declaredNullability, 'declaredNullability');
+ }
+
+ bool checkTypeParameterType_parameter(EquivalenceVisitor visitor,
+ TypeParameterType node, TypeParameterType other) {
+ return visitor.checkDeclarations(
+ node.parameter, other.parameter, 'parameter');
+ }
+
+ bool checkTypeParameterType_promotedBound(EquivalenceVisitor visitor,
+ TypeParameterType node, TypeParameterType other) {
+ return visitor.checkNodes(
+ node.promotedBound, other.promotedBound, 'promotedBound');
+ }
+
+ bool checkNamedType_name(
+ EquivalenceVisitor visitor, NamedType node, NamedType other) {
+ return visitor.checkValues(node.name, other.name, 'name');
+ }
+
+ bool checkNamedType_type(
+ EquivalenceVisitor visitor, NamedType node, NamedType other) {
+ return visitor.checkNodes(node.type, other.type, 'type');
+ }
+
+ bool checkNamedType_isRequired(
+ EquivalenceVisitor visitor, NamedType node, NamedType other) {
+ return visitor.checkValues(node.isRequired, other.isRequired, 'isRequired');
+ }
+
+ bool checkSupertype_className(
+ EquivalenceVisitor visitor, Supertype node, Supertype other) {
+ return visitor.checkReferences(
+ node.className, other.className, 'className');
+ }
+
+ bool checkSupertype_typeArguments(
+ EquivalenceVisitor visitor, Supertype node, Supertype other) {
+ return visitor.checkLists(node.typeArguments, other.typeArguments,
+ visitor.checkNodes, 'typeArguments');
+ }
+
+ bool checkNullConstant_value(
+ EquivalenceVisitor visitor, NullConstant node, NullConstant other) {
+ return visitor.checkValues(node.value, other.value, 'value');
+ }
+
+ bool checkBoolConstant_value(
+ EquivalenceVisitor visitor, BoolConstant node, BoolConstant other) {
+ return visitor.checkValues(node.value, other.value, 'value');
+ }
+
+ bool checkIntConstant_value(
+ EquivalenceVisitor visitor, IntConstant node, IntConstant other) {
+ return visitor.checkValues(node.value, other.value, 'value');
+ }
+
+ bool checkDoubleConstant_value(
+ EquivalenceVisitor visitor, DoubleConstant node, DoubleConstant other) {
+ return visitor.checkValues(node.value, other.value, 'value');
+ }
+
+ bool checkStringConstant_value(
+ EquivalenceVisitor visitor, StringConstant node, StringConstant other) {
+ return visitor.checkValues(node.value, other.value, 'value');
+ }
+
+ bool checkSymbolConstant_name(
+ EquivalenceVisitor visitor, SymbolConstant node, SymbolConstant other) {
+ return visitor.checkValues(node.name, other.name, 'name');
+ }
+
+ bool checkSymbolConstant_libraryReference(
+ EquivalenceVisitor visitor, SymbolConstant node, SymbolConstant other) {
+ return visitor.checkReferences(
+ node.libraryReference, other.libraryReference, 'libraryReference');
+ }
+
+ bool checkMapConstant_keyType(
+ EquivalenceVisitor visitor, MapConstant node, MapConstant other) {
+ return visitor.checkNodes(node.keyType, other.keyType, 'keyType');
+ }
+
+ bool checkMapConstant_valueType(
+ EquivalenceVisitor visitor, MapConstant node, MapConstant other) {
+ return visitor.checkNodes(node.valueType, other.valueType, 'valueType');
+ }
+
+ bool checkConstantMapEntry_key(EquivalenceVisitor visitor,
+ ConstantMapEntry node, ConstantMapEntry other) {
+ return visitor.checkNodes(node.key, other.key, 'key');
+ }
+
+ bool checkConstantMapEntry_value(EquivalenceVisitor visitor,
+ ConstantMapEntry node, ConstantMapEntry other) {
+ return visitor.checkNodes(node.value, other.value, 'value');
+ }
+
+ bool checkMapConstant_entries(
+ EquivalenceVisitor visitor, MapConstant node, MapConstant other) {
+ return visitor.checkLists(node.entries, other.entries, (a, b, _) {
+ if (identical(a, b)) return true;
+ if (a is! ConstantMapEntry) return false;
+ if (b is! ConstantMapEntry) return false;
+ return checkConstantMapEntry(visitor, a, b);
+ }, 'entries');
+ }
+
+ bool checkListConstant_typeArgument(
+ EquivalenceVisitor visitor, ListConstant node, ListConstant other) {
+ return visitor.checkNodes(
+ node.typeArgument, other.typeArgument, 'typeArgument');
+ }
+
+ bool checkListConstant_entries(
+ EquivalenceVisitor visitor, ListConstant node, ListConstant other) {
+ return visitor.checkLists(
+ node.entries, other.entries, visitor.checkNodes, 'entries');
+ }
+
+ bool checkSetConstant_typeArgument(
+ EquivalenceVisitor visitor, SetConstant node, SetConstant other) {
+ return visitor.checkNodes(
+ node.typeArgument, other.typeArgument, 'typeArgument');
+ }
+
+ bool checkSetConstant_entries(
+ EquivalenceVisitor visitor, SetConstant node, SetConstant other) {
+ return visitor.checkLists(
+ node.entries, other.entries, visitor.checkNodes, 'entries');
+ }
+
+ bool checkInstanceConstant_classReference(EquivalenceVisitor visitor,
+ InstanceConstant node, InstanceConstant other) {
+ return visitor.checkReferences(
+ node.classReference, other.classReference, 'classReference');
+ }
+
+ bool checkInstanceConstant_typeArguments(EquivalenceVisitor visitor,
+ InstanceConstant node, InstanceConstant other) {
+ return visitor.checkLists(node.typeArguments, other.typeArguments,
+ visitor.checkNodes, 'typeArguments');
+ }
+
+ bool checkInstanceConstant_fieldValues(EquivalenceVisitor visitor,
+ InstanceConstant node, InstanceConstant other) {
+ return visitor.checkMaps(
+ node.fieldValues,
+ other.fieldValues,
+ visitor.matchReferences,
+ visitor.checkReferences,
+ visitor.checkNodes,
+ 'fieldValues');
+ }
+
+ bool checkInstantiationConstant_tearOffConstant(EquivalenceVisitor visitor,
+ InstantiationConstant node, InstantiationConstant other) {
+ return visitor.checkNodes(
+ node.tearOffConstant, other.tearOffConstant, 'tearOffConstant');
+ }
+
+ bool checkInstantiationConstant_types(EquivalenceVisitor visitor,
+ InstantiationConstant node, InstantiationConstant other) {
+ return visitor.checkLists(
+ node.types, other.types, visitor.checkNodes, 'types');
+ }
+
+ bool checkStaticTearOffConstant_targetReference(EquivalenceVisitor visitor,
+ StaticTearOffConstant node, StaticTearOffConstant other) {
+ return visitor.checkReferences(
+ node.targetReference, other.targetReference, 'targetReference');
+ }
+
+ bool checkConstructorTearOffConstant_targetReference(
+ EquivalenceVisitor visitor,
+ ConstructorTearOffConstant node,
+ ConstructorTearOffConstant other) {
+ return visitor.checkReferences(
+ node.targetReference, other.targetReference, 'targetReference');
+ }
+
+ bool checkRedirectingFactoryTearOffConstant_targetReference(
+ EquivalenceVisitor visitor,
+ RedirectingFactoryTearOffConstant node,
+ RedirectingFactoryTearOffConstant other) {
+ return visitor.checkReferences(
+ node.targetReference, other.targetReference, 'targetReference');
+ }
+
+ bool checkTypedefTearOffConstant_parameters(EquivalenceVisitor visitor,
+ TypedefTearOffConstant node, TypedefTearOffConstant other) {
+ return visitor.checkLists(
+ node.parameters, other.parameters, visitor.checkNodes, 'parameters');
+ }
+
+ bool checkTypedefTearOffConstant_tearOffConstant(EquivalenceVisitor visitor,
+ TypedefTearOffConstant node, TypedefTearOffConstant other) {
+ return visitor.checkNodes(
+ node.tearOffConstant, other.tearOffConstant, 'tearOffConstant');
+ }
+
+ bool checkTypedefTearOffConstant_types(EquivalenceVisitor visitor,
+ TypedefTearOffConstant node, TypedefTearOffConstant other) {
+ return visitor.checkLists(
+ node.types, other.types, visitor.checkNodes, 'types');
+ }
+
+ bool checkTypeLiteralConstant_type(EquivalenceVisitor visitor,
+ TypeLiteralConstant node, TypeLiteralConstant other) {
+ return visitor.checkNodes(node.type, other.type, 'type');
+ }
+
+ bool checkUnevaluatedConstant_expression(EquivalenceVisitor visitor,
+ UnevaluatedConstant node, UnevaluatedConstant other) {
+ return visitor.checkNodes(node.expression, other.expression, 'expression');
+ }
+}
diff --git a/pkg/kernel/lib/src/equivalence_helpers.dart b/pkg/kernel/lib/src/equivalence_helpers.dart
new file mode 100644
index 0000000..a7ccb27
--- /dev/null
+++ b/pkg/kernel/lib/src/equivalence_helpers.dart
@@ -0,0 +1,400 @@
+// 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.
+
+part of 'equivalence.dart';
+
+/// The node or property currently visited by the [EquivalenceVisitor].
+abstract class State {
+ const State();
+
+ State? get parent;
+}
+
+/// State for visiting two AST nodes in [EquivalenceVisitor].
+class NodeState extends State {
+ final State? parent;
+ final Node a;
+ final Node b;
+
+ NodeState(this.a, this.b, [this.parent]);
+}
+
+/// State for visiting an AST property in [EquivalenceVisitor]
+class PropertyState extends State {
+ final State? parent;
+ final String name;
+
+ PropertyState(this.name, [this.parent]);
+}
+
+/// The state of the equivalence visitor.
+///
+/// This holds the currently found inequivalences and the current assumptions.
+/// This also determines whether inequivalence are currently reported.
+class CheckingState {
+ /// If `true`, inequivalences are currently reported.
+ final bool isAsserting;
+
+ CheckingState(
+ {this.isAsserting: true,
+ UnionFind<Reference>? assumedReferences,
+ State? currentState})
+ : _assumedReferences = assumedReferences ?? new UnionFind<Reference>(),
+ _currentState = currentState;
+
+ /// Create a new [CheckingState] that inherits the [_currentState] and a copy
+ /// of the current assumptions. If [isAsserting] is `true`, the new state
+ /// will register inequivalences.
+ CheckingState createSubState({bool isAsserting: false}) {
+ return new CheckingState(
+ isAsserting: isAsserting,
+ assumedReferences: _assumedReferences.clone(),
+ currentState: _currentState)
+ .._assumedDeclarationMap.addAll(_assumedDeclarationMap);
+ }
+
+ /// Returns a state corresponding to the state which does _not_ register
+ /// inequivalences. If this state is already not registering inequivalences,
+ /// `this` is returned.
+ CheckingState toMatchingState() {
+ if (!isAsserting) return this;
+ return createSubState(isAsserting: false);
+ }
+
+ /// Returns that value that should be used as the result value when
+ /// inequivalence are found.
+ ///
+ /// See [EquivalenceVisitor.resultOnInequivalence] for details.
+ bool get resultOnInequivalence => isAsserting;
+
+ /// Map of [Reference]s that are assumed to be equivalent. The keys are
+ /// the [Reference]s on the left side of the equivalence relation.
+ UnionFind<Reference> _assumedReferences;
+
+ /// Returns `true` if [a] and [b] are currently assumed to be equivalent.
+ bool checkAssumedReferences(Reference? a, Reference? b) {
+ if (identical(a, b)) return true;
+ if (a == null || b == null) return false;
+ return _assumedReferences.valuesInSameSet(a, b);
+ }
+
+ /// Assume that [a] and [b] are equivalent, if possible.
+ ///
+ /// Returns `true` if [a] and [b] could be assumed to be equivalent. This
+ /// is not the case if either [a] or [b] is `null`.
+ bool assumeReferences(Reference? a, Reference? b) {
+ if (identical(a, b)) return true;
+ if (a == null || b == null) return false;
+ _assumedReferences.unionOfValues(a, b);
+ return true;
+ }
+
+ /// Map of declarations that are assumed to be equivalent.
+ Map<dynamic, dynamic> _assumedDeclarationMap = {};
+
+ /// Returns `true` if [a] and [b] are currently assumed to be equivalent.
+ bool checkAssumedDeclarations(dynamic a, dynamic b) {
+ if (identical(a, b)) return true;
+ if (a == null || b == null) return false;
+ return _assumedDeclarationMap.containsKey(a) &&
+ _assumedDeclarationMap[a] == b;
+ }
+
+ /// Assume that [a] and [b] are equivalent, if possible.
+ ///
+ /// Returns `true` if [a] and [b] could be assumed to be equivalent. This
+ /// would not be the case if [a] is already assumed to be equivalent to
+ /// another declaration.
+ bool assumeDeclarations(dynamic a, dynamic b) {
+ if (identical(a, b)) return true;
+ if (a == null || b == null) return false;
+ if (_assumedDeclarationMap.containsKey(a)) {
+ return _assumedDeclarationMap[a] == b;
+ } else {
+ _assumedDeclarationMap[a] = b;
+ return true;
+ }
+ }
+
+ /// The currently visited node or property.
+ State? _currentState;
+
+ /// Enters a new property state of a property named [propertyName].
+ void pushPropertyState(String propertyName) {
+ _currentState = new PropertyState(propertyName, _currentState);
+ }
+
+ /// Enters a new node state of nodes [a] and [b].
+ void pushNodeState(Node a, Node b) {
+ _currentState = new NodeState(a, b, _currentState);
+ }
+
+ /// Leaves the current node or property.
+ void popState() {
+ _currentState = _currentState?.parent;
+ }
+
+ /// List of registered inequivalences.
+ List<Inequivalence> _inequivalences = [];
+
+ /// Registers the inequivalence [message] on [propertyName].
+ void registerInequivalence(String propertyName, String message) {
+ _inequivalences.add(new Inequivalence(
+ new PropertyState(propertyName, _currentState), message));
+ }
+
+ /// Returns `true` if inequivalences have been registered.
+ bool get hasInequivalences => _inequivalences.isNotEmpty;
+
+ /// Returns the [EquivalenceResult] for the registered inequivalences. If
+ /// [hasInequivalences] is `true`, the result is marked has having
+ /// inequivalences, even when none have been registered.
+ EquivalenceResult toResult({bool hasInequivalences: false}) =>
+ new EquivalenceResult(
+ hasInequivalences: hasInequivalences,
+ registeredInequivalences: _inequivalences.toList());
+}
+
+/// The result of performing equivalence checking.
+class EquivalenceResult {
+ final bool hasInequivalences;
+ final List<Inequivalence> registeredInequivalences;
+
+ EquivalenceResult(
+ {this.hasInequivalences: false, required this.registeredInequivalences});
+
+ bool get isEquivalent =>
+ !hasInequivalences && registeredInequivalences.isEmpty;
+
+ @override
+ String toString() {
+ StringBuffer sb = new StringBuffer();
+ for (Inequivalence inequivalence in registeredInequivalences) {
+ sb.writeln(inequivalence);
+ }
+ return sb.toString();
+ }
+}
+
+/// A registered inequivalence holding the [state] at which is was found and
+/// details about the inequivalence.
+class Inequivalence {
+ final State state;
+ final String message;
+
+ Inequivalence(this.state, this.message);
+
+ @override
+ String toString() {
+ List<State> states = [];
+ State? state = this.state;
+ while (state != null) {
+ states.add(state);
+ state = state.parent;
+ }
+ StringBuffer sb = new StringBuffer();
+ sb.writeln(message);
+ String indent = ' ';
+ for (State state in states.reversed) {
+ if (state is NodeState) {
+ sb.writeln();
+ sb.write(indent);
+ indent = ' $indent';
+ if (state.a.runtimeType == state.b.runtimeType) {
+ if (state.a is NamedNode) {
+ sb.write(state.a.runtimeType);
+ sb.write('(');
+ sb.write(state.a.toText(defaultAstTextStrategy));
+ sb.write(')');
+ } else {
+ sb.write(state.a.runtimeType);
+ }
+ } else {
+ sb.write('(${state.a.runtimeType}/${state.b.runtimeType})');
+ }
+ } else if (state is PropertyState) {
+ sb.write('.${state.name}');
+ } else {
+ throw new UnsupportedError('Unexpected state ${state.runtimeType}');
+ }
+ }
+ return sb.toString();
+ }
+}
+
+/// Enum for different kinds of [ReferenceName]s.
+enum ReferenceNameKind {
+ /// A reference name without information.
+ Unknown,
+
+ /// A reference name of a library.
+ Library,
+
+ /// A reference name of a class or extension.
+ Declaration,
+
+ /// A reference name of a typedef or member.
+ Member,
+}
+
+/// Abstract representation of a [Reference] or [CanonicalName].
+///
+/// This is used to determine nominality of [Reference]s consistently,
+/// regardless of whether the [Reference] has an attached node or canonical
+/// name.
+class ReferenceName {
+ final ReferenceNameKind kind;
+ final ReferenceName? parent;
+ final String? name;
+ final String? uri;
+
+ ReferenceName.internal(this.kind, this.name, [this.parent, this.uri]);
+
+ factory ReferenceName.fromNamedNode(NamedNode node) {
+ if (node is Library) {
+ return new ReferenceName.internal(
+ ReferenceNameKind.Library, node.importUri.toString());
+ } else if (node is Extension) {
+ return new ReferenceName.internal(ReferenceNameKind.Declaration,
+ node.name, new ReferenceName.fromNamedNode(node.enclosingLibrary));
+ } else if (node is Class) {
+ return new ReferenceName.internal(ReferenceNameKind.Declaration,
+ node.name, new ReferenceName.fromNamedNode(node.enclosingLibrary));
+ } else if (node is Typedef) {
+ return new ReferenceName.internal(ReferenceNameKind.Member, node.name,
+ new ReferenceName.fromNamedNode(node.enclosingLibrary));
+ } else if (node is Member) {
+ Class? enclosingClass = node.enclosingClass;
+ Reference? libraryReference = node.name.libraryName;
+ String? uri;
+ if (libraryReference != null) {
+ Library? library = libraryReference.node as Library?;
+ if (library != null) {
+ uri = library.importUri.toString();
+ } else {
+ uri = libraryReference.canonicalName?.name;
+ }
+ }
+ if (enclosingClass != null) {
+ return new ReferenceName.internal(
+ ReferenceNameKind.Member,
+ node.name.text,
+ new ReferenceName.fromNamedNode(enclosingClass),
+ uri);
+ } else {
+ return new ReferenceName.internal(
+ ReferenceNameKind.Member,
+ node.name.text,
+ new ReferenceName.fromNamedNode(node.enclosingLibrary),
+ uri);
+ }
+ } else {
+ throw new ArgumentError(
+ 'Unexpected named node ${node} (${node.runtimeType})');
+ }
+ }
+
+ factory ReferenceName.fromCanonicalName(CanonicalName canonicalName) {
+ List<CanonicalName> parents = [];
+ CanonicalName? parent = canonicalName;
+ while (parent != null) {
+ parents.add(parent);
+ parent = parent.parent;
+ }
+ parents = parents.reversed.toList();
+ ReferenceName? referenceName;
+ ReferenceNameKind kind = ReferenceNameKind.Declaration;
+ for (int index = 1; index < parents.length; index++) {
+ if (index == 1) {
+ // Library reference.
+ referenceName = new ReferenceName.internal(
+ ReferenceNameKind.Library, parents[index].name);
+ } else if (CanonicalName.isSymbolicName(parents[index].name)) {
+ // Skip symbolic names
+ kind = ReferenceNameKind.Member;
+ } else {
+ if (index + 2 == parents.length) {
+ // This is a private name.
+ referenceName = new ReferenceName.internal(ReferenceNameKind.Member,
+ parents[index + 1].name, referenceName, parents[index].name);
+ break;
+ } else {
+ referenceName = new ReferenceName.internal(
+ kind, parents[index].name, referenceName);
+ }
+ }
+ }
+ return referenceName ??
+ new ReferenceName.internal(ReferenceNameKind.Unknown, null);
+ }
+
+ String? get libraryUri {
+ if (kind == ReferenceNameKind.Library) {
+ return name;
+ } else {
+ return parent?.libraryUri;
+ }
+ }
+
+ String? get declarationName {
+ if (kind == ReferenceNameKind.Declaration) {
+ return name;
+ } else {
+ return parent?.declarationName;
+ }
+ }
+
+ String? get memberName {
+ if (kind == ReferenceNameKind.Member) {
+ return name;
+ }
+ return null;
+ }
+
+ String? get memberUri {
+ if (kind == ReferenceNameKind.Member) {
+ return uri;
+ }
+ return null;
+ }
+
+ static ReferenceName? fromReference(Reference? reference) {
+ if (reference == null) {
+ return null;
+ }
+ NamedNode? node = reference.node;
+ if (node != null) {
+ return new ReferenceName.fromNamedNode(node);
+ }
+ CanonicalName? canonicalName = reference.canonicalName;
+ if (canonicalName != null) {
+ return new ReferenceName.fromCanonicalName(canonicalName);
+ }
+ return new ReferenceName.internal(ReferenceNameKind.Unknown, null);
+ }
+
+ @override
+ int get hashCode =>
+ name.hashCode * 13 + uri.hashCode * 17 + parent.hashCode * 19;
+
+ @override
+ bool operator ==(Object other) {
+ if (identical(this, other)) return true;
+ return other is ReferenceName &&
+ name == other.name &&
+ uri == other.uri &&
+ parent == other.parent;
+ }
+
+ @override
+ String toString() {
+ if (parent != null) {
+ return '${parent}/$name';
+ } else if (name != null) {
+ return '/$name';
+ } else {
+ return '<null>';
+ }
+ }
+}
diff --git a/pkg/kernel/lib/src/heap.dart b/pkg/kernel/lib/src/heap.dart
index ecb3f0a..5cbeeab 100644
--- a/pkg/kernel/lib/src/heap.dart
+++ b/pkg/kernel/lib/src/heap.dart
@@ -12,7 +12,7 @@
void add(T item) {
int index = _items.length;
- _items.length += 1;
+ _items.add(item);
while (index > 0) {
T parent = _items[_parentIndex(index)];
if (sortsBefore(parent, item)) break;
diff --git a/pkg/kernel/lib/src/union_find.dart b/pkg/kernel/lib/src/union_find.dart
new file mode 100644
index 0000000..4dffab0
--- /dev/null
+++ b/pkg/kernel/lib/src/union_find.dart
@@ -0,0 +1,76 @@
+// 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.
+
+import 'dart:collection';
+
+class UnionFindNode<T> {
+ final T value;
+ UnionFindNode<T>? parent;
+
+ UnionFindNode(this.value);
+}
+
+class UnionFind<T> {
+ final bool _useIdentity;
+ final Map<T, UnionFindNode<T>> _nodeMap;
+
+ UnionFind({bool useIdentity: false})
+ : _nodeMap = useIdentity ? new LinkedHashMap.identity() : {},
+ _useIdentity = useIdentity;
+
+ UnionFind<T> clone() {
+ UnionFind<T> newUnionFind = new UnionFind<T>(useIdentity: _useIdentity);
+ Map<UnionFindNode<T>, UnionFindNode<T>> oldToNewMap = {};
+
+ UnionFindNode<T> getNewNode(UnionFindNode<T> oldNode) {
+ UnionFindNode<T> newNode = newUnionFind[oldNode.value];
+ return oldToNewMap[oldNode] = newNode;
+ }
+
+ for (UnionFindNode<T> oldNode in _nodeMap.values) {
+ UnionFindNode<T> newNode = getNewNode(oldNode);
+ if (oldNode.parent != null) {
+ newNode.parent = getNewNode(oldNode.parent!);
+ }
+ }
+ return newUnionFind;
+ }
+
+ UnionFindNode<T> operator [](T value) =>
+ _nodeMap[value] ??= new UnionFindNode<T>(value);
+
+ Iterable<UnionFindNode<T>> get nodes => _nodeMap.values;
+
+ Iterable<T> get values => nodes.map((n) => n.value);
+
+ UnionFindNode<T> findNode(UnionFindNode<T> node) {
+ if (node.parent != null) {
+ return node.parent = findNode(node.parent!);
+ }
+ return node;
+ }
+
+ void unionOfValues(T a, T b) {
+ unionOfNodes(this[a], this[b]);
+ }
+
+ UnionFindNode<T> unionOfNodes(UnionFindNode<T> a, UnionFindNode<T> b) {
+ UnionFindNode<T> rootA = findNode(a);
+ UnionFindNode<T> rootB = findNode(b);
+ if (rootA != rootB) {
+ return rootB.parent = rootA;
+ }
+ return rootA;
+ }
+
+ bool valuesInSameSet(T a, T b) {
+ UnionFindNode<T>? node1 = _nodeMap[a];
+ UnionFindNode<T>? node2 = _nodeMap[b];
+ return node1 != null && node2 != null && nodesInSameSet(node1, node2);
+ }
+
+ bool nodesInSameSet(UnionFindNode<T> a, UnionFindNode<T> b) {
+ return findNode(a) == findNode(b);
+ }
+}
diff --git a/pkg/kernel/lib/target/targets.dart b/pkg/kernel/lib/target/targets.dart
index 90615e8..55a69cd 100644
--- a/pkg/kernel/lib/target/targets.dart
+++ b/pkg/kernel/lib/target/targets.dart
@@ -74,7 +74,7 @@
}
abstract class DiagnosticReporter<M, C> {
- void report(M message, int charOffset, int length, Uri fileUri,
+ void report(M message, int charOffset, int length, Uri? fileUri,
{List<C> context});
}
@@ -256,7 +256,7 @@
Map<String, String>? environmentDefines,
DiagnosticReporter diagnosticReporter,
ReferenceFromIndex? referenceFromIndex,
- {void logger(String msg),
+ {void Function(String msg)? logger,
ChangedStructureNotifier? changedStructureNotifier});
/// Perform target-specific modular transformations on the given program.
@@ -354,7 +354,7 @@
/// synthesized top level functions.
int get enabledConstructorTearOffLowerings;
- /// Returns `true` if lowering of constructor tear offs is enabled.
+ /// Returns `true` if lowering of generative constructor tear offs is enabled.
///
/// This is determined by the [enabledConstructorTearOffLowerings] mask.
bool get isConstructorTearOffLoweringEnabled =>
@@ -362,6 +362,23 @@
ConstructorTearOffLowering.constructors) !=
0;
+ /// Returns `true` if lowering of non-redirecting factory tear offs is
+ /// enabled.
+ ///
+ /// This is determined by the [enabledConstructorTearOffLowerings] mask.
+ bool get isFactoryTearOffLoweringEnabled =>
+ (enabledConstructorTearOffLowerings &
+ ConstructorTearOffLowering.factories) !=
+ 0;
+
+ /// Returns `true` if lowering of redirecting factory tear offs is enabled.
+ ///
+ /// This is determined by the [enabledConstructorTearOffLowerings] mask.
+ bool get isRedirectingFactoryTearOffLoweringEnabled =>
+ (enabledConstructorTearOffLowerings &
+ ConstructorTearOffLowering.redirectingFactories) !=
+ 0;
+
/// Returns `true` if lowering of typedef tear offs is enabled.
///
/// This is determined by the [enabledConstructorTearOffLowerings] mask.
@@ -409,8 +426,6 @@
/// with the accessed getter or field as the interface target.
bool get supportsExplicitGetterCalls;
- bool get supportsNewMethodInvocationEncoding;
-
/// Builds an expression that instantiates an [Invocation] that can be passed
/// to [noSuchMethod].
Expression instantiateInvocation(CoreTypes coreTypes, Expression receiver,
@@ -478,9 +493,6 @@
!flags.forceNoExplicitGetterCallsForTesting;
@override
- bool get supportsNewMethodInvocationEncoding => true;
-
- @override
int get enabledConstructorTearOffLowerings =>
flags.forceConstructorTearOffLoweringForTesting;
@@ -635,13 +647,19 @@
}
class ConstructorTearOffLowering {
- /// Create top level functions to use as tear offs of constructors.
+ /// Create static functions to use as tear offs of generative constructors.
static const int constructors = 1 << 0;
- /// Create top level functions to use as tear offs of non trivial redirecting
- /// factory constructors and typedefs.
- static const int typedefs = 1 << 1;
+ /// Create static functions to use as tear offs of non-redirecting factories.
+ static const int factories = 1 << 1;
+
+ /// Create static functions to use as tear offs of redirecting factories.
+ static const int redirectingFactories = 1 << 2;
+
+ /// Create top level functions to use as tear offs of typedefs that are not
+ /// proper renames.
+ static const int typedefs = 1 << 3;
static const int none = 0;
- static const int all = (1 << 2) - 1;
+ static const int all = (1 << 4) - 1;
}
diff --git a/pkg/kernel/lib/text/ast_to_text.dart b/pkg/kernel/lib/text/ast_to_text.dart
index 197bdfa..eacfa1e 100644
--- a/pkg/kernel/lib/text/ast_to_text.dart
+++ b/pkg/kernel/lib/text/ast_to_text.dart
@@ -1243,20 +1243,13 @@
name: node.name, initializers: node.initializers);
}
- visitRedirectingFactoryConstructor(RedirectingFactoryConstructor node) {
+ visitRedirectingFactory(RedirectingFactory node) {
writeAnnotationList(node.annotations);
writeIndentation();
writeModifier(node.isExternal, 'external');
writeModifier(node.isConst, 'const');
writeWord('redirecting_factory');
-
- // ignore: unnecessary_null_comparison
- if (node.name != null) {
- writeName(node.name);
- }
- writeTypeParameterList(node.typeParameters);
- writeParameterList(node.positionalParameters, node.namedParameters,
- node.requiredParameterCount);
+ writeFunction(node.function, name: node.name);
writeSpaced('=');
writeMemberReferenceFromReference(node.targetReference!);
if (node.typeArguments.isNotEmpty) {
@@ -1327,7 +1320,7 @@
node.fields.forEach(writeNode);
node.constructors.forEach(writeNode);
node.procedures.forEach(writeNode);
- node.redirectingFactoryConstructors.forEach(writeNode);
+ node.redirectingFactories.forEach(writeNode);
--indentation;
writeIndentation();
endLine('}');
@@ -1545,23 +1538,6 @@
writeSymbol('null');
}
- visitMethodInvocation(MethodInvocation node) {
- writeExpression(node.receiver, Precedence.PRIMARY);
- writeSymbol('.');
- writeInterfaceTarget(node.name, node.interfaceTargetReference);
- List<String> flags = <String>[];
- if (node.isInvariant) {
- flags.add('Invariant');
- }
- if (node.isBoundsSafe) {
- flags.add('BoundsSafe');
- }
- if (flags.isNotEmpty) {
- write('{${flags.join(',')}}');
- }
- writeNode(node.arguments);
- }
-
visitSuperMethodInvocation(SuperMethodInvocation node) {
writeWord('super');
writeSymbol('.');
@@ -1992,12 +1968,6 @@
writeSymbol('}');
}
- visitPropertyGet(PropertyGet node) {
- writeExpression(node.receiver, Precedence.PRIMARY);
- writeSymbol('.');
- writeInterfaceTarget(node.name, node.interfaceTargetReference);
- }
-
visitDynamicSet(DynamicSet node) {
writeExpression(node.receiver, Precedence.PRIMARY);
_writeDynamicAccessKind(node.kind);
@@ -2015,14 +1985,6 @@
writeExpression(node.value);
}
- visitPropertySet(PropertySet node) {
- writeExpression(node.receiver, Precedence.PRIMARY);
- writeSymbol('.');
- writeInterfaceTarget(node.name, node.interfaceTargetReference);
- writeSpaced('=');
- writeExpression(node.value);
- }
-
visitSuperPropertyGet(SuperPropertyGet node) {
writeWord('super');
writeSymbol('.');
@@ -2052,7 +2014,25 @@
}
visitConstructorTearOff(ConstructorTearOff node) {
- writeMemberReferenceFromReference(node.constructorReference);
+ writeMemberReferenceFromReference(node.targetReference);
+ }
+
+ visitRedirectingFactoryTearOff(RedirectingFactoryTearOff node) {
+ writeMemberReferenceFromReference(node.targetReference);
+ }
+
+ visitTypedefTearOff(TypedefTearOff node) {
+ writeTypeParameterList(node.typeParameters);
+ state = SYMBOL;
+ writeSymbol('.(');
+ writeNode(node.expression);
+ if (node.typeArguments.isNotEmpty) {
+ writeSymbol('<');
+ writeList(node.typeArguments, writeType);
+ writeSymbol('>');
+ }
+ writeSymbol(')');
+ state = WORD;
}
visitExpressionStatement(ExpressionStatement node) {
@@ -2667,9 +2647,14 @@
writeIndentation();
writeConstantReference(node);
writeSpaced('=');
- writeWord('partial-instantiation');
+ writeWord('instantiation');
writeSpace();
- writeMemberReferenceFromReference(node.tearOffConstant.memberReference);
+ Constant tearOffConstant = node.tearOffConstant;
+ if (tearOffConstant is TearOffConstant) {
+ writeMemberReferenceFromReference(tearOffConstant.targetReference);
+ } else {
+ writeConstantReference(tearOffConstant);
+ }
writeSpace();
writeSymbol('<');
writeList(node.types, writeType);
@@ -2688,9 +2673,29 @@
writeIndentation();
writeConstantReference(node);
writeSpaced('=');
- writeWord('tearoff');
+ writeWord('static-tearoff');
writeSpace();
- writeMemberReferenceFromReference(node.memberReference);
+ writeMemberReferenceFromReference(node.targetReference);
+ endLine();
+ }
+
+ visitTypedefTearOffConstant(TypedefTearOffConstant node) {
+ writeIndentation();
+ writeConstantReference(node);
+ writeSpaced('=');
+ writeWord('typedef-tearoff');
+ writeSpace();
+ writeTypeParameterList(node.parameters);
+ state = SYMBOL;
+ writeSymbol('.(');
+ writeConstantReference(node.tearOffConstant);
+ if (node.types.isNotEmpty) {
+ writeSymbol('<');
+ writeList(node.types, writeType);
+ writeSymbol('>');
+ }
+ writeSymbol(')');
+ state = WORD;
endLine();
}
@@ -2704,6 +2709,27 @@
endLine();
}
+ visitConstructorTearOffConstant(ConstructorTearOffConstant node) {
+ writeIndentation();
+ writeConstantReference(node);
+ writeSpaced('=');
+ writeWord('constructor-tearoff');
+ writeSpace();
+ writeMemberReferenceFromReference(node.targetReference);
+ endLine();
+ }
+
+ visitRedirectingFactoryTearOffConstant(
+ RedirectingFactoryTearOffConstant node) {
+ writeIndentation();
+ writeConstantReference(node);
+ writeSpaced('=');
+ writeWord('redirecting-factory-tearoff');
+ writeSpace();
+ writeMemberReferenceFromReference(node.targetReference);
+ endLine();
+ }
+
defaultNode(Node node) {
write('<${node.runtimeType}>');
}
@@ -2768,9 +2794,6 @@
int visitInvalidExpression(InvalidExpression node) => CALLEE;
@override
- int visitMethodInvocation(MethodInvocation node) => CALLEE;
-
- @override
int visitInstanceInvocation(InstanceInvocation node) => CALLEE;
@override
@@ -2874,9 +2897,6 @@
int visitVariableSet(VariableSet node) => EXPRESSION;
@override
- int visitPropertyGet(PropertyGet node) => PRIMARY;
-
- @override
int visitInstanceGet(InstanceGet node) => PRIMARY;
@override
@@ -2889,9 +2909,6 @@
int visitFunctionTearOff(FunctionTearOff node) => PRIMARY;
@override
- int visitPropertySet(PropertySet node) => EXPRESSION;
-
- @override
int visitSuperPropertyGet(SuperPropertyGet node) => PRIMARY;
@override
@@ -2910,6 +2927,9 @@
int visitConstructorTearOff(ConstructorTearOff node) => PRIMARY;
@override
+ int visitRedirectingFactoryTearOff(RedirectingFactoryTearOff node) => PRIMARY;
+
+ @override
int visitTypedefTearOff(TypedefTearOff node) => EXPRESSION;
@override
diff --git a/pkg/compiler/lib/src/ir/debug.dart b/pkg/kernel/lib/text/debug_printer.dart
similarity index 93%
rename from pkg/compiler/lib/src/ir/debug.dart
rename to pkg/kernel/lib/text/debug_printer.dart
index 3b9e11a..fa700c1 100644
--- a/pkg/compiler/lib/src/ir/debug.dart
+++ b/pkg/kernel/lib/text/debug_printer.dart
@@ -8,14 +8,14 @@
import 'package:kernel/ast.dart';
-import '../util/util.dart' show Indentation, Tagging;
+import 'indentation.dart' show Indentation, Tagging;
class DebugPrinter extends Visitor<void>
with Indentation, Tagging<Node>, VisitorVoidMixin {
@override
StringBuffer sb = new StringBuffer();
- void visitNodeWithChildren(Node node, String type, [Map params]) {
+ void visitNodeWithChildren(Node node, String type, [Map? params]) {
openNode(node, type, params);
node.visitChildren(this);
closeNode();
@@ -102,7 +102,7 @@
/// Pretty-prints given node tree into string.
static String prettyPrint(Node node) {
- var p = new DebugPrinter();
+ DebugPrinter p = new DebugPrinter();
node.accept(p);
return p.sb.toString();
}
diff --git a/pkg/compiler/lib/src/util/indentation.dart b/pkg/kernel/lib/text/indentation.dart
similarity index 88%
rename from pkg/compiler/lib/src/util/indentation.dart
rename to pkg/kernel/lib/text/indentation.dart
index fb7cc21..4c9c344 100644
--- a/pkg/compiler/lib/src/util/indentation.dart
+++ b/pkg/kernel/lib/text/indentation.dart
@@ -2,8 +2,6 @@
// 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.
-part of dart2js.util;
-
/// Indentation utility class. Should be used as a mixin in most cases.
class Indentation {
/// The current indentation string.
@@ -46,7 +44,7 @@
/// upon return of [f] and returning its result.
indentBlock(Function f) {
indentMore();
- var result = f();
+ dynamic result = f();
indentLess();
return result;
}
@@ -54,19 +52,17 @@
abstract class Tagging<N> implements Indentation {
StringBuffer sb = new StringBuffer();
- Link<String> tagStack = const Link<String>();
+ List<String> tagStack = [];
void pushTag(String tag) {
- tagStack = tagStack.prepend(tag);
+ tagStack.add(tag);
indentMore();
}
String popTag() {
assert(!tagStack.isEmpty);
- String tag = tagStack.head;
- tagStack = tagStack.tail;
indentLess();
- return tag;
+ return tagStack.removeLast();
}
/// Adds given string to result string.
@@ -81,7 +77,7 @@
/// The method "opens" the node, meaning that all output after calling
/// this method and before calling closeNode() will represent contents
/// of given node.
- void openNode(N node, String type, [Map params]) {
+ void openNode(N node, String type, [Map? params]) {
if (params == null) params = new Map();
addCurrentIndent();
sb.write("<");
@@ -92,7 +88,7 @@
}
/// Adds given node to result string.
- void openAndCloseNode(N node, String type, [Map params]) {
+ void openAndCloseNode(N node, String type, [Map? params]) {
if (params == null) params = {};
addCurrentIndent();
sb.write("<");
@@ -110,7 +106,7 @@
sb.write(">\n");
}
- void addTypeWithParams(String type, [Map params]) {
+ void addTypeWithParams(String type, [Map? params]) {
if (params == null) params = new Map();
sb.write("${type}");
params.forEach((k, v) {
@@ -133,5 +129,5 @@
}
/// Converts a parameter value into a string.
- String valueToString(var value) => value;
+ String valueToString(dynamic value) => value;
}
diff --git a/pkg/kernel/lib/text/serializer_combinators.dart b/pkg/kernel/lib/text/serializer_combinators.dart
index 7af498e..aae9ea2 100644
--- a/pkg/kernel/lib/text/serializer_combinators.dart
+++ b/pkg/kernel/lib/text/serializer_combinators.dart
@@ -714,7 +714,7 @@
/// Serializes an object and uses it as a binder for the name that is retrieved
/// from the object using [nameGetter] and (temporarily) modified using
/// [nameSetter]. The binder is added to the enclosing environment.
-class Binder<T extends Node> extends TextSerializer<Tuple2<String, T>> {
+class Binder<T extends Node> extends TextSerializer<Tuple2<String?, T>> {
final Tuple2Serializer<String, T> namedContents;
Binder(TextSerializer<T> contents)
@@ -733,13 +733,13 @@
return new Tuple2(name, object);
}
- void writeTo(StringBuffer buffer, Tuple2<String, T> namedObject,
+ void writeTo(StringBuffer buffer, Tuple2<String?, T> namedObject,
SerializationState? state) {
if (state == null) {
throw StateError(
"No serialization state provided for ${runtimeType}.writeTo.");
}
- String nameClue = namedObject.first;
+ String? nameClue = namedObject.first;
T object = namedObject.second;
String distinctName =
state.environment.addBinder(object, nameClue: nameClue);
diff --git a/pkg/kernel/lib/text/text_serializer.dart b/pkg/kernel/lib/text/text_serializer.dart
index 0c4f26e..5d740c4 100644
--- a/pkg/kernel/lib/text/text_serializer.dart
+++ b/pkg/kernel/lib/text/text_serializer.dart
@@ -70,8 +70,6 @@
String visitLet(Let _) => "let";
- String visitPropertyGet(PropertyGet _) => "get-prop";
- String visitPropertySet(PropertySet _) => "set-prop";
String visitInstanceGet(InstanceGet _) => "get-instance";
String visitInstanceSet(InstanceSet _) => "set-instance";
String visitDynamicGet(DynamicGet _) => "get-dynamic";
@@ -80,7 +78,6 @@
String visitFunctionTearOff(FunctionTearOff _) => "tearoff-function";
String visitSuperPropertyGet(SuperPropertyGet _) => "get-super";
String visitSuperPropertySet(SuperPropertySet _) => "set-super";
- String visitMethodInvocation(MethodInvocation _) => "invoke-method";
String visitInstanceInvocation(InstanceInvocation _) => "invoke-instance";
String visitInstanceGetterInvocation(InstanceGetterInvocation _) =>
"invoke-instance-getter";
@@ -97,6 +94,10 @@
String visitStaticGet(StaticGet _) => "get-static";
String visitStaticSet(StaticSet _) => "set-static";
String visitStaticTearOff(StaticTearOff _) => "tearoff-static";
+ String visitConstructorTearOff(ConstructorTearOff _) => "tearoff-constructor";
+ String visitRedirectingFactoryTearOff(RedirectingFactoryTearOff _) =>
+ "tearoff-redirecting-factory";
+ String visitTypedefTearOff(TypedefTearOff _) => "tearoff-typedef";
String visitStaticInvocation(StaticInvocation expression) {
return expression.isConst ? "invoke-const-static" : "invoke-static";
}
@@ -415,33 +416,6 @@
return new Let(tuple.first, tuple.second);
}
-TextSerializer<PropertyGet> propertyGetSerializer = new Wrapped(
- unwrapPropertyGet,
- wrapPropertyGet,
- new Tuple2Serializer(expressionSerializer, nameSerializer));
-
-Tuple2<Expression, Name> unwrapPropertyGet(PropertyGet expression) {
- return new Tuple2(expression.receiver, expression.name);
-}
-
-PropertyGet wrapPropertyGet(Tuple2<Expression, Name> tuple) {
- return new PropertyGet(tuple.first, tuple.second);
-}
-
-TextSerializer<PropertySet> propertySetSerializer = new Wrapped(
- unwrapPropertySet,
- wrapPropertySet,
- new Tuple3Serializer(
- expressionSerializer, nameSerializer, expressionSerializer));
-
-Tuple3<Expression, Name, Expression> unwrapPropertySet(PropertySet expression) {
- return new Tuple3(expression.receiver, expression.name, expression.value);
-}
-
-PropertySet wrapPropertySet(Tuple3<Expression, Name, Expression> tuple) {
- return new PropertySet(tuple.first, tuple.second, tuple.third);
-}
-
TextSerializer<InstanceGet> instanceGetSerializer = new Wrapped<
Tuple5<InstanceAccessKind, Expression, Name, CanonicalName, DartType>,
InstanceGet>(
@@ -586,22 +560,6 @@
return new SuperPropertySet(tuple.first, tuple.second, null);
}
-TextSerializer<MethodInvocation> methodInvocationSerializer = new Wrapped(
- unwrapMethodInvocation,
- wrapMethodInvocation,
- new Tuple3Serializer(
- expressionSerializer, nameSerializer, argumentsSerializer));
-
-Tuple3<Expression, Name, Arguments> unwrapMethodInvocation(
- MethodInvocation expression) {
- return new Tuple3(expression.receiver, expression.name, expression.arguments);
-}
-
-MethodInvocation wrapMethodInvocation(
- Tuple3<Expression, Name, Arguments> tuple) {
- return new MethodInvocation(tuple.first, tuple.second, tuple.third);
-}
-
const Map<InstanceAccessKind, String> instanceAccessKindToName = const {
InstanceAccessKind.Instance: "instance",
InstanceAccessKind.Object: "object",
@@ -931,6 +889,55 @@
return new StaticTearOff.byReference(name.reference);
}
+const TextSerializer<ConstructorTearOff> constructorTearOffSerializer =
+ const Wrapped(unwrapConstructorTearOff, wrapConstructorTearOff,
+ canonicalNameSerializer);
+
+CanonicalName unwrapConstructorTearOff(ConstructorTearOff expression) {
+ return expression.targetReference.canonicalName!;
+}
+
+ConstructorTearOff wrapConstructorTearOff(CanonicalName name) {
+ return new ConstructorTearOff.byReference(name.reference);
+}
+
+const TextSerializer<RedirectingFactoryTearOff>
+ redirectingFactoryTearOffSerializer = const Wrapped(
+ unwrapRedirectingFactoryTearOff,
+ wrapRedirectingFactoryTearOff,
+ canonicalNameSerializer);
+
+CanonicalName unwrapRedirectingFactoryTearOff(
+ RedirectingFactoryTearOff expression) {
+ return expression.targetReference.canonicalName!;
+}
+
+RedirectingFactoryTearOff wrapRedirectingFactoryTearOff(CanonicalName name) {
+ return new RedirectingFactoryTearOff.byReference(name.reference);
+}
+
+final TextSerializer<TypedefTearOff> typedefTearOffSerializer = new Wrapped<
+ Tuple2<List<TypeParameter>, Tuple2<Expression, List<DartType>>>,
+ TypedefTearOff>(
+ unwrapTypedefTearOff,
+ wrapTypedefTearOff,
+ Bind(
+ typeParametersSerializer,
+ Tuple2Serializer(
+ expressionSerializer, ListSerializer(dartTypeSerializer))));
+
+Tuple2<List<TypeParameter>, Tuple2<Expression, List<DartType>>>
+ unwrapTypedefTearOff(TypedefTearOff node) {
+ return new Tuple2(
+ node.typeParameters, new Tuple2(node.expression, node.typeArguments));
+}
+
+TypedefTearOff wrapTypedefTearOff(
+ Tuple2<List<TypeParameter>, Tuple2<Expression, List<DartType>>> tuple) {
+ return new TypedefTearOff(
+ tuple.first, tuple.second.first, tuple.second.second);
+}
+
TextSerializer<StaticSet> staticSetSerializer = new Wrapped(
unwrapStaticSet,
wrapStaticSet,
@@ -1653,7 +1660,7 @@
(ls) => Tuple2(ls, ls.body),
(t) => t.first..body = t.second,
Bind(
- Wrapped<Tuple2<String, LabeledStatement>, LabeledStatement>(
+ Wrapped<Tuple2<String?, LabeledStatement>, LabeledStatement>(
(ls) => Tuple2("L", ls),
(t) => t.second,
Binder(Wrapped(
@@ -1722,7 +1729,7 @@
}
TextSerializer<SwitchCase> switchCaseCaseSerializer =
- Wrapped<Tuple2<String, SwitchCase>, SwitchCase>(
+ Wrapped<Tuple2<String?, SwitchCase>, SwitchCase>(
(w) => Tuple2("L", w),
(u) => u.second,
Binder(Wrapped<List<Expression>, SwitchCase>(
@@ -1731,7 +1738,7 @@
ListSerializer(expressionSerializer))));
TextSerializer<SwitchCase> switchCaseDefaultSerializer = Wrapped<
- Tuple2<String, SwitchCase>, SwitchCase>(
+ Tuple2<String?, SwitchCase>, SwitchCase>(
(w) => Tuple2("L", w),
(u) => u.second,
Binder(
@@ -1836,8 +1843,7 @@
Procedure.FlagAbstract: "abstract",
Procedure.FlagExternal: "external",
Procedure.FlagConst: "const",
- Procedure.FlagRedirectingFactoryConstructor:
- "redirecting-factory-constructor",
+ Procedure.FlagRedirectingFactory: "redirecting-factory-constructor",
Procedure.FlagExtensionMember: "extension-member",
Procedure.FlagNonNullableByDefault: "non-nullable-by-default",
Procedure.FlagSynthetic: "synthetic",
@@ -1906,20 +1912,18 @@
ListSerializer(
Case(ConstructorFlagTagger(), convertFlagsMap(constructorFlagToName))));
-const Map<int, String> redirectingFactoryConstructorFlagToName = const {
- RedirectingFactoryConstructor.FlagConst: "const",
- RedirectingFactoryConstructor.FlagExternal: "external",
- RedirectingFactoryConstructor.FlagNonNullableByDefault:
- "non-nullable-by-default",
+const Map<int, String> redirectingFactoryFlagToName = const {
+ RedirectingFactory.FlagConst: "const",
+ RedirectingFactory.FlagExternal: "external",
+ RedirectingFactory.FlagNonNullableByDefault: "non-nullable-by-default",
};
-class RedirectingFactoryConstructorFlagTagger implements Tagger<int> {
- const RedirectingFactoryConstructorFlagTagger();
+class RedirectingFactoryFlagTagger implements Tagger<int> {
+ const RedirectingFactoryFlagTagger();
String tag(int flag) {
- return redirectingFactoryConstructorFlagToName[flag] ??
- (throw StateError(
- "Unknown RedirectingFactoryConstructor flag value: ${flag}."));
+ return redirectingFactoryFlagToName[flag] ??
+ (throw StateError("Unknown RedirectingFactory flag value: ${flag}."));
}
}
@@ -1929,8 +1933,8 @@
.where((f) => f != 0)
.toList(),
(u) => u.fold(0, (fs, f) => fs |= f),
- ListSerializer(Case(RedirectingFactoryConstructorFlagTagger(),
- convertFlagsMap(redirectingFactoryConstructorFlagToName))));
+ ListSerializer(Case(RedirectingFactoryFlagTagger(),
+ convertFlagsMap(redirectingFactoryFlagToName))));
class MemberTagger implements Tagger<Member> {
const MemberTagger();
@@ -1940,7 +1944,7 @@
return node.hasSetter ? "mutable-field" : "immutable-field";
} else if (node is Constructor) {
return "constructor";
- } else if (node is RedirectingFactoryConstructor) {
+ } else if (node is RedirectingFactory) {
return "redirecting-factory-constructor";
} else if (node is Procedure) {
switch (node.kind) {
@@ -2036,57 +2040,25 @@
Tuple4Serializer(nameSerializer, constructorFlagsSerializer,
functionNodeWithInitializersSerializer, UriSerializer()));
-TextSerializer<RedirectingFactoryConstructor>
- redirectingFactoryConstructorSerializer
+TextSerializer<RedirectingFactory> redirectingFactoryConstructorSerializer
// Comment added to direct formatter.
= Wrapped<
- Tuple5<
- Name,
- int,
- CanonicalName,
- Tuple2<
- List<TypeParameter>,
- Tuple4<List<VariableDeclaration>, List<VariableDeclaration>,
- List<VariableDeclaration>, List<DartType>>>,
- Uri>,
- RedirectingFactoryConstructor>(
- (w) => Tuple5(
- w.name,
- w.flags,
- w.targetReference!.canonicalName!,
- Tuple2(
- w.typeParameters,
- Tuple4(
- w.positionalParameters
- .take(w.requiredParameterCount)
- .toList(),
- w.positionalParameters
- .skip(w.requiredParameterCount)
- .toList(),
- w.namedParameters,
- w.typeArguments)),
- w.fileUri),
- (u) => RedirectingFactoryConstructor(u.third.reference,
+ Tuple6<Name, int, FunctionNode, CanonicalName, List<DartType>, Uri>,
+ RedirectingFactory>(
+ (w) => Tuple6(w.name, w.flags, w.function,
+ w.targetReference!.canonicalName!, w.typeArguments, w.fileUri),
+ (u) => RedirectingFactory(u.fourth.reference,
name: u.first,
- typeParameters: u.fourth.first,
- positionalParameters:
- u.fourth.second.first + u.fourth.second.second,
- requiredParameterCount: u.fourth.second.first.length,
- namedParameters: u.fourth.second.third,
- typeArguments: u.fourth.second.fourth,
- fileUri: u.fifth)
+ function: u.third,
+ typeArguments: u.fifth,
+ fileUri: u.sixth)
..flags = u.second,
- Tuple5Serializer(
+ Tuple6Serializer(
nameSerializer,
redirectingFactoryConstructorFlagsSerializer,
+ functionNodeSerializer,
CanonicalNameSerializer(),
- Bind(
- typeParametersSerializer,
- Tuple4Serializer(
- ListSerializer(variableDeclarationSerializer),
- ListSerializer(variableDeclarationSerializer),
- ListSerializer(variableDeclarationSerializer),
- ListSerializer(dartTypeSerializer))),
+ ListSerializer(dartTypeSerializer),
UriSerializer()));
Case<Member> memberSerializer = new Case.uninitialized(const MemberTagger());
@@ -2210,7 +2182,14 @@
String visitStringConstant(StringConstant node) => "const-string";
String visitSymbolConstant(SymbolConstant node) => "const-symbol";
String visitStaticTearOffConstant(StaticTearOffConstant node) =>
- "const-tearoff";
+ "const-tearoff-static";
+ String visitConstructorTearOffConstant(ConstructorTearOffConstant node) =>
+ "const-tearoff-constructor";
+ String visitRedirectingFactoryTearOffConstant(
+ RedirectingFactoryTearOffConstant node) =>
+ "const-tearoff-redirecting-factory";
+ String visitTypedefTearOffConstant(TypedefTearOffConstant node) =>
+ "const-tearoff-typedef";
String visitTypeLiteralConstant(TypeLiteralConstant node) => "const-type";
String visitUnevaluatedConstant(UnevaluatedConstant node) => "const-expr";
@@ -2256,11 +2235,11 @@
Wrapped<void, NullConstant>((w) => null, (u) => NullConstant(), Nothing());
TextSerializer<InstantiationConstant> instantiationConstantSerializer =
- Wrapped<Tuple2<TearOffConstant, List<DartType>>, InstantiationConstant>(
+ Wrapped<Tuple2<Constant, List<DartType>>, InstantiationConstant>(
(w) => Tuple2(w.tearOffConstant, w.types),
(u) => InstantiationConstant(u.first, u.second),
Tuple2Serializer(
- tearOffConstantSerializer, ListSerializer(dartTypeSerializer)));
+ constantSerializer, ListSerializer(dartTypeSerializer)));
TextSerializer<SetConstant> setConstantSerializer =
Wrapped<Tuple2<DartType, List<Constant>>, SetConstant>(
@@ -2279,12 +2258,48 @@
(u) => SymbolConstant(u.first, u.second?.reference),
Tuple2Serializer(DartString(), Optional(CanonicalNameSerializer())));
-TextSerializer<StaticTearOffConstant> tearOffConstantSerializer =
+TextSerializer<StaticTearOffConstant> staticTearOffConstantSerializer =
Wrapped<CanonicalName, StaticTearOffConstant>(
- (w) => w.memberReference.canonicalName!,
+ (w) => w.targetReference.canonicalName!,
(u) => StaticTearOffConstant.byReference(u.reference),
CanonicalNameSerializer());
+TextSerializer<ConstructorTearOffConstant>
+ constructorTearOffConstantSerializer =
+ Wrapped<CanonicalName, ConstructorTearOffConstant>(
+ (w) => w.targetReference.canonicalName!,
+ (u) => ConstructorTearOffConstant.byReference(u.reference),
+ CanonicalNameSerializer());
+
+TextSerializer<RedirectingFactoryTearOffConstant>
+ redirectingFactoryTearOffConstantSerializer =
+ Wrapped<CanonicalName, RedirectingFactoryTearOffConstant>(
+ (w) => w.targetReference.canonicalName!,
+ (u) => RedirectingFactoryTearOffConstant.byReference(u.reference),
+ CanonicalNameSerializer());
+
+final TextSerializer<TypedefTearOffConstant> typedefTearOffConstantSerializer =
+ new Wrapped<Tuple2<List<TypeParameter>, Tuple2<Constant, List<DartType>>>,
+ TypedefTearOffConstant>(
+ unwrapTypedefTearOffConstant,
+ wrapTypedefTearOffConstant,
+ Bind(
+ typeParametersSerializer,
+ Tuple2Serializer(
+ constantSerializer, ListSerializer(dartTypeSerializer))));
+
+Tuple2<List<TypeParameter>, Tuple2<Constant, List<DartType>>>
+ unwrapTypedefTearOffConstant(TypedefTearOffConstant node) {
+ return new Tuple2(
+ node.parameters, new Tuple2(node.tearOffConstant, node.types));
+}
+
+TypedefTearOffConstant wrapTypedefTearOffConstant(
+ Tuple2<List<TypeParameter>, Tuple2<Constant, List<DartType>>> tuple) {
+ return new TypedefTearOffConstant(
+ tuple.first, tuple.second.first as TearOffConstant, tuple.second.second);
+}
+
TextSerializer<TypeLiteralConstant> typeLiteralConstantSerializer =
Wrapped<DartType, TypeLiteralConstant>(
(w) => w.type, (u) => TypeLiteralConstant(u), dartTypeSerializer);
@@ -2559,8 +2574,6 @@
"map": mapLiteralSerializer,
"const-map": constMapLiteralSerializer,
"let": letSerializer,
- "get-prop": propertyGetSerializer,
- "set-prop": propertySetSerializer,
"get-instance": instanceGetSerializer,
"set-instance": instanceSetSerializer,
"get-dynamic": dynamicGetSerializer,
@@ -2569,7 +2582,6 @@
"tearoff-function": functionTearOffSerializer,
"get-super": superPropertyGetSerializer,
"set-super": superPropertySetSerializer,
- "invoke-method": methodInvocationSerializer,
"invoke-instance": instanceInvocationSerializer,
"invoke-instance-getter": instanceGetterInvocationSerializer,
"invoke-dynamic": dynamicInvocationSerializer,
@@ -2582,7 +2594,10 @@
"set-var": variableSetSerializer,
"get-static": staticGetSerializer,
"set-static": staticSetSerializer,
- "tearoff-static": staticGetSerializer,
+ "tearoff-static": staticTearOffSerializer,
+ "tearoff-constructor": constructorTearOffSerializer,
+ "tearoff-redirecting-factory": redirectingFactoryTearOffSerializer,
+ "tearoff-typedef": typedefTearOffSerializer,
"invoke-static": staticInvocationSerializer,
"invoke-const-static": constStaticInvocationSerializer,
"invoke-constructor": constructorInvocationSerializer,
@@ -2659,7 +2674,11 @@
"const-set": setConstantSerializer,
"const-string": stringConstantSerializer,
"const-symbol": symbolConstantSerializer,
- "const-tearoff": tearOffConstantSerializer,
+ "const-tearoff-static": staticTearOffConstantSerializer,
+ "const-tearoff-constructor": constructorTearOffConstantSerializer,
+ "const-tearoff-redirecting-factory":
+ redirectingFactoryTearOffConstantSerializer,
+ "const-tearoff-typedef": typedefTearOffConstantSerializer,
"const-type": typeLiteralConstantSerializer,
"const-expr": unevaluatedConstantSerializer,
"const-object": instanceConstantSerializer,
diff --git a/pkg/kernel/lib/transformations/async.dart b/pkg/kernel/lib/transformations/async.dart
index b18d98f..43fca30 100644
--- a/pkg/kernel/lib/transformations/async.dart
+++ b/pkg/kernel/lib/transformations/async.dart
@@ -115,21 +115,40 @@
return result;
}
+ // Wraps VariableGet in an unsafeCast if `type` isn't dynamic.
+ Expression unsafeCastVariableGet(
+ VariableDeclaration variable, DartType type) {
+ if (type != const DynamicType()) {
+ return StaticInvocation(
+ continuationRewriter.helper.unsafeCast,
+ Arguments(<Expression>[VariableGet(variable)],
+ types: <DartType>[type]));
+ }
+ return VariableGet(variable);
+ }
+
// Name an expression by emitting an assignment to a temporary variable.
Expression name(Expression expr) {
- // Allocate as dynamic as temps might be reused with different types.
- VariableDeclaration temp =
- allocateTemporary(nameIndex, const DynamicType());
- statements.add(ExpressionStatement(VariableSet(temp, expr)));
- // Type annotate the get via an unsafe cast since all temps are allocated
- // as dynamic.
DartType type = expr.getStaticType(_staticTypeContext);
- return StaticInvocation(continuationRewriter.helper.unsafeCast,
- Arguments(<Expression>[VariableGet(temp)], types: <DartType>[type]));
+ VariableDeclaration temp = allocateTemporary(nameIndex, type);
+ statements.add(ExpressionStatement(VariableSet(temp, expr)));
+ // Wrap in unsafeCast to make sure we pass type information even if we later
+ // have to re-type the temporary variable to dynamic.
+ return unsafeCastVariableGet(temp, type);
}
VariableDeclaration allocateTemporary(int index,
[DartType type = const DynamicType()]) {
+ if (variables.length > index) {
+ // Re-type temporary to dynamic if we detect reuse with different type.
+ // Note: We should make sure all uses use `unsafeCast(...)` to pass their
+ // type information on, as that is lost otherwise.
+ if (variables[index].type != const DynamicType() &&
+ variables[index].type != type) {
+ variables[index].type = const DynamicType();
+ }
+ return variables[index];
+ }
for (var i = variables.length; i <= index; i++) {
variables.add(VariableDeclaration(":async_temporary_${i}", type: type));
}
@@ -384,10 +403,9 @@
// so any statements it emits occur after in the accumulated list (that is,
// so they occur before in the corresponding block).
var rightBody = blockOf(rightStatements);
- var result = allocateTemporary(
- nameIndex,
- _staticTypeContext.typeEnvironment.coreTypes
- .boolRawType(_staticTypeContext.nonNullable));
+ final type = _staticTypeContext.typeEnvironment.coreTypes
+ .boolRawType(_staticTypeContext.nonNullable);
+ final result = allocateTemporary(nameIndex, type);
final objectEquals = continuationRewriter.helper.coreTypes.objectEquals;
rightBody.addStatement(new ExpressionStatement(new VariableSet(
result,
@@ -402,7 +420,8 @@
then = new EmptyStatement();
otherwise = rightBody;
}
- statements.add(new IfStatement(new VariableGet(result), then, otherwise));
+ statements.add(
+ new IfStatement(unsafeCastVariableGet(result, type), then, otherwise));
final test = new EqualsCall(expr.left, new BoolLiteral(true),
interfaceTarget: objectEquals,
@@ -414,7 +433,7 @@
++nameIndex;
seenAwait = seenAwait || rightAwait;
- return new VariableGet(result);
+ return unsafeCastVariableGet(result, type);
}
TreeNode visitConditionalExpression(ConditionalExpression expr) {
@@ -455,15 +474,15 @@
});
}
- // If then or otherwise has emitted statements we will produce a temporary t
- // and emit:
+ // If `then` or `otherwise` has emitted statements we will produce a
+ // temporary t and emit:
//
// if ([condition]) {
// t = [left];
// } else {
// t = [right];
// }
- var result = allocateTemporary(nameIndex, expr.staticType);
+ final result = allocateTemporary(nameIndex, expr.staticType);
var thenBody = blockOf(thenStatements);
var otherwiseBody = blockOf(otherwiseStatements);
thenBody.addStatement(
@@ -478,7 +497,7 @@
++nameIndex;
seenAwait = seenAwait || thenAwait || otherwiseAwait;
- return new VariableGet(result);
+ return unsafeCastVariableGet(result, expr.staticType);
}
// Others.
diff --git a/pkg/kernel/lib/transformations/scanner.dart b/pkg/kernel/lib/transformations/scanner.dart
index d80aa65..18c7814 100644
--- a/pkg/kernel/lib/transformations/scanner.dart
+++ b/pkg/kernel/lib/transformations/scanner.dart
@@ -260,7 +260,7 @@
return result;
}
- void visitMethodInvocation(MethodInvocation node) {
+ void visitInstanceInvocation(InstanceInvocation node) {
if (predicate(node)) {
_result!.targets[node] = next?.scan(node);
// TODO: Update result.errors.
diff --git a/pkg/kernel/lib/transformations/value_class.dart b/pkg/kernel/lib/transformations/value_class.dart
index 014256c..61481e5 100644
--- a/pkg/kernel/lib/transformations/value_class.dart
+++ b/pkg/kernel/lib/transformations/value_class.dart
@@ -61,17 +61,14 @@
}
void transformComponent(Component node, CoreTypes coreTypes,
- ClassHierarchy hierarchy, TypeEnvironment typeEnvironment,
- {required bool useNewMethodInvocationEncoding}) {
+ ClassHierarchy hierarchy, TypeEnvironment typeEnvironment) {
ValueClassScanner scanner = new ValueClassScanner();
ScanResult<Class, Null> valueClasses = scanner.scan(node);
for (Class valueClass in valueClasses.targets.keys) {
- transformValueClass(valueClass, coreTypes, hierarchy, typeEnvironment,
- useNewMethodInvocationEncoding: useNewMethodInvocationEncoding);
+ transformValueClass(valueClass, coreTypes, hierarchy, typeEnvironment);
}
- treatCopyWithCallSites(node, coreTypes, typeEnvironment, hierarchy,
- useNewMethodInvocationEncoding: useNewMethodInvocationEncoding);
+ treatCopyWithCallSites(node, coreTypes, typeEnvironment, hierarchy);
for (Class valueClass in valueClasses.targets.keys) {
removeValueClassAnnotation(valueClass);
@@ -79,8 +76,7 @@
}
void transformValueClass(Class cls, CoreTypes coreTypes,
- ClassHierarchy hierarchy, TypeEnvironment typeEnvironment,
- {required bool useNewMethodInvocationEncoding}) {
+ ClassHierarchy hierarchy, TypeEnvironment typeEnvironment) {
Constructor? syntheticConstructor = null;
for (Constructor constructor in cls.constructors) {
if (constructor.isSynthetic) {
@@ -93,12 +89,9 @@
allVariablesList.sort((a, b) => a.name!.compareTo(b.name!));
addConstructor(cls, coreTypes, syntheticConstructor!);
- addEqualsOperator(cls, coreTypes, hierarchy, allVariablesList,
- useNewMethodInvocationEncoding: useNewMethodInvocationEncoding);
- addHashCode(cls, coreTypes, hierarchy, allVariablesList,
- useNewMethodInvocationEncoding: useNewMethodInvocationEncoding);
- addToString(cls, coreTypes, hierarchy, allVariablesList,
- useNewMethodInvocationEncoding: useNewMethodInvocationEncoding);
+ addEqualsOperator(cls, coreTypes, hierarchy, allVariablesList);
+ addHashCode(cls, coreTypes, hierarchy, allVariablesList);
+ addToString(cls, coreTypes, hierarchy, allVariablesList);
addCopyWith(cls, coreTypes, hierarchy, allVariablesList, syntheticConstructor,
typeEnvironment);
}
@@ -140,8 +133,7 @@
}
void addEqualsOperator(Class cls, CoreTypes coreTypes, ClassHierarchy hierarchy,
- List<VariableDeclaration> allVariablesList,
- {required bool useNewMethodInvocationEncoding}) {
+ List<VariableDeclaration> allVariablesList) {
List<VariableDeclaration> allVariables = allVariablesList.toList();
for (Procedure procedure in cls.procedures) {
if (procedure.kind == ProcedureKind.Operator &&
@@ -178,16 +170,10 @@
ReturnStatement(allVariables
.map((f) => _createEquals(
_createGet(ThisExpression(), Name(f.name!),
- interfaceTarget: targets[f],
- useNewMethodInvocationEncoding:
- useNewMethodInvocationEncoding),
+ interfaceTarget: targets[f]),
_createGet(VariableGet(other, myType), Name(f.name!),
- interfaceTarget: targets[f],
- useNewMethodInvocationEncoding:
- useNewMethodInvocationEncoding),
- interfaceTarget: targetsEquals[f] as Procedure,
- useNewMethodInvocationEncoding:
- useNewMethodInvocationEncoding))
+ interfaceTarget: targets[f]),
+ interfaceTarget: targetsEquals[f] as Procedure))
.fold(
IsExpression(VariableGet(other), myType),
(previousValue, element) => LogicalExpression(
@@ -200,8 +186,7 @@
}
void addHashCode(Class cls, CoreTypes coreTypes, ClassHierarchy hierarchy,
- List<VariableDeclaration> allVariablesList,
- {required bool useNewMethodInvocationEncoding}) {
+ List<VariableDeclaration> allVariablesList) {
List<VariableDeclaration> allVariables = allVariablesList.toList();
for (Procedure procedure in cls.procedures) {
if (procedure.kind == ProcedureKind.Getter &&
@@ -255,13 +240,9 @@
allVariables
.map((f) => (_createGet(
_createGet(ThisExpression(), Name(f.name!),
- interfaceTarget: targets[f],
- useNewMethodInvocationEncoding:
- useNewMethodInvocationEncoding),
+ interfaceTarget: targets[f]),
Name("hashCode"),
- interfaceTarget: targetsHashcode[f],
- useNewMethodInvocationEncoding:
- useNewMethodInvocationEncoding)))
+ interfaceTarget: targetsHashcode[f])))
.fold(
_createGet(
StringLiteral(
@@ -269,9 +250,7 @@
cls.name),
Name("hashCode"),
interfaceTarget: hierarchy.getInterfaceMember(
- coreTypes.stringClass, Name("hashCode")),
- useNewMethodInvocationEncoding:
- useNewMethodInvocationEncoding),
+ coreTypes.stringClass, Name("hashCode"))),
(previousValue, element) => StaticInvocation(
hashCombine!, Arguments([previousValue, element])))
]))),
@@ -281,8 +260,7 @@
}
void addToString(Class cls, CoreTypes coreTypes, ClassHierarchy hierarchy,
- List<VariableDeclaration> allVariablesList,
- {required bool useNewMethodInvocationEncoding}) {
+ List<VariableDeclaration> allVariablesList) {
List<Expression> wording = [StringLiteral("${cls.name}(")];
for (VariableDeclaration variable in allVariablesList) {
@@ -296,12 +274,10 @@
Name("toString")) as Procedure;
wording.add(_createInvocation(
_createGet(ThisExpression(), Name(variable.name!),
- interfaceTarget: variableTarget,
- useNewMethodInvocationEncoding: useNewMethodInvocationEncoding),
+ interfaceTarget: variableTarget),
Name("toString"),
Arguments([]),
- interfaceTarget: toStringTarget,
- useNewMethodInvocationEncoding: useNewMethodInvocationEncoding));
+ interfaceTarget: toStringTarget));
wording.add(StringLiteral(", "));
}
if (allVariablesList.length != 0) {
@@ -392,8 +368,7 @@
}
void treatCopyWithCallSites(Component component, CoreTypes coreTypes,
- TypeEnvironment typeEnvironment, ClassHierarchy hierarchy,
- {required bool useNewMethodInvocationEncoding}) {
+ TypeEnvironment typeEnvironment, ClassHierarchy hierarchy) {
ValueClassCopyWithScanner valueCopyWithScanner =
new ValueClassCopyWithScanner();
AllMemberScanner copyWithScanner = AllMemberScanner(valueCopyWithScanner);
@@ -415,8 +390,7 @@
Class valueClass = valueClassType.classNode;
if (isValueClass(valueClass)) {
treatCopyWithCallSite(
- valueClass, copyWithCall, coreTypes, hierarchy,
- useNewMethodInvocationEncoding: useNewMethodInvocationEncoding);
+ valueClass, copyWithCall, coreTypes, hierarchy);
}
}
}
@@ -428,8 +402,7 @@
Class valueClass,
InstanceInvocationExpression copyWithCall,
CoreTypes coreTypes,
- ClassHierarchy hierarchy,
- {required bool useNewMethodInvocationEncoding}) {
+ ClassHierarchy hierarchy) {
Map<String, Expression> preTransformationArguments = new Map();
for (NamedExpression argument in copyWithCall.arguments.named) {
preTransformationArguments[argument.name] = argument.value;
@@ -452,18 +425,15 @@
argument.name!, preTransformationArguments[argument.name]!)
..parent = postTransformationArguments);
} else {
- postTransformationArguments.named.add(NamedExpression(
- argument.name!,
- _createGet(VariableGet(letVariable), Name(argument.name!),
- useNewMethodInvocationEncoding: useNewMethodInvocationEncoding))
+ postTransformationArguments.named.add(NamedExpression(argument.name!,
+ _createGet(VariableGet(letVariable), Name(argument.name!)))
..parent = postTransformationArguments);
}
}
copyWithCall.replaceWith(Let(
letVariable,
_createInvocation(VariableGet(letVariable), Name("copyWith"),
- postTransformationArguments,
- useNewMethodInvocationEncoding: useNewMethodInvocationEncoding)));
+ postTransformationArguments)));
}
bool isValueClass(Class node) {
@@ -483,47 +453,33 @@
// access kind on InstanceInvocation.
Expression _createInvocation(
Expression receiver, Name name, Arguments arguments,
- {Procedure? interfaceTarget,
- required bool useNewMethodInvocationEncoding}) {
- if (useNewMethodInvocationEncoding) {
- if (interfaceTarget != null) {
- return InstanceInvocation(
- InstanceAccessKind.Instance, receiver, name, arguments,
- interfaceTarget: interfaceTarget,
- functionType: interfaceTarget.getterType as FunctionType);
- } else {
- return DynamicInvocation(
- DynamicAccessKind.Dynamic, receiver, name, arguments);
- }
+ {Procedure? interfaceTarget}) {
+ if (interfaceTarget != null) {
+ return InstanceInvocation(
+ InstanceAccessKind.Instance, receiver, name, arguments,
+ interfaceTarget: interfaceTarget,
+ functionType: interfaceTarget.getterType as FunctionType);
} else {
- return MethodInvocation(receiver, name, arguments, interfaceTarget);
+ return DynamicInvocation(
+ DynamicAccessKind.Dynamic, receiver, name, arguments);
}
}
Expression _createEquals(Expression left, Expression right,
- {required Procedure interfaceTarget,
- required bool useNewMethodInvocationEncoding}) {
- if (useNewMethodInvocationEncoding) {
- return EqualsCall(left, right,
- interfaceTarget: interfaceTarget,
- functionType: interfaceTarget.getterType as FunctionType);
- } else {
- return MethodInvocation(left, Name('=='), Arguments([right]));
- }
+ {required Procedure interfaceTarget}) {
+ return EqualsCall(left, right,
+ interfaceTarget: interfaceTarget,
+ functionType: interfaceTarget.getterType as FunctionType);
}
// TODO(johnniwinther): Ensure correct result type on InstanceGet.
Expression _createGet(Expression receiver, Name name,
- {Member? interfaceTarget, required bool useNewMethodInvocationEncoding}) {
- if (useNewMethodInvocationEncoding) {
- if (interfaceTarget != null) {
- return InstanceGet(InstanceAccessKind.Instance, receiver, name,
- interfaceTarget: interfaceTarget,
- resultType: interfaceTarget.getterType);
- } else {
- return DynamicGet(DynamicAccessKind.Dynamic, receiver, name);
- }
+ {Member? interfaceTarget}) {
+ if (interfaceTarget != null) {
+ return InstanceGet(InstanceAccessKind.Instance, receiver, name,
+ interfaceTarget: interfaceTarget,
+ resultType: interfaceTarget.getterType);
} else {
- return PropertyGet(receiver, name, interfaceTarget);
+ return DynamicGet(DynamicAccessKind.Dynamic, receiver, name);
}
}
diff --git a/pkg/kernel/lib/type_algebra.dart b/pkg/kernel/lib/type_algebra.dart
index 4439705..e598523 100644
--- a/pkg/kernel/lib/type_algebra.dart
+++ b/pkg/kernel/lib/type_algebra.dart
@@ -136,9 +136,11 @@
}
class FreshTypeParameters {
- ///
+ /// The newly created type parameters.
final List<TypeParameter> freshTypeParameters;
+ /// List of [TypeParameterType]s for [TypeParameter].
final List<DartType> freshTypeArguments;
+ /// Substitution from the original type parameters to [freshTypeArguments].
final Substitution substitution;
FreshTypeParameters(
@@ -175,6 +177,8 @@
static const Substitution empty = _NullSubstitution.instance;
+ bool get isEmpty => identical(this, empty);
+
/// Substitutes each parameter to the type it maps to in [map].
static Substitution fromMap(Map<TypeParameter, DartType> map) {
if (map.isEmpty) return _NullSubstitution.instance;
diff --git a/pkg/kernel/lib/type_checker.dart b/pkg/kernel/lib/type_checker.dart
index af4d5e3..3d6cf83 100644
--- a/pkg/kernel/lib/type_checker.dart
+++ b/pkg/kernel/lib/type_checker.dart
@@ -208,7 +208,7 @@
handleFunctionNode(node.function);
}
- visitRedirectingFactoryConstructor(RedirectingFactoryConstructor node) {
+ visitRedirectingFactory(RedirectingFactory node) {
currentReturnType = null;
currentYieldType = null;
}
@@ -521,8 +521,12 @@
@override
DartType visitConstructorTearOff(ConstructorTearOff node) {
- return node.constructorReference.asConstructor.function
- .computeFunctionType(Nullability.nonNullable);
+ return node.function.computeFunctionType(Nullability.nonNullable);
+ }
+
+ @override
+ DartType visitRedirectingFactoryTearOff(RedirectingFactoryTearOff node) {
+ return node.function.computeFunctionType(Nullability.nonNullable);
}
@override
@@ -633,61 +637,6 @@
}
@override
- DartType visitMethodInvocation(MethodInvocation node) {
- Member? target = node.interfaceTarget;
- if (target == null) {
- DartType receiver = visitExpression(node.receiver);
- if (node.name.text == '==') {
- visitExpression(node.arguments.positional.single);
- return environment.coreTypes.boolLegacyRawType;
- }
- if (node.name.text == 'call' && receiver is FunctionType) {
- return handleFunctionCall(node, receiver, node.arguments);
- }
- checkUnresolvedInvocation(receiver, node);
- return handleDynamicCall(receiver, node.arguments);
- } else if (target is Procedure &&
- environment.isSpecialCasedBinaryOperator(target)) {
- assert(node.arguments.positional.length == 1);
- DartType receiver = visitExpression(node.receiver);
- DartType argument = visitExpression(node.arguments.positional[0]);
- return environment.getTypeOfSpecialCasedBinaryOperator(
- receiver, argument);
- } else {
- return handleCall(node.arguments, target.getterType,
- receiver: getReceiverType(node, node.receiver, target));
- }
- }
-
- @override
- DartType visitPropertyGet(PropertyGet node) {
- Member? target = node.interfaceTarget;
- if (target == null) {
- final DartType receiver = visitExpression(node.receiver);
- checkUnresolvedInvocation(receiver, node);
- return const DynamicType();
- } else {
- Substitution receiver = getReceiverType(node, node.receiver, target);
- return receiver.substituteType(target.getterType);
- }
- }
-
- @override
- DartType visitPropertySet(PropertySet node) {
- Member? target = node.interfaceTarget;
- DartType value = visitExpression(node.value);
- if (target != null) {
- Substitution receiver = getReceiverType(node, node.receiver, target);
- checkAssignable(node.value, value,
- receiver.substituteType(target.setterType, contravariant: true));
- } else {
- final DartType receiver = visitExpression(node.receiver);
- checkUnresolvedInvocation(receiver, node);
- }
- return value;
- }
-
- @override
DartType visitNot(Not node) {
visitExpression(node.operand);
return environment.coreTypes.boolLegacyRawType;
diff --git a/pkg/kernel/lib/verifier.dart b/pkg/kernel/lib/verifier.dart
index aec9d76..f589e8a 100644
--- a/pkg/kernel/lib/verifier.dart
+++ b/pkg/kernel/lib/verifier.dart
@@ -72,6 +72,8 @@
bool inUnevaluatedConstant = false;
+ bool inConstant = false;
+
Library? currentLibrary;
Member? currentMember;
@@ -635,6 +637,13 @@
}
}
+ @override
+ void visitTypedefTearOff(TypedefTearOff node) {
+ declareTypeParameters(node.typeParameters);
+ super.visitTypedefTearOff(node);
+ undeclareTypeParameters(node.typeParameters);
+ }
+
void checkTargetedInvocation(Member target, InvocationExpression node) {
visitChildren(node);
// ignore: unnecessary_null_comparison
@@ -821,10 +830,13 @@
visitTypeParameterType(TypeParameterType node) {
TypeParameter parameter = node.parameter;
if (!typeParametersInScope.contains(parameter)) {
+ TreeNode? owner = parameter.parent is FunctionNode
+ ? parameter.parent!.parent
+ : parameter.parent;
problem(
currentParent,
"Type parameter '$parameter' referenced out of"
- " scope, parent is: '${parameter.parent}'.");
+ " scope, owner is: '${owner}'.");
}
if (parameter.parent is Class && !classTypeParametersAreInScope) {
problem(
@@ -876,6 +888,31 @@
" ${node.typedefNode.typeParameters.length} parameters.");
}
}
+
+ @override
+ void visitConstantExpression(ConstantExpression node) {
+ bool oldInConstant = inConstant;
+ inConstant = true;
+ visitChildren(node);
+ inConstant = oldInConstant;
+ }
+
+ @override
+ void visitTypeParameter(TypeParameter node) {
+ if (inConstant) {
+ // Don't expect the type parameters to have the current parent as parent.
+ node.visitChildren(this);
+ } else {
+ visitChildren(node);
+ }
+ }
+
+ @override
+ void visitTypedefTearOffConstant(TypedefTearOffConstant node) {
+ declareTypeParameters(node.parameters);
+ super.visitTypedefTearOffConstant(node);
+ undeclareTypeParameters(node.parameters);
+ }
}
void verifyGetStaticType(TypeEnvironment env, Component component) {
diff --git a/pkg/kernel/lib/visitor.dart b/pkg/kernel/lib/visitor.dart
index 1f71e2c..5e5c959 100644
--- a/pkg/kernel/lib/visitor.dart
+++ b/pkg/kernel/lib/visitor.dart
@@ -23,8 +23,6 @@
R visitInstanceGet(InstanceGet node) => defaultExpression(node);
R visitInstanceSet(InstanceSet node) => defaultExpression(node);
R visitInstanceTearOff(InstanceTearOff node) => defaultExpression(node);
- R visitPropertyGet(PropertyGet node) => defaultExpression(node);
- R visitPropertySet(PropertySet node) => defaultExpression(node);
R visitSuperPropertyGet(SuperPropertyGet node) => defaultExpression(node);
R visitSuperPropertySet(SuperPropertySet node) => defaultExpression(node);
R visitStaticGet(StaticGet node) => defaultExpression(node);
@@ -39,7 +37,6 @@
defaultExpression(node);
R visitEqualsNull(EqualsNull node) => defaultExpression(node);
R visitEqualsCall(EqualsCall node) => defaultExpression(node);
- R visitMethodInvocation(MethodInvocation node) => defaultExpression(node);
R visitSuperMethodInvocation(SuperMethodInvocation node) =>
defaultExpression(node);
R visitStaticInvocation(StaticInvocation node) => defaultExpression(node);
@@ -82,6 +79,8 @@
R visitCheckLibraryIsLoaded(CheckLibraryIsLoaded node) =>
defaultExpression(node);
R visitConstructorTearOff(ConstructorTearOff node) => defaultExpression(node);
+ R visitRedirectingFactoryTearOff(RedirectingFactoryTearOff node) =>
+ defaultExpression(node);
R visitTypedefTearOff(TypedefTearOff node) => defaultExpression(node);
}
@@ -124,7 +123,7 @@
R visitConstructor(Constructor node) => defaultMember(node);
R visitProcedure(Procedure node) => defaultMember(node);
R visitField(Field node) => defaultMember(node);
- R visitRedirectingFactoryConstructor(RedirectingFactoryConstructor node) {
+ R visitRedirectingFactory(RedirectingFactory node) {
return defaultMember(node);
}
}
@@ -137,8 +136,7 @@
R visitConstructor(Constructor node, A arg) => defaultMember(node, arg);
R visitProcedure(Procedure node, A arg) => defaultMember(node, arg);
R visitField(Field node, A arg) => defaultMember(node, arg);
- R visitRedirectingFactoryConstructor(
- RedirectingFactoryConstructor node, A arg) {
+ R visitRedirectingFactory(RedirectingFactory node, A arg) {
return defaultMember(node, arg);
}
}
@@ -199,8 +197,6 @@
R visitInstanceGet(InstanceGet node) => defaultExpression(node);
R visitInstanceSet(InstanceSet node) => defaultExpression(node);
R visitInstanceTearOff(InstanceTearOff node) => defaultExpression(node);
- R visitPropertyGet(PropertyGet node) => defaultExpression(node);
- R visitPropertySet(PropertySet node) => defaultExpression(node);
R visitSuperPropertyGet(SuperPropertyGet node) => defaultExpression(node);
R visitSuperPropertySet(SuperPropertySet node) => defaultExpression(node);
R visitStaticGet(StaticGet node) => defaultExpression(node);
@@ -215,7 +211,6 @@
defaultExpression(node);
R visitEqualsNull(EqualsNull node) => defaultExpression(node);
R visitEqualsCall(EqualsCall node) => defaultExpression(node);
- R visitMethodInvocation(MethodInvocation node) => defaultExpression(node);
R visitSuperMethodInvocation(SuperMethodInvocation node) =>
defaultExpression(node);
R visitStaticInvocation(StaticInvocation node) => defaultExpression(node);
@@ -258,6 +253,8 @@
R visitCheckLibraryIsLoaded(CheckLibraryIsLoaded node) =>
defaultExpression(node);
R visitConstructorTearOff(ConstructorTearOff node) => defaultExpression(node);
+ R visitRedirectingFactoryTearOff(RedirectingFactoryTearOff node) =>
+ defaultExpression(node);
R visitTypedefTearOff(TypedefTearOff node) => defaultExpression(node);
// Statements
@@ -292,7 +289,7 @@
R visitConstructor(Constructor node) => defaultMember(node);
R visitProcedure(Procedure node) => defaultMember(node);
R visitField(Field node) => defaultMember(node);
- R visitRedirectingFactoryConstructor(RedirectingFactoryConstructor node) {
+ R visitRedirectingFactory(RedirectingFactory node) {
return defaultMember(node);
}
@@ -353,8 +350,6 @@
R visitInstanceSet(InstanceSet node, A arg) => defaultExpression(node, arg);
R visitInstanceTearOff(InstanceTearOff node, A arg) =>
defaultExpression(node, arg);
- R visitPropertyGet(PropertyGet node, A arg) => defaultExpression(node, arg);
- R visitPropertySet(PropertySet node, A arg) => defaultExpression(node, arg);
R visitSuperPropertyGet(SuperPropertyGet node, A arg) =>
defaultExpression(node, arg);
R visitSuperPropertySet(SuperPropertySet node, A arg) =>
@@ -375,8 +370,6 @@
defaultExpression(node, arg);
R visitEqualsNull(EqualsNull node, A arg) => defaultExpression(node, arg);
R visitEqualsCall(EqualsCall node, A arg) => defaultExpression(node, arg);
- R visitMethodInvocation(MethodInvocation node, A arg) =>
- defaultExpression(node, arg);
R visitSuperMethodInvocation(SuperMethodInvocation node, A arg) =>
defaultExpression(node, arg);
R visitStaticInvocation(StaticInvocation node, A arg) =>
@@ -436,6 +429,8 @@
defaultExpression(node, arg);
R visitConstructorTearOff(ConstructorTearOff node, A arg) =>
defaultExpression(node, arg);
+ R visitRedirectingFactoryTearOff(RedirectingFactoryTearOff node, A arg) =>
+ defaultExpression(node, arg);
R visitTypedefTearOff(TypedefTearOff node, A arg) =>
defaultExpression(node, arg);
@@ -480,8 +475,7 @@
R visitConstructor(Constructor node, A arg) => defaultMember(node, arg);
R visitProcedure(Procedure node, A arg) => defaultMember(node, arg);
R visitField(Field node, A arg) => defaultMember(node, arg);
- R visitRedirectingFactoryConstructor(
- RedirectingFactoryConstructor node, A arg) {
+ R visitRedirectingFactory(RedirectingFactory node, A arg) {
return defaultMember(node, arg);
}
@@ -589,10 +583,49 @@
defaultConstant(node);
R visitConstructorTearOffConstant(ConstructorTearOffConstant node) =>
defaultConstant(node);
+ R visitRedirectingFactoryTearOffConstant(
+ RedirectingFactoryTearOffConstant node) =>
+ defaultConstant(node);
R visitTypeLiteralConstant(TypeLiteralConstant node) => defaultConstant(node);
R visitUnevaluatedConstant(UnevaluatedConstant node) => defaultConstant(node);
}
+abstract class ConstantVisitor1<R, A> {
+ const ConstantVisitor1();
+
+ R defaultConstant(Constant node, A arg);
+
+ R visitNullConstant(NullConstant node, A arg) => defaultConstant(node, arg);
+ R visitBoolConstant(BoolConstant node, A arg) => defaultConstant(node, arg);
+ R visitIntConstant(IntConstant node, A arg) => defaultConstant(node, arg);
+ R visitDoubleConstant(DoubleConstant node, A arg) =>
+ defaultConstant(node, arg);
+ R visitStringConstant(StringConstant node, A arg) =>
+ defaultConstant(node, arg);
+ R visitSymbolConstant(SymbolConstant node, A arg) =>
+ defaultConstant(node, arg);
+ R visitMapConstant(MapConstant node, A arg) => defaultConstant(node, arg);
+ R visitListConstant(ListConstant node, A arg) => defaultConstant(node, arg);
+ R visitSetConstant(SetConstant node, A arg) => defaultConstant(node, arg);
+ R visitInstanceConstant(InstanceConstant node, A arg) =>
+ defaultConstant(node, arg);
+ R visitInstantiationConstant(InstantiationConstant node, A arg) =>
+ defaultConstant(node, arg);
+ R visitStaticTearOffConstant(StaticTearOffConstant node, A arg) =>
+ defaultConstant(node, arg);
+ R visitTypedefTearOffConstant(TypedefTearOffConstant node, A arg) =>
+ defaultConstant(node, arg);
+ R visitConstructorTearOffConstant(ConstructorTearOffConstant node, A arg) =>
+ defaultConstant(node, arg);
+ R visitRedirectingFactoryTearOffConstant(
+ RedirectingFactoryTearOffConstant node, A arg) =>
+ defaultConstant(node, arg);
+ R visitTypeLiteralConstant(TypeLiteralConstant node, A arg) =>
+ defaultConstant(node, arg);
+ R visitUnevaluatedConstant(UnevaluatedConstant node, A arg) =>
+ defaultConstant(node, arg);
+}
+
abstract class _ConstantCallback<R> {
R defaultConstant(Constant node);
@@ -610,6 +643,8 @@
R visitTypedefTearOffConstant(TypedefTearOffConstant node);
R visitStaticTearOffConstant(StaticTearOffConstant node);
R visitConstructorTearOffConstant(ConstructorTearOffConstant node);
+ R visitRedirectingFactoryTearOffConstant(
+ RedirectingFactoryTearOffConstant node);
R visitTypeLiteralConstant(TypeLiteralConstant node);
R visitUnevaluatedConstant(UnevaluatedConstant node);
}
@@ -636,6 +671,11 @@
_callback.visitConstructorTearOffConstant(node);
@override
+ R visitRedirectingFactoryTearOffConstant(
+ RedirectingFactoryTearOffConstant node) =>
+ _callback.visitRedirectingFactoryTearOffConstant(node);
+
+ @override
R visitInstantiationConstant(InstantiationConstant node) =>
_callback.visitInstantiationConstant(node);
@@ -730,6 +770,9 @@
defaultConstant(node);
R visitConstructorTearOffConstant(ConstructorTearOffConstant node) =>
defaultConstant(node);
+ R visitRedirectingFactoryTearOffConstant(
+ RedirectingFactoryTearOffConstant node) =>
+ defaultConstant(node);
R visitTypeLiteralConstant(TypeLiteralConstant node) => defaultConstant(node);
R visitUnevaluatedConstant(UnevaluatedConstant node) => defaultConstant(node);
}
@@ -774,6 +817,9 @@
defaultConstant(node);
void visitConstructorTearOffConstant(ConstructorTearOffConstant node) =>
defaultConstant(node);
+ void visitRedirectingFactoryTearOffConstant(
+ RedirectingFactoryTearOffConstant node) =>
+ defaultConstant(node);
void visitTypeLiteralConstant(TypeLiteralConstant node) =>
defaultConstant(node);
void visitUnevaluatedConstant(UnevaluatedConstant node) =>
@@ -788,12 +834,26 @@
R visitFieldReference(Field node) => defaultMemberReference(node);
R visitConstructorReference(Constructor node) => defaultMemberReference(node);
R visitProcedureReference(Procedure node) => defaultMemberReference(node);
- R visitRedirectingFactoryConstructorReference(
- RedirectingFactoryConstructor node) {
+ R visitRedirectingFactoryReference(RedirectingFactory node) {
return defaultMemberReference(node);
}
}
+abstract class MemberReferenceVisitor1<R, A> {
+ const MemberReferenceVisitor1();
+
+ R defaultMemberReference(Member node, A arg);
+
+ R visitFieldReference(Field node, A arg) => defaultMemberReference(node, arg);
+ R visitConstructorReference(Constructor node, A arg) =>
+ defaultMemberReference(node, arg);
+ R visitProcedureReference(Procedure node, A arg) =>
+ defaultMemberReference(node, arg);
+ R visitRedirectingFactoryReference(RedirectingFactory node, A arg) {
+ return defaultMemberReference(node, arg);
+ }
+}
+
abstract class Visitor<R> extends TreeVisitor<R>
implements
DartTypeVisitor<R>,
@@ -839,6 +899,9 @@
defaultConstant(node);
R visitConstructorTearOffConstant(ConstructorTearOffConstant node) =>
defaultConstant(node);
+ R visitRedirectingFactoryTearOffConstant(
+ RedirectingFactoryTearOffConstant node) =>
+ defaultConstant(node);
R visitTypeLiteralConstant(TypeLiteralConstant node) => defaultConstant(node);
R visitUnevaluatedConstant(UnevaluatedConstant node) => defaultConstant(node);
@@ -878,6 +941,11 @@
defaultConstantReference(node);
R visitConstructorTearOffConstantReference(ConstructorTearOffConstant node) =>
defaultConstantReference(node);
+ R visitRedirectingFactoryTearOffConstantReference(
+ RedirectingFactoryTearOffConstant node) =>
+ defaultConstantReference(node);
+ R visitTypedefTearOffConstantReference(TypedefTearOffConstant node) =>
+ defaultConstantReference(node);
R visitTypeLiteralConstantReference(TypeLiteralConstant node) =>
defaultConstantReference(node);
R visitUnevaluatedConstantReference(UnevaluatedConstant node) =>
@@ -889,8 +957,7 @@
R visitFieldReference(Field node) => defaultMemberReference(node);
R visitConstructorReference(Constructor node) => defaultMemberReference(node);
R visitProcedureReference(Procedure node) => defaultMemberReference(node);
- R visitRedirectingFactoryConstructorReference(
- RedirectingFactoryConstructor node) {
+ R visitRedirectingFactoryReference(RedirectingFactory node) {
return defaultMemberReference(node);
}
@@ -899,6 +966,118 @@
R visitNamedType(NamedType node) => defaultNode(node);
}
+abstract class Visitor1<R, A> extends TreeVisitor1<R, A>
+ implements
+ DartTypeVisitor1<R, A>,
+ ConstantVisitor1<R, A>,
+ MemberReferenceVisitor1<R, A> {
+ const Visitor1();
+
+ /// The catch-all case, except for references.
+ R defaultNode(Node node, A arg);
+ R defaultTreeNode(TreeNode node, A arg) => defaultNode(node, arg);
+
+ // DartTypes
+ R defaultDartType(DartType node, A arg) => defaultNode(node, arg);
+ R visitInvalidType(InvalidType node, A arg) => defaultDartType(node, arg);
+ R visitDynamicType(DynamicType node, A arg) => defaultDartType(node, arg);
+ R visitVoidType(VoidType node, A arg) => defaultDartType(node, arg);
+ R visitInterfaceType(InterfaceType node, A arg) => defaultDartType(node, arg);
+ R visitFutureOrType(FutureOrType node, A arg) => defaultDartType(node, arg);
+ R visitFunctionType(FunctionType node, A arg) => defaultDartType(node, arg);
+ R visitTypeParameterType(TypeParameterType node, A arg) =>
+ defaultDartType(node, arg);
+ R visitTypedefType(TypedefType node, A arg) => defaultDartType(node, arg);
+ R visitNeverType(NeverType node, A arg) => defaultDartType(node, arg);
+ R visitNullType(NullType node, A arg) => defaultDartType(node, arg);
+ R visitExtensionType(ExtensionType node, A arg) => defaultDartType(node, arg);
+
+ // Constants
+ R defaultConstant(Constant node, A arg) => defaultNode(node, arg);
+ R visitNullConstant(NullConstant node, A arg) => defaultConstant(node, arg);
+ R visitBoolConstant(BoolConstant node, A arg) => defaultConstant(node, arg);
+ R visitIntConstant(IntConstant node, A arg) => defaultConstant(node, arg);
+ R visitDoubleConstant(DoubleConstant node, A arg) =>
+ defaultConstant(node, arg);
+ R visitStringConstant(StringConstant node, A arg) =>
+ defaultConstant(node, arg);
+ R visitSymbolConstant(SymbolConstant node, A arg) =>
+ defaultConstant(node, arg);
+ R visitMapConstant(MapConstant node, A arg) => defaultConstant(node, arg);
+ R visitListConstant(ListConstant node, A arg) => defaultConstant(node, arg);
+ R visitSetConstant(SetConstant node, A arg) => defaultConstant(node, arg);
+ R visitInstanceConstant(InstanceConstant node, A arg) =>
+ defaultConstant(node, arg);
+ R visitInstantiationConstant(InstantiationConstant node, A arg) =>
+ defaultConstant(node, arg);
+ R visitTypeLiteralConstant(TypeLiteralConstant node, A arg) =>
+ defaultConstant(node, arg);
+ R visitUnevaluatedConstant(UnevaluatedConstant node, A arg) =>
+ defaultConstant(node, arg);
+
+ // Class references
+ R visitClassReference(Class node, A arg);
+
+ R visitTypedefReference(Typedef node, A arg);
+
+ R visitExtensionReference(Extension node, A arg);
+
+ // Constant references
+ R defaultConstantReference(Constant node, A arg);
+
+ R visitNullConstantReference(NullConstant node, A arg) =>
+ defaultConstantReference(node, arg);
+ R visitBoolConstantReference(BoolConstant node, A arg) =>
+ defaultConstantReference(node, arg);
+ R visitIntConstantReference(IntConstant node, A arg) =>
+ defaultConstantReference(node, arg);
+ R visitDoubleConstantReference(DoubleConstant node, A arg) =>
+ defaultConstantReference(node, arg);
+ R visitStringConstantReference(StringConstant node, A arg) =>
+ defaultConstantReference(node, arg);
+ R visitSymbolConstantReference(SymbolConstant node, A arg) =>
+ defaultConstantReference(node, arg);
+ R visitMapConstantReference(MapConstant node, A arg) =>
+ defaultConstantReference(node, arg);
+ R visitListConstantReference(ListConstant node, A arg) =>
+ defaultConstantReference(node, arg);
+ R visitSetConstantReference(SetConstant node, A arg) =>
+ defaultConstantReference(node, arg);
+ R visitInstanceConstantReference(InstanceConstant node, A arg) =>
+ defaultConstantReference(node, arg);
+ R visitInstantiationConstantReference(InstantiationConstant node, A arg) =>
+ defaultConstantReference(node, arg);
+ R visitConstructorTearOffConstantReference(
+ ConstructorTearOffConstant node, A arg) =>
+ defaultConstantReference(node, arg);
+ R visitRedirectingFactoryTearOffConstantReference(
+ RedirectingFactoryTearOffConstant node, A arg) =>
+ defaultConstantReference(node, arg);
+ R visitStaticTearOffConstantReference(StaticTearOffConstant node, A arg) =>
+ defaultConstantReference(node, arg);
+ R visitTypedefTearOffConstantReference(TypedefTearOffConstant node, A arg) =>
+ defaultConstantReference(node, arg);
+ R visitTypeLiteralConstantReference(TypeLiteralConstant node, A arg) =>
+ defaultConstantReference(node, arg);
+ R visitUnevaluatedConstantReference(UnevaluatedConstant node, A arg) =>
+ defaultConstantReference(node, arg);
+
+ // Member references
+ R defaultMemberReference(Member node, A arg);
+
+ R visitFieldReference(Field node, A arg) => defaultMemberReference(node, arg);
+ R visitConstructorReference(Constructor node, A arg) =>
+ defaultMemberReference(node, arg);
+ R visitProcedureReference(Procedure node, A arg) =>
+ defaultMemberReference(node, arg);
+ R visitRedirectingFactoryReference(RedirectingFactory node, A arg) =>
+ defaultMemberReference(node, arg);
+
+ R visitName(Name node, A arg) => defaultNode(node, arg);
+ R visitSupertype(Supertype node, A arg) => defaultNode(node, arg);
+ R visitNamedType(NamedType node, A arg) => defaultNode(node, arg);
+}
+
/// Visitor mixin that throws as its base case.
mixin VisitorThrowingMixin<R> implements Visitor<R> {
@override
@@ -1346,14 +1525,14 @@
transformList(nodes, parent, dummyField);
}
- /// Transforms or removes [RedirectingFactoryConstructor] nodes in [nodes] as
+ /// Transforms or removes [RedirectingFactory] nodes in [nodes] as
/// children of [parent].
///
/// This is convenience method for calling [transformList] with removal
- /// sentinel for [RedirectingFactoryConstructor] nodes.
- void transformRedirectingFactoryConstructorList(
- List<RedirectingFactoryConstructor> nodes, TreeNode parent) {
- transformList(nodes, parent, dummyRedirectingFactoryConstructor);
+ /// sentinel for [RedirectingFactory] nodes.
+ void transformRedirectingFactoryList(
+ List<RedirectingFactory> nodes, TreeNode parent) {
+ transformList(nodes, parent, dummyRedirectingFactory);
}
/// Transforms or removes [Typedef] nodes in [nodes] as children of [parent].
@@ -1498,8 +1677,6 @@
R visitInstanceSet(InstanceSet node, T arg) => defaultExpression(node, arg);
R visitInstanceTearOff(InstanceTearOff node, T arg) =>
defaultExpression(node, arg);
- R visitPropertyGet(PropertyGet node, T arg) => defaultExpression(node, arg);
- R visitPropertySet(PropertySet node, T arg) => defaultExpression(node, arg);
R visitSuperPropertyGet(SuperPropertyGet node, T arg) =>
defaultExpression(node, arg);
R visitSuperPropertySet(SuperPropertySet node, T arg) =>
@@ -1520,8 +1697,6 @@
defaultExpression(node, arg);
R visitEqualsNull(EqualsNull node, T arg) => defaultExpression(node, arg);
R visitEqualsCall(EqualsCall node, T arg) => defaultExpression(node, arg);
- R visitMethodInvocation(MethodInvocation node, T arg) =>
- defaultExpression(node, arg);
R visitSuperMethodInvocation(SuperMethodInvocation node, T arg) =>
defaultExpression(node, arg);
R visitStaticInvocation(StaticInvocation node, T arg) =>
@@ -1581,6 +1756,8 @@
defaultExpression(node, arg);
R visitConstructorTearOff(ConstructorTearOff node, T arg) =>
defaultExpression(node, arg);
+ R visitRedirectingFactoryTearOff(RedirectingFactoryTearOff node, T arg) =>
+ defaultExpression(node, arg);
R visitTypedefTearOff(TypedefTearOff node, T arg) =>
defaultExpression(node, arg);
}
diff --git a/pkg/kernel/test/ast_membench.dart b/pkg/kernel/test/ast_membench.dart
index baf8245..bd448d0 100644
--- a/pkg/kernel/test/ast_membench.dart
+++ b/pkg/kernel/test/ast_membench.dart
@@ -3,8 +3,6 @@
// 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.
-// @dart = 2.9
-
import 'package:kernel/kernel.dart';
import 'dart:io';
diff --git a/pkg/kernel/test/binary/can_read_platform_test.dart b/pkg/kernel/test/binary/can_read_platform_test.dart
index 2c8d827..2b447bc 100644
--- a/pkg/kernel/test/binary/can_read_platform_test.dart
+++ b/pkg/kernel/test/binary/can_read_platform_test.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'dart:io';
import 'package:kernel/binary/ast_from_binary.dart';
diff --git a/pkg/kernel/test/binary/component_mode_test.dart b/pkg/kernel/test/binary/component_mode_test.dart
index 2358e2f..c036b67 100644
--- a/pkg/kernel/test/binary/component_mode_test.dart
+++ b/pkg/kernel/test/binary/component_mode_test.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:kernel/binary/ast_from_binary.dart';
import 'utils.dart';
diff --git a/pkg/kernel/test/binary/invalid_index_size.dart b/pkg/kernel/test/binary/invalid_index_size.dart
index 2722ee4..893c14b 100644
--- a/pkg/kernel/test/binary/invalid_index_size.dart
+++ b/pkg/kernel/test/binary/invalid_index_size.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:kernel/binary/ast_from_binary.dart' show ParseError;
import 'utils.dart';
diff --git a/pkg/kernel/test/binary/lazy_reading_test.dart b/pkg/kernel/test/binary/lazy_reading_test.dart
index 9d8d45c..f8bec83 100644
--- a/pkg/kernel/test/binary/lazy_reading_test.dart
+++ b/pkg/kernel/test/binary/lazy_reading_test.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:kernel/binary/ast_from_binary.dart';
import 'package:kernel/src/tool/find_referenced_libraries.dart';
import 'utils.dart';
@@ -47,9 +45,9 @@
final Library loadedLib = loadedComponent.libraries.single;
final Class loadedClassA = loadedLib.classes.first;
final ExpressionStatement loadedConstructorA =
- loadedClassA.constructors.single.function.body;
+ loadedClassA.constructors.single.function.body as ExpressionStatement;
final ConstructorInvocation loadedConstructorInvocation =
- loadedConstructorA.expression;
+ loadedConstructorA.expression as ConstructorInvocation;
final Class pointedToClass =
loadedConstructorInvocation.target.enclosingClass;
final Library pointedToLib =
@@ -81,9 +79,9 @@
final Library loadedLib = loadedComponent2.libraries.single;
final Class loadedClassA = loadedLib.classes.first;
final ExpressionStatement loadedConstructorA =
- loadedClassA.constructors.single.function.body;
+ loadedClassA.constructors.single.function.body as ExpressionStatement;
final ConstructorInvocation loadedConstructorInvocation =
- loadedConstructorA.expression;
+ loadedConstructorA.expression as ConstructorInvocation;
final Class pointedToClass =
loadedConstructorInvocation.target.enclosingClass;
final Library pointedToLib =
diff --git a/pkg/kernel/test/binary/library_flags_test.dart b/pkg/kernel/test/binary/library_flags_test.dart
index c930c3c..d8776d6 100644
--- a/pkg/kernel/test/binary/library_flags_test.dart
+++ b/pkg/kernel/test/binary/library_flags_test.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'utils.dart';
/// Test that library flags are serialized and read correctly.
diff --git a/pkg/kernel/test/binary/utils.dart b/pkg/kernel/test/binary/utils.dart
index 4253db8..1005909 100644
--- a/pkg/kernel/test/binary/utils.dart
+++ b/pkg/kernel/test/binary/utils.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'dart:io' show BytesBuilder;
import 'package:kernel/binary/ast_to_binary.dart' show BinaryPrinter;
diff --git a/pkg/kernel/test/binary_bench.dart b/pkg/kernel/test/binary_bench.dart
index 75834e6..3c63ecd 100644
--- a/pkg/kernel/test/binary_bench.dart
+++ b/pkg/kernel/test/binary_bench.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
// This files contains methods for benchmarking Kernel binary serialization
// and deserialization routines.
@@ -35,8 +33,8 @@
},
};
-Benchmark benchmark;
-File sourceDill;
+Benchmark? benchmark;
+late File sourceDill;
bool forGolem = false;
bool forRaw = false;
@@ -47,7 +45,7 @@
}
final bytes = sourceDill.readAsBytesSync();
- benchmark(bytes);
+ benchmark!(bytes);
}
const warmupIterations = 100;
@@ -64,7 +62,8 @@
}
final warmupUs = sw.elapsedMicroseconds / warmupIterations;
- final runsUs = new List<int>.filled(benchmarkIterations, null);
+ final runsUs =
+ new List<int>.filled(benchmarkIterations, /* dummy value = */ 0);
for (var i = 0; i < benchmarkIterations; i++) {
sw.reset();
_fromBinary(bytes, eager: eager);
@@ -88,7 +87,8 @@
}
final warmupUs = sw.elapsedMicroseconds / warmupIterations;
- final runsUs = new List<int>.filled(benchmarkIterations, null);
+ final runsUs =
+ new List<int>.filled(benchmarkIterations, /* dummy value = */ 0);
for (var i = 0; i < benchmarkIterations; i++) {
sw.reset();
_toBinary(p);
@@ -106,7 +106,7 @@
BenchmarkResult(this.name, this.coldRunUs, this.warmupUs, this.runsUs);
- static T add<T extends num>(T x, T y) => x + y;
+ static T add<T extends num>(T x, T y) => x + y as T;
void report() {
runsUs.sort();
diff --git a/pkg/kernel/test/class_hierarchy_basic.dart b/pkg/kernel/test/class_hierarchy_basic.dart
index 1a9b34e..78ca0c5 100644
--- a/pkg/kernel/test/class_hierarchy_basic.dart
+++ b/pkg/kernel/test/class_hierarchy_basic.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
library kernel.class_hierarchy_basic;
import 'package:kernel/class_hierarchy.dart';
@@ -97,19 +95,19 @@
superMixtures[node] = new Set<Class>()..add(node);
supertypes[node] = new Set<Class>()..add(node);
if (node.supertype != null) {
- buildSuperTypeSets(node.supertype.classNode);
- superclasses[node].addAll(superclasses[node.supertype.classNode]);
- superMixtures[node].addAll(superMixtures[node.supertype.classNode]);
- supertypes[node].addAll(supertypes[node.supertype.classNode]);
+ buildSuperTypeSets(node.supertype!.classNode);
+ superclasses[node]!.addAll(superclasses[node.supertype!.classNode]!);
+ superMixtures[node]!.addAll(superMixtures[node.supertype!.classNode]!);
+ supertypes[node]!.addAll(supertypes[node.supertype!.classNode]!);
}
if (node.mixedInType != null) {
- buildSuperTypeSets(node.mixedInType.classNode);
- superMixtures[node].addAll(superMixtures[node.mixedInType.classNode]);
- supertypes[node].addAll(supertypes[node.mixedInType.classNode]);
+ buildSuperTypeSets(node.mixedInType!.classNode);
+ superMixtures[node]!.addAll(superMixtures[node.mixedInType!.classNode]!);
+ supertypes[node]!.addAll(supertypes[node.mixedInType!.classNode]!);
}
for (var supertype in node.implementedTypes) {
buildSuperTypeSets(supertype.classNode);
- supertypes[node].addAll(supertypes[supertype.classNode]);
+ supertypes[node]!.addAll(supertypes[supertype.classNode]!);
}
classes.add(node);
classIndex[node] = classes.length - 1;
@@ -125,8 +123,8 @@
buildSuperTypeInstantiations(superclass);
var substitution = Substitution.fromPairs(
superclass.typeParameters, supertype.typeArguments);
- supertypeInstantiations[superclass].forEach((key, type) {
- supertypeInstantiations[node][key] =
+ supertypeInstantiations[superclass]!.forEach((key, type) {
+ supertypeInstantiations[node]![key] =
substitution.substituteSupertype(type);
});
}
@@ -137,25 +135,26 @@
gettersAndCalls[node] = <Name, Member>{};
setters[node] = <Name, Member>{};
if (node.supertype != null) {
- buildDispatchTable(node.supertype.classNode);
- gettersAndCalls[node].addAll(gettersAndCalls[node.supertype.classNode]);
- setters[node].addAll(setters[node.supertype.classNode]);
+ buildDispatchTable(node.supertype!.classNode);
+ gettersAndCalls[node]!
+ .addAll(gettersAndCalls[node.supertype!.classNode]!);
+ setters[node]!.addAll(setters[node.supertype!.classNode]!);
}
// Overwrite map entries with declared members.
Class mixin = node.mixedInType?.classNode ?? node;
for (Procedure procedure in mixin.procedures) {
if (procedure.isStatic || procedure.isAbstract) continue;
if (procedure.kind == ProcedureKind.Setter) {
- setters[node][procedure.name] = procedure;
+ setters[node]![procedure.name] = procedure;
} else {
- gettersAndCalls[node][procedure.name] = procedure;
+ gettersAndCalls[node]![procedure.name] = procedure;
}
}
for (Field field in mixin.fields) {
if (field.isStatic) continue;
- gettersAndCalls[node][field.name] = field;
+ gettersAndCalls[node]![field.name] = field;
if (!field.isFinal) {
- setters[node][field.name] = field;
+ setters[node]![field.name] = field;
}
}
}
@@ -163,7 +162,7 @@
void mergeMaps(
Map<Name, List<Member>> source, Map<Name, List<Member>> destination) {
for (var name in source.keys) {
- destination.putIfAbsent(name, () => <Member>[]).addAll(source[name]);
+ destination.putIfAbsent(name, () => <Member>[]).addAll(source[name]!);
}
}
@@ -171,12 +170,12 @@
if (interfaceGettersAndCalls.containsKey(node)) return;
interfaceGettersAndCalls[node] = <Name, List<Member>>{};
interfaceSetters[node] = <Name, List<Member>>{};
- void inheritFrom(Supertype type) {
+ void inheritFrom(Supertype? type) {
if (type == null) return;
buildInterfaceTable(type.classNode);
- mergeMaps(interfaceGettersAndCalls[type.classNode],
- interfaceGettersAndCalls[node]);
- mergeMaps(interfaceSetters[type.classNode], interfaceSetters[node]);
+ mergeMaps(interfaceGettersAndCalls[type.classNode]!,
+ interfaceGettersAndCalls[node]!);
+ mergeMaps(interfaceSetters[type.classNode]!, interfaceSetters[node]!);
}
inheritFrom(node.supertype);
@@ -186,70 +185,70 @@
for (Procedure procedure in node.mixin.procedures) {
if (procedure.isStatic) continue;
if (procedure.kind == ProcedureKind.Setter) {
- interfaceSetters[node][procedure.name] = <Member>[procedure];
+ interfaceSetters[node]![procedure.name] = <Member>[procedure];
} else {
- interfaceGettersAndCalls[node][procedure.name] = <Member>[procedure];
+ interfaceGettersAndCalls[node]![procedure.name] = <Member>[procedure];
}
}
for (Field field in node.mixin.fields) {
if (field.isStatic) continue;
- interfaceGettersAndCalls[node][field.name] = <Member>[field];
+ interfaceGettersAndCalls[node]![field.name] = <Member>[field];
if (!field.isFinal) {
- interfaceSetters[node][field.name] = <Member>[field];
+ interfaceSetters[node]![field.name] = <Member>[field];
}
}
}
bool isSubclassOf(Class subtype, Class supertype) {
- return superclasses[subtype].contains(supertype);
+ return superclasses[subtype]!.contains(supertype);
}
bool isSubmixtureOf(Class subtype, Class supertype) {
- return superMixtures[subtype].contains(supertype);
+ return superMixtures[subtype]!.contains(supertype);
}
bool isSubtypeOf(Class subtype, Class supertype) {
- return supertypes[subtype].contains(supertype);
+ return supertypes[subtype]!.contains(supertype);
}
- Supertype getClassAsInstanceOf(Class type, Class supertype) {
- return supertypeInstantiations[type][supertype];
+ Supertype? getClassAsInstanceOf(Class type, Class supertype) {
+ return supertypeInstantiations[type]![supertype];
}
- Member getDispatchTarget(Class class_, Name name, {bool setter: false}) {
- return setter ? setters[class_][name] : gettersAndCalls[class_][name];
+ Member? getDispatchTarget(Class class_, Name name, {bool setter: false}) {
+ return setter ? setters[class_]![name] : gettersAndCalls[class_]![name];
}
List<Member> getDispatchTargets(Class class_, {bool setters: false}) {
return setters
- ? this.setters[class_].values
- : gettersAndCalls[class_].values;
+ ? this.setters[class_]!.values.toList()
+ : gettersAndCalls[class_]!.values.toList();
}
- Member tryFirst(List<Member> members) {
- return (members == null || members.isEmpty) ? null : members[0];
+ Member? tryFirst(Iterable<Member>? members) {
+ return (members == null || members.isEmpty) ? null : members.first;
}
- Member getInterfaceMember(Class class_, Name name, {bool setter: false}) {
+ Member? getInterfaceMember(Class class_, Name name, {bool setter: false}) {
return tryFirst(getInterfaceMembersByName(class_, name, setter: setter));
}
Iterable<Member> getInterfaceMembersByName(Class class_, Name name,
{bool setter: false}) {
var iterable = setter
- ? interfaceSetters[class_][name]
- : interfaceGettersAndCalls[class_][name];
+ ? interfaceSetters[class_]![name]
+ : interfaceGettersAndCalls[class_]![name];
return iterable == null ? const <Member>[] : iterable;
}
List<Member> getInterfaceMembers(Class class_, {bool setters: false}) {
return setters
- ? interfaceSetters[class_].values.expand((x) => x)
- : interfaceGettersAndCalls[class_].values.expand((x) => x);
+ ? interfaceSetters[class_]!.values.expand((x) => x).toList()
+ : interfaceGettersAndCalls[class_]!.values.expand((x) => x).toList();
}
int getClassIndex(Class node) {
- return classIndex[node];
+ return classIndex[node]!;
}
List<int> getExpenseHistogram() => <int>[];
diff --git a/pkg/kernel/test/class_hierarchy_bench.dart b/pkg/kernel/test/class_hierarchy_bench.dart
index 97d3dcd..f6bf037 100644
--- a/pkg/kernel/test/class_hierarchy_bench.dart
+++ b/pkg/kernel/test/class_hierarchy_bench.dart
@@ -3,8 +3,6 @@
// 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.
-// @dart = 2.9
-
import 'package:kernel/kernel.dart';
import 'package:kernel/class_hierarchy.dart';
import 'package:kernel/core_types.dart';
@@ -61,7 +59,8 @@
int hierarchyCount = int.parse(options['cycle']);
var hierarchies = <ClosedWorldClassHierarchy>[];
for (int i = 0; i < hierarchyCount; i++) {
- hierarchies.add(buildHierarchy());
+ // TODO(johnniwinther): This doesn't work for the [BasicClassHierarchy].
+ hierarchies.add(buildHierarchy() as ClosedWorldClassHierarchy);
}
List<Class> classes = hierarchies.first.classes.toList();
@@ -246,13 +245,13 @@
classIds[class_] = classIds.length;
}
- List<int> depth = new List.filled(classes.length, null);
+ List<int> depth = new List.filled(classes.length, /* dummy value = */ 0);
for (int i = 0; i < depth.length; ++i) {
int parentDepth = 0;
var classNode = classes[i];
for (var supertype in classNode.supers) {
var superclass = supertype.classNode;
- int index = classIds[superclass];
+ int index = classIds[superclass]!;
if (!(index < i)) {
throw '${classNode.name}($i) extends ${superclass.name}($index)';
}
@@ -264,7 +263,7 @@
List<int> depthHistogram = getHistogramOf(depth);
double averageDepth = average(depth);
double medianDepth = median(depth);
- int totalDepth = sum(depth);
+ int totalDepth = sum(depth) as int;
int numberOfClasses = classes.length;
String expenseHistogram =
diff --git a/pkg/kernel/test/class_hierarchy_membench.dart b/pkg/kernel/test/class_hierarchy_membench.dart
index 2c65048..0e6aefa 100644
--- a/pkg/kernel/test/class_hierarchy_membench.dart
+++ b/pkg/kernel/test/class_hierarchy_membench.dart
@@ -3,8 +3,6 @@
// 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.
-// @dart = 2.9
-
import 'package:kernel/kernel.dart';
import 'package:kernel/class_hierarchy.dart';
import 'package:kernel/core_types.dart';
@@ -53,7 +51,8 @@
List<ClosedWorldClassHierarchy> keepAlive = <ClosedWorldClassHierarchy>[];
for (int i = 0; i < copyCount; ++i) {
- keepAlive.add(buildHierarchy());
+ // TODO(johnniwinther): This doesn't work for the [BasicClassHierarchy].
+ keepAlive.add(buildHierarchy() as ClosedWorldClassHierarchy);
}
print('$copyCount copies built');
diff --git a/pkg/kernel/test/class_hierarchy_self_check.dart b/pkg/kernel/test/class_hierarchy_self_check.dart
index 182a2b7..4cea403 100644
--- a/pkg/kernel/test/class_hierarchy_self_check.dart
+++ b/pkg/kernel/test/class_hierarchy_self_check.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:kernel/kernel.dart';
import 'package:kernel/class_hierarchy.dart';
import 'package:kernel/core_types.dart';
@@ -23,7 +21,7 @@
BasicClassHierarchy basic = new BasicClassHierarchy(component);
CoreTypes coreTypes = new CoreTypes(component);
ClosedWorldClassHierarchy classHierarchy =
- new ClassHierarchy(component, coreTypes);
+ new ClassHierarchy(component, coreTypes) as ClosedWorldClassHierarchy;
int total = classHierarchy.numberOfClasses;
int progress = 0;
for (var class1 in classHierarchy.classes) {
@@ -60,18 +58,18 @@
progress = 0;
for (var classNode in classHierarchy.classes) {
Iterable<Name> candidateNames = <Iterable<Name>>[
- basic.gettersAndCalls[classNode].keys,
- basic.setters[classNode].keys,
+ basic.gettersAndCalls[classNode]!.keys,
+ basic.setters[classNode]!.keys,
pickRandom(nameList, 100)
].expand((x) => x);
for (Name name in candidateNames) {
- Member expectedGetter =
+ Member? expectedGetter =
basic.getDispatchTarget(classNode, name, setter: false);
- Member expectedSetter =
+ Member? expectedSetter =
basic.getDispatchTarget(classNode, name, setter: true);
- Member actualGetter =
+ Member? actualGetter =
classHierarchy.getDispatchTarget(classNode, name, setter: false);
- Member actualSetter =
+ Member? actualSetter =
classHierarchy.getDispatchTarget(classNode, name, setter: true);
if (actualGetter != expectedGetter) {
fail('lookupGetter($classNode, $name) returned '
@@ -90,18 +88,18 @@
progress = 0;
for (var classNode in classHierarchy.classes) {
Iterable<Name> candidateNames = [
- basic.interfaceGettersAndCalls[classNode].keys,
- basic.interfaceSetters[classNode].keys,
+ basic.interfaceGettersAndCalls[classNode]!.keys,
+ basic.interfaceSetters[classNode]!.keys,
pickRandom(nameList, 100)
].expand((x) => x);
for (Name name in candidateNames) {
- Member expectedGetter =
+ Member? expectedGetter =
basic.getInterfaceMember(classNode, name, setter: false);
- Member expectedSetter =
+ Member? expectedSetter =
basic.getInterfaceMember(classNode, name, setter: true);
- Member actualGetter =
+ Member? actualGetter =
classHierarchy.getInterfaceMember(classNode, name, setter: false);
- Member actualSetter =
+ Member? actualSetter =
classHierarchy.getInterfaceMember(classNode, name, setter: true);
if (actualGetter != expectedGetter) {
fail('getInterfaceMember($classNode, $name) returned '
diff --git a/pkg/kernel/test/class_hierarchy_test.dart b/pkg/kernel/test/class_hierarchy_test.dart
index 65b263d..f5a2bc5 100644
--- a/pkg/kernel/test/class_hierarchy_test.dart
+++ b/pkg/kernel/test/class_hierarchy_test.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import "package:expect/minitest.dart";
import "package:kernel/ast.dart";
@@ -82,11 +80,11 @@
class ClosedWorldClassHierarchyTest {
final Component component = createMockSdkComponent();
- CoreTypes coreTypes;
+ late CoreTypes coreTypes;
- Library library;
+ late Library library;
- ClassHierarchy _hierarchy;
+ ClassHierarchy? _hierarchy;
ClosedWorldClassHierarchyTest() {
coreTypes = new CoreTypes(component);
@@ -335,8 +333,9 @@
/// The [TypeParameterType]s corresponding to [typeParameterNames] are
/// passed to optional [extends_] and [implements_] callbacks.
Class addGenericClass(String name, List<String> typeParameterNames,
- {Supertype extends_(List<DartType> typeParameterTypes),
- List<Supertype> implements_(List<DartType> typeParameterTypes)}) {
+ {Supertype Function(List<DartType> typeParameterTypes)? extends_,
+ List<Supertype> Function(List<DartType> typeParameterTypes)?
+ implements_}) {
var typeParameters = typeParameterNames
.map((name) => new TypeParameter(
name, coreTypes.objectLegacyRawType, coreTypes.objectLegacyRawType))
diff --git a/pkg/kernel/test/class_hierarchy_test_disabled.dart b/pkg/kernel/test/class_hierarchy_test_disabled.dart
index 5cba5d7..40155b0 100644
--- a/pkg/kernel/test/class_hierarchy_test_disabled.dart
+++ b/pkg/kernel/test/class_hierarchy_test_disabled.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:kernel/kernel.dart';
import 'package:test/test.dart';
import 'class_hierarchy_self_check.dart';
diff --git a/pkg/kernel/test/constant_equals_test.dart b/pkg/kernel/test/constant_equals_test.dart
index 689ae71..80611c6 100644
--- a/pkg/kernel/test/constant_equals_test.dart
+++ b/pkg/kernel/test/constant_equals_test.dart
@@ -8,6 +8,9 @@
if (a != b) {
throw 'Expected $a and $b to be equal.';
}
+ if (a.hashCode != b.hashCode) {
+ throw 'Expected $a and $b hash codes to be equal.';
+ }
}
testNotEquals(Constant a, Constant b) {
@@ -33,10 +36,29 @@
fileUri: uri,
isStatic: true);
+ Class cls = new Class(name: 'Class', fileUri: uri);
+ Procedure factory = new Procedure(
+ new Name('foo'), ProcedureKind.Factory, new FunctionNode(null),
+ fileUri: uri, isStatic: true);
+ cls.addProcedure(factory);
+ Constructor constructor = new Constructor(new FunctionNode(null),
+ name: new Name('foo'), fileUri: uri);
+ cls.addConstructor(constructor);
+ Procedure redirectingFactory = new Procedure(
+ new Name('foo'), ProcedureKind.Factory, new FunctionNode(null),
+ fileUri: uri, isStatic: true)
+ ..isRedirectingFactory = true;
+ cls.addProcedure(redirectingFactory);
+
TearOffConstant tearOffConstant1a = new StaticTearOffConstant(procedure1);
TearOffConstant tearOffConstant1b = new StaticTearOffConstant(procedure1);
TearOffConstant tearOffConstant2 = new StaticTearOffConstant(procedure2);
TearOffConstant tearOffConstant3 = new StaticTearOffConstant(procedure3);
+ TearOffConstant tearOffConstant4 =
+ new ConstructorTearOffConstant(constructor);
+ TearOffConstant tearOffConstant5 = new ConstructorTearOffConstant(factory);
+ TearOffConstant tearOffConstant6 =
+ new RedirectingFactoryTearOffConstant(redirectingFactory);
// foo() {}
// const a = foo;
@@ -161,5 +183,13 @@
[typeParameter2a, typeParameter2b],
tearOffConstant3,
[new TypeParameterType(typeParameter2b, Nullability.nullable)]));
+
+ testEquals(tearOffConstant4, tearOffConstant4);
+ testEquals(tearOffConstant5, tearOffConstant5);
+ testEquals(tearOffConstant6, tearOffConstant6);
+
+ testNotEquals(tearOffConstant4, tearOffConstant5);
+ testNotEquals(tearOffConstant4, tearOffConstant6);
+ testNotEquals(tearOffConstant5, tearOffConstant6);
}
}
diff --git a/pkg/kernel/test/convert_field_to_setter_getter.dart b/pkg/kernel/test/convert_field_to_setter_getter.dart
index d7e7fd7..89f1fd9 100644
--- a/pkg/kernel/test/convert_field_to_setter_getter.dart
+++ b/pkg/kernel/test/convert_field_to_setter_getter.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:kernel/binary/ast_from_binary.dart';
import 'package:kernel/binary/ast_to_binary.dart';
import 'binary/utils.dart';
@@ -42,14 +40,16 @@
// Canonical names are now set: Verify that the field is marked as such,
// canonical-name-wise.
String getterCanonicalName = '${field.getterReference.canonicalName}';
- if (field.getterReference.canonicalName.parent.name != "@getters") {
- throw "Expected @getters parent, but had "
- "${field.getterReference.canonicalName.parent.name}";
+ if (field.getterReference.canonicalName!.parent!.name !=
+ CanonicalName.gettersName) {
+ throw "Expected ${CanonicalName.gettersName} parent, but had "
+ "${field.getterReference.canonicalName!.parent!.name}";
}
- String setterCanonicalName = '${field.setterReference.canonicalName}';
- if (field.setterReference.canonicalName.parent.name != "@setters") {
- throw "Expected @setters parent, but had "
- "${field.setterReference.canonicalName.parent.name}";
+ String setterCanonicalName = '${field.setterReference!.canonicalName}';
+ if (field.setterReference!.canonicalName!.parent!.name !=
+ CanonicalName.settersName) {
+ throw "Expected ${CanonicalName.settersName} parent, but had "
+ "${field.setterReference!.canonicalName!.parent!.name}";
}
// Replace the field with a setter/getter pair.
@@ -65,7 +65,7 @@
// a setter/getter), the reference wouldn't (because of the way `bindTo` is
// implemented) actually have it's canonical name set, and serialization
// wouldn't work.)
- field.getterReference?.canonicalName?.unbind();
+ field.getterReference.canonicalName?.unbind();
lib1.addProcedure(getter);
FunctionNode setterFunction = new FunctionNode(new Block([]),
@@ -82,18 +82,18 @@
List<int> writtenBytesGetterSetter = serialize(lib1, lib2);
// Canonical names are now set: Verify that the getter/setter is marked as
// such, canonical-name-wise.
- if (getter.reference.canonicalName.parent.name != "@getters") {
+ if (getter.reference.canonicalName!.parent!.name != "@getters") {
throw "Expected @getters parent, but had "
- "${getter.reference.canonicalName.parent.name}";
+ "${getter.reference.canonicalName!.parent!.name}";
}
if ('${getter.reference.canonicalName}' != getterCanonicalName) {
throw "Unexpected getter canonical name. "
"Expected $getterCanonicalName, "
"actual ${getter.reference.canonicalName}.";
}
- if (setter.reference.canonicalName.parent.name != "@setters") {
+ if (setter.reference.canonicalName!.parent!.name != "@setters") {
throw "Expected @setters parent, but had "
- "${setter.reference.canonicalName.parent.name}";
+ "${setter.reference.canonicalName!.parent!.name}";
}
if ('${setter.reference.canonicalName}' != setterCanonicalName) {
throw "Unexpected setter canonical name. "
@@ -110,7 +110,7 @@
fileUri: lib1Uri);
// Important: Unbind any old canonical name
// (nulling out the canonical name is not enough, see above).
- fieldReplacement.getterReference?.canonicalName?.unbind();
+ fieldReplacement.getterReference.canonicalName?.unbind();
fieldReplacement.setterReference?.canonicalName?.unbind();
lib1.addField(fieldReplacement);
@@ -119,15 +119,15 @@
List<int> writtenBytesFieldNew = serialize(lib1, lib2);
// Canonical names are now set: Verify that the field is marked as such,
// canonical-name-wise.
- if (fieldReplacement.getterReference.canonicalName.parent.name !=
+ if (fieldReplacement.getterReference.canonicalName!.parent!.name !=
"@getters") {
throw "Expected @getters parent, but had "
- "${fieldReplacement.getterReference.canonicalName.parent.name}";
+ "${fieldReplacement.getterReference.canonicalName!.parent!.name}";
}
- if (fieldReplacement.setterReference.canonicalName.parent.name !=
+ if (fieldReplacement.setterReference!.canonicalName!.parent!.name !=
"@setters") {
throw "Expected @setters parent, but had "
- "${fieldReplacement.setterReference.canonicalName.parent.name}";
+ "${fieldReplacement.setterReference!.canonicalName!.parent!.name}";
}
// Load the written stuff and ensure it is as expected.
@@ -188,15 +188,16 @@
}
Member getSetTarget(Procedure p) {
- Block block = p.function.body;
- ExpressionStatement getterStatement = block.statements[0];
- StaticSet staticSet = getterStatement.expression;
+ Block block = p.function.body as Block;
+ ExpressionStatement getterStatement =
+ block.statements[0] as ExpressionStatement;
+ StaticSet staticSet = getterStatement.expression as StaticSet;
return staticSet.target;
}
Member getGetTarget(Procedure p) {
- Block block = p.function.body;
- ReturnStatement setterStatement = block.statements[1];
- StaticGet staticGet = setterStatement.expression;
+ Block block = p.function.body as Block;
+ ReturnStatement setterStatement = block.statements[1] as ReturnStatement;
+ StaticGet staticGet = setterStatement.expression as StaticGet;
return staticGet.target;
}
diff --git a/pkg/kernel/test/dart_type_equivalence_test.dart b/pkg/kernel/test/dart_type_equivalence_test.dart
index acf4b96..41a7a01 100644
--- a/pkg/kernel/test/dart_type_equivalence_test.dart
+++ b/pkg/kernel/test/dart_type_equivalence_test.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import "package:expect/expect.dart" show Expect;
import 'package:kernel/ast.dart';
diff --git a/pkg/kernel/test/equivalence_test.dart b/pkg/kernel/test/equivalence_test.dart
new file mode 100644
index 0000000..de5ec47
--- /dev/null
+++ b/pkg/kernel/test/equivalence_test.dart
@@ -0,0 +1,204 @@
+// 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.
+
+import 'package:expect/expect.dart';
+import 'package:kernel/ast.dart';
+import 'package:kernel/src/equivalence.dart';
+
+final Component component1 = createComponent();
+final Component component2 = createComponent();
+
+List<Test> tests = [
+ Test(IntLiteral(0), IntLiteral(0)),
+ Test(IntLiteral(42), IntLiteral(42)),
+ Test(IntLiteral(0), IntLiteral(42), inequivalence: '''
+Values 0 and 42 are not equivalent
+.root
+ IntLiteral.value
+'''),
+ Test(StringLiteral('0'), StringLiteral('0')),
+ Test(StringLiteral('42'), StringLiteral('42')),
+ Test(StringLiteral('0'), StringLiteral('42'), inequivalence: '''
+Values 0 and 42 are not equivalent
+.root
+ StringLiteral.value
+'''),
+ Test(IntLiteral(0), IntLiteral(42), strategy: const IgnoreIntLiteralValue()),
+ Test(StringLiteral('0'), StringLiteral('42'),
+ strategy: const IgnoreIntLiteralValue(), inequivalence: '''
+Values 0 and 42 are not equivalent
+.root
+ StringLiteral.value
+'''),
+ Test(IntLiteral(0), StringLiteral('0'), inequivalence: '''
+Inequivalent nodes
+1: IntLiteral(0)
+2: StringLiteral("0")
+.root
+'''),
+ Test(Not(Not(Not(BoolLiteral(true)))), Not(Not(Not(BoolLiteral(true))))),
+ Test(Not(Not(BoolLiteral(true))), Not(Not(Not(BoolLiteral(true)))),
+ inequivalence: '''
+Inequivalent nodes
+1: BoolLiteral(true)
+2: Not(!true)
+.root
+ Not.operand
+ Not.operand
+'''),
+ Test(Not(Not(Not(BoolLiteral(true)))), Not(Not(BoolLiteral(true))),
+ inequivalence: '''
+Inequivalent nodes
+1: Not(!true)
+2: BoolLiteral(true)
+.root
+ Not.operand
+ Not.operand
+'''),
+ Test(Not(Not(Not(BoolLiteral(true)))), Not(Not(Not(BoolLiteral(false)))),
+ inequivalence: '''
+Values true and false are not equivalent
+.root
+ Not.operand
+ Not.operand
+ Not.operand
+ BoolLiteral.value
+'''),
+ Test(component1, component2),
+ Test(component1.libraries[0], component2.libraries[0]),
+ Test(component1.libraries[0], component2.libraries[0]),
+ Test(component1.libraries[0], component2.libraries[1], inequivalence: '''
+Inequivalent nodes
+1: library file://uri1/
+2: library file://uri2/
+.root
+'''),
+ Test(component1.libraries[1], component2.libraries[2], inequivalence: '''
+Inequivalent nodes
+1: library file://uri2/
+2: library file://uri3/
+.root
+'''),
+ Test(component1.libraries[1], component2.libraries[3], inequivalence: '''
+Values file://uri2/ and file://uri3/ are not equivalent
+.root
+ Library(library file://uri2/).fileUri
+'''),
+ Test(component1.libraries[0].procedures[0],
+ component2.libraries[0].procedures[1],
+ inequivalence: '''
+Inequivalent nodes
+1: foo
+2: bar
+.root
+'''),
+ // TODO(johnniwinther): Improve message for inequivalent references with the
+ // same simple name.
+ Test(component1.libraries[0].procedures[0],
+ component2.libraries[2].procedures[0],
+ inequivalence: '''
+Inequivalent nodes
+1: foo
+2: foo
+.root
+'''),
+ Test(StaticTearOff.byReference(Reference()),
+ StaticTearOff.byReference(Reference())),
+ Test(
+ StaticTearOff.byReference(
+ component1.libraries[0].procedures[0].reference),
+ StaticTearOff.byReference(
+ component2.libraries[0].procedures[0].reference)),
+ // TODO(johnniwinther): Improve message for inequivalent references with the
+ // same simple name.
+ Test(
+ StaticTearOff.byReference(
+ component1.libraries[0].procedures[0].reference),
+ StaticTearOff.byReference(
+ component2.libraries[2].procedures[0].reference),
+ inequivalence: '''
+Inequivalent references:
+1: Reference to foo
+2: Reference to foo
+.root
+ StaticTearOff.targetReference
+'''),
+];
+
+main() {
+ for (Test test in tests) {
+ EquivalenceResult result =
+ checkEquivalence(test.a, test.b, strategy: test.strategy);
+ if (test.isEquivalent) {
+ Expect.equals(result.isEquivalent, test.isEquivalent,
+ 'Unexpected result for\n${test.a}\n${test.b}:\n$result');
+ } else if (result.isEquivalent) {
+ Expect.equals(
+ result.isEquivalent,
+ test.isEquivalent,
+ 'Unexpected equivalence for\n${test.a}\n${test.b}:\n'
+ 'Expected ${test.inequivalence}');
+ } else {
+ Expect.stringEquals(
+ result.toString(),
+ test.inequivalence!,
+ 'Unexpected inequivalence result for\n${test.a}\n${test.b}:\n'
+ 'Expected:\n---\n${test.inequivalence}\n---\n'
+ 'Actual:\n---\n${result}\n---');
+ }
+ }
+}
+
+class Test {
+ final Node a;
+ final Node b;
+ final String? inequivalence;
+ final EquivalenceStrategy strategy;
+
+ Test(this.a, this.b,
+ {this.inequivalence, this.strategy = const EquivalenceStrategy()});
+
+ bool get isEquivalent => inequivalence == null;
+}
+
+class IgnoreIntLiteralValue extends EquivalenceStrategy {
+ const IgnoreIntLiteralValue();
+
+ @override
+ bool checkIntLiteral_value(
+ EquivalenceVisitor visitor, IntLiteral a, IntLiteral b) =>
+ true;
+}
+
+Component createComponent() {
+ Component component = new Component();
+ Uri uri1 = Uri.parse('file://uri1');
+ Uri uri2 = Uri.parse('file://uri2');
+ Uri uri3 = Uri.parse('file://uri3');
+ Library library1 = new Library(uri1, fileUri: uri1);
+ component.libraries.add(library1);
+ Procedure procedure1foo = new Procedure(
+ new Name('foo'), ProcedureKind.Method, new FunctionNode(null),
+ fileUri: uri1);
+ library1.addProcedure(procedure1foo);
+ Procedure procedure1bar = new Procedure(
+ new Name('bar'), ProcedureKind.Method, new FunctionNode(null),
+ fileUri: uri1);
+ library1.addProcedure(procedure1bar);
+
+ Library library2 = new Library(uri2, fileUri: uri2);
+ component.libraries.add(library2);
+
+ Library library3 = new Library(uri3, fileUri: uri2);
+ component.libraries.add(library3);
+ Procedure procedure3foo = new Procedure(
+ new Name('foo'), ProcedureKind.Method, new FunctionNode(null),
+ fileUri: uri1);
+ library3.addProcedure(procedure3foo);
+
+ Library library4 = new Library(uri2, fileUri: uri3);
+ component.libraries.add(library4);
+
+ return component;
+}
diff --git a/pkg/kernel/test/equivalent_dill_test.dart b/pkg/kernel/test/equivalent_dill_test.dart
new file mode 100644
index 0000000..baac8b3
--- /dev/null
+++ b/pkg/kernel/test/equivalent_dill_test.dart
@@ -0,0 +1,112 @@
+// Copyright (c) 2020, 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.
+
+// @dart = 2.9
+
+import 'dart:io';
+
+import 'package:kernel/binary/ast_from_binary.dart';
+import 'package:kernel/kernel.dart';
+import 'package:kernel/src/equivalence.dart';
+
+main(List<String> args) {
+ String resolvedExecutable = Platform.environment['resolvedExecutable'];
+ File exe =
+ new File(resolvedExecutable ?? Platform.resolvedExecutable).absolute;
+ int steps = 0;
+ Directory parent = exe.parent.parent;
+ while (true) {
+ Set<String> foundDirs = {};
+ for (FileSystemEntity entry in parent.listSync(recursive: false)) {
+ if (entry is Directory) {
+ List<String> pathSegments = entry.uri.pathSegments;
+ String name = pathSegments[pathSegments.length - 2];
+ foundDirs.add(name);
+ }
+ }
+ if (foundDirs.contains("pkg") &&
+ foundDirs.contains("tools") &&
+ foundDirs.contains("tests")) {
+ break;
+ }
+ steps++;
+ if (parent.uri == parent.parent.uri) {
+ throw "Reached end without finding the root.";
+ }
+ parent = parent.parent;
+ }
+ // We had to go $steps steps to reach the "root" --- now we should go 2 steps
+ // shorter to be in the "compiled dir".
+ parent = exe.parent;
+ for (int i = steps - 2; i >= 0; i--) {
+ parent = parent.parent;
+ }
+
+ List<File> dills = [];
+ for (FileSystemEntity entry in parent.listSync(recursive: false)) {
+ if (entry is File) {
+ if (entry.path.toLowerCase().endsWith(".dill")) {
+ dills.add(entry);
+ }
+ }
+ }
+ Directory sdk = new Directory.fromUri(parent.uri.resolve("dart-sdk/"));
+ for (FileSystemEntity entry in sdk.listSync(recursive: true)) {
+ if (entry is File) {
+ if (entry.path.toLowerCase().endsWith(".dill")) {
+ dills.add(entry);
+ }
+ }
+ }
+
+ print("Found ${dills.length} dills!");
+
+ List<File> errors = [];
+ for (File dill in dills) {
+ if (args.isNotEmpty &&
+ !args.any((arg) => dill.absolute.path.endsWith(arg))) {
+ print('Skipping $dill');
+ continue;
+ }
+ if (!canRead(dill)) {
+ errors.add(dill);
+ }
+ }
+ if (errors.isEmpty) {
+ print("Read all OK.");
+ } else {
+ print("Errors when reading:");
+ for (File error in errors) {
+ print(error);
+ }
+ exitCode = 1;
+ }
+}
+
+bool canRead(File dill) {
+ print("Reading $dill");
+ List<int> bytes = dill.readAsBytesSync();
+
+ try {
+ Component component1 = new Component();
+ new BinaryBuilder(bytes).readComponent(component1);
+
+ Component component2 = new Component();
+ new BinaryBuilder(bytes).readComponent(component2);
+
+ EquivalenceResult result = checkEquivalence(component1, component2);
+ if (!result.isEquivalent) {
+ print(result);
+ }
+ return result.isEquivalent;
+ } catch (e, st) {
+ print("Error for $dill:");
+ print(e);
+ print(st);
+ print("");
+ print("--------------------");
+ print("");
+ return false;
+ }
+}
diff --git a/pkg/kernel/test/flatten_test.dart b/pkg/kernel/test/flatten_test.dart
index 2dd50b8..2c5c656 100644
--- a/pkg/kernel/test/flatten_test.dart
+++ b/pkg/kernel/test/flatten_test.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import "package:expect/expect.dart" show Expect;
import 'package:kernel/ast.dart';
@@ -62,7 +60,7 @@
class Test {
final String input;
final String output;
- final String typeParameters;
+ final String? typeParameters;
const Test(this.input, this.output, [this.typeParameters]);
}
diff --git a/pkg/kernel/test/future_value_type_test.dart b/pkg/kernel/test/future_value_type_test.dart
index f256cfe..9d0e32e 100644
--- a/pkg/kernel/test/future_value_type_test.dart
+++ b/pkg/kernel/test/future_value_type_test.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import "package:expect/expect.dart" show Expect;
import 'package:kernel/ast.dart';
diff --git a/pkg/kernel/test/graph_test.dart b/pkg/kernel/test/graph_test.dart
index 28668f6..1dc79f9 100644
--- a/pkg/kernel/test/graph_test.dart
+++ b/pkg/kernel/test/graph_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE.md file.
-// @dart = 2.9
-
library kernel.test.graph_test;
import 'package:expect/expect.dart' show Expect;
@@ -17,7 +15,7 @@
Iterable<String> get vertices => graph.keys;
- Iterable<String> neighborsOf(String vertex) => graph[vertex];
+ Iterable<String> neighborsOf(String vertex) => graph[vertex]!;
}
void test(String expected, Map<String, List<String>> graph) {
diff --git a/pkg/kernel/test/heap_test.dart b/pkg/kernel/test/heap_test.dart
index 95071ef..32b294e 100644
--- a/pkg/kernel/test/heap_test.dart
+++ b/pkg/kernel/test/heap_test.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:kernel/src/heap.dart';
import 'package:test/test.dart';
diff --git a/pkg/kernel/test/import_table_test.dart b/pkg/kernel/test/import_table_test.dart
index 62c10f0..c64f614 100644
--- a/pkg/kernel/test/import_table_test.dart
+++ b/pkg/kernel/test/import_table_test.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:kernel/import_table.dart';
main() {
diff --git a/pkg/compiler/test/model/indentation_test.dart b/pkg/kernel/test/indentation_test.dart
similarity index 88%
rename from pkg/compiler/test/model/indentation_test.dart
rename to pkg/kernel/test/indentation_test.dart
index 98a4f41..94bf983 100644
--- a/pkg/compiler/test/model/indentation_test.dart
+++ b/pkg/kernel/test/indentation_test.dart
@@ -2,10 +2,8 @@
// 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.
-// @dart = 2.7
-
-import "package:expect/expect.dart";
-import 'package:compiler/src/util/util.dart' show Indentation;
+import 'package:expect/expect.dart';
+import 'package:kernel/text/indentation.dart' show Indentation;
main() {
Indentation ind = new Indentation();
diff --git a/pkg/kernel/test/legacy_erasure_test.dart b/pkg/kernel/test/legacy_erasure_test.dart
index 4e14b3b..24b1a33 100644
--- a/pkg/kernel/test/legacy_erasure_test.dart
+++ b/pkg/kernel/test/legacy_erasure_test.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import "package:expect/expect.dart" show Expect;
import 'package:kernel/ast.dart';
diff --git a/pkg/kernel/test/load_concat_dill_keeps_source_test.dart b/pkg/kernel/test/load_concat_dill_keeps_source_test.dart
index 0c2dc97..e8debc6 100644
--- a/pkg/kernel/test/load_concat_dill_keeps_source_test.dart
+++ b/pkg/kernel/test/load_concat_dill_keeps_source_test.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
// Test that 79cc54e51924cd5a6bdc2bd1771f2d0ee7af8899 works as intended.
import 'dart:convert';
@@ -67,16 +65,16 @@
builder.readComponent(tmp);
if (tmp.uriToSource[uri1] == null) throw "No data for $uri1";
if (tmp.uriToSource[uri2] == null) throw "No data for $uri2";
- if (expect1 && tmp.uriToSource[uri1].source.isEmpty) {
+ if (expect1 && tmp.uriToSource[uri1]!.source.isEmpty) {
throw "No data for $uri1";
}
- if (!expect1 && tmp.uriToSource[uri1].source.isNotEmpty) {
+ if (!expect1 && tmp.uriToSource[uri1]!.source.isNotEmpty) {
throw "Unexpected data for $uri1";
}
- if (expect2 && tmp.uriToSource[uri2].source.isEmpty) {
+ if (expect2 && tmp.uriToSource[uri2]!.source.isEmpty) {
throw "No data data for $uri2";
}
- if (!expect2 && tmp.uriToSource[uri2].source.isNotEmpty) {
+ if (!expect2 && tmp.uriToSource[uri2]!.source.isNotEmpty) {
throw "Unexpected data for $uri2";
}
}
diff --git a/pkg/kernel/test/metadata_test.dart b/pkg/kernel/test/metadata_test.dart
index ed46532..16418c6 100644
--- a/pkg/kernel/test/metadata_test.dart
+++ b/pkg/kernel/test/metadata_test.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'dart:convert';
import 'dart:io';
@@ -21,10 +19,10 @@
/// * type representing the first type parameter of its enclosing function
class Metadata {
final String string;
- final Reference _memberRef;
+ final Reference? _memberRef;
final DartType type;
- Member get member => _memberRef?.asMember;
+ Member? get member => _memberRef?.asMember;
Metadata.forNode(TreeNode n)
: this(
@@ -36,7 +34,7 @@
Metadata(this.string, this._memberRef, this.type);
}
-Member getMemberForMetadata(TreeNode node) {
+Member? getMemberForMetadata(TreeNode node) {
final parent = node.parent;
if (parent == null) return null;
if (parent is Member) return parent;
@@ -67,7 +65,7 @@
sink.writeByteList(utf8.encode(metadata.string));
sink.writeStringReference(metadata.string);
sink.writeNullAllowedCanonicalNameReference(
- metadata.member?.reference?.canonicalName);
+ metadata.member?.reference.canonicalName);
sink.writeDartType(metadata.type);
}
@@ -116,7 +114,7 @@
/// [shouldAnnotate] predicate.
void annotate(Component p, NodePredicate shouldAnnotate) {
globalDebuggingNames = new NameSystem();
- final repository = p.metadata[TestMetadataRepository.kTag];
+ final repository = p.metadata[TestMetadataRepository.kTag]!;
p.accept(new Visitor(shouldAnnotate, (node) {
repository.mapping[node] = new Metadata.forNode(node);
}));
@@ -126,7 +124,7 @@
/// component matching [shouldAnnotate] predicate has correct metadata.
void validate(Component p, NodePredicate shouldAnnotate) {
globalDebuggingNames = new NameSystem();
- final repository = p.metadata[TestMetadataRepository.kTag];
+ final repository = p.metadata[TestMetadataRepository.kTag]!;
p.accept(new Visitor(shouldAnnotate, (node) {
final m = repository.mapping[node];
final expected = new Metadata.forNode(node);
@@ -168,7 +166,7 @@
final component = fromBinary(platformBinary);
annotate(component, shouldAnnotate);
validate(component, shouldAnnotate);
- expect(component.metadata[TestMetadataRepository.kTag].mapping.length,
+ expect(component.metadata[TestMetadataRepository.kTag]!.mapping.length,
greaterThan(0));
final annotatedComponentBinary = binaryTransformer(toBinary(component));
@@ -176,7 +174,7 @@
validate(annotatedComponentFromBinary, shouldAnnotate);
expect(
annotatedComponentFromBinary
- .metadata[TestMetadataRepository.kTag].mapping.length,
+ .metadata[TestMetadataRepository.kTag]!.mapping.length,
greaterThan(0));
}
diff --git a/pkg/kernel/test/nnbd_top_merge_test.dart b/pkg/kernel/test/nnbd_top_merge_test.dart
index 7fac29a..c6255f1 100644
--- a/pkg/kernel/test/nnbd_top_merge_test.dart
+++ b/pkg/kernel/test/nnbd_top_merge_test.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import "package:expect/expect.dart" show Expect;
import 'package:kernel/ast.dart';
@@ -129,8 +127,8 @@
List<String> parts = input.split(' vs ');
DartType aType = env.parseType(parts[0]);
DartType bType = env.parseType(parts[1]);
- DartType expectedOutputType1;
- DartType expectedOutputType2;
+ DartType? expectedOutputType1;
+ DartType? expectedOutputType2;
if (output is List) {
expectedOutputType1 = env.parseType(output[0]);
expectedOutputType2 = env.parseType(output[1]);
@@ -138,8 +136,8 @@
expectedOutputType1 = expectedOutputType2 = env.parseType(output);
}
- void test(DartType a, DartType b, DartType expectedOutputType) {
- DartType actualOutputType = nnbdTopMerge(env.coreTypes, a, b);
+ void test(DartType a, DartType b, DartType? expectedOutputType) {
+ DartType? actualOutputType = nnbdTopMerge(env.coreTypes, a, b);
print('nnbdTopMerge($a,$b) = '
'$actualOutputType (expected=$expectedOutputType)');
Expect.equals(
diff --git a/pkg/kernel/test/non_null_test.dart b/pkg/kernel/test/non_null_test.dart
index 5a3dca1..3fc2b89 100644
--- a/pkg/kernel/test/non_null_test.dart
+++ b/pkg/kernel/test/non_null_test.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import "package:expect/expect.dart" show Expect;
import 'package:kernel/ast.dart';
diff --git a/pkg/kernel/test/norm_test.dart b/pkg/kernel/test/norm_test.dart
index 0f2cd38..0e1c9b1 100644
--- a/pkg/kernel/test/norm_test.dart
+++ b/pkg/kernel/test/norm_test.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import "package:expect/expect.dart" show Expect;
import 'package:kernel/ast.dart';
diff --git a/pkg/kernel/test/regression_40662_test.dart b/pkg/kernel/test/regression_40662_test.dart
deleted file mode 100644
index 77eaf47..0000000
--- a/pkg/kernel/test/regression_40662_test.dart
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright (c) 2020, 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.
-
-// @dart = 2.9
-
-// Regression test for https://github.com/dart-lang/sdk/issues/40662.
-
-import "package:expect/expect.dart" show Expect;
-
-bar(int a, List<int> b) {
- Expect.equals(-1, a);
- Expect.equals(-1, (b[0] - 2));
-}
-
-foo(int x) async => bar(x - 1, x != null ? [x + 1, x + 2, await null] : null);
-
-void main() async => await foo(0);
diff --git a/pkg/kernel/test/relink_test.dart b/pkg/kernel/test/relink_test.dart
index 3f4c9be..47da2a9 100644
--- a/pkg/kernel/test/relink_test.dart
+++ b/pkg/kernel/test/relink_test.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:kernel/binary/ast_from_binary.dart';
import 'package:kernel/binary/ast_to_binary.dart';
import 'package:kernel/src/tool/find_referenced_libraries.dart';
@@ -141,9 +139,11 @@
Uri.parse('org-dartlang:///main.dart')) {
throw "Expected main first, got ${component1Prime.libraries[0].importUri}";
}
- Block block = component1Prime.libraries[0].procedures[0].function.body;
- ReturnStatement returnStatement = block.statements[0];
- StaticInvocation staticInvocation = returnStatement.expression;
+ Block block =
+ component1Prime.libraries[0].procedures[0].function.body as Block;
+ ReturnStatement returnStatement = block.statements[0] as ReturnStatement;
+ StaticInvocation staticInvocation =
+ returnStatement.expression as StaticInvocation;
Procedure target = staticInvocation.target;
return target;
}
diff --git a/pkg/kernel/test/round_trip.dart b/pkg/kernel/test/round_trip.dart
index 3766db0..188a2a1 100644
--- a/pkg/kernel/test/round_trip.dart
+++ b/pkg/kernel/test/round_trip.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
library kernel.round_trip;
import 'dart:io';
@@ -30,7 +28,7 @@
}
}
-void testRoundTrip(List<int> bytes, List<int> sdkBytes) async {
+Future<void> testRoundTrip(List<int> bytes, List<int>? sdkBytes) async {
var component = new Component();
if (sdkBytes != null) {
var sdk = new Component(nameRoot: component.root);
diff --git a/pkg/kernel/test/round_trip_self_check.dart b/pkg/kernel/test/round_trip_self_check.dart
index da2e0e1..058cef8 100644
--- a/pkg/kernel/test/round_trip_self_check.dart
+++ b/pkg/kernel/test/round_trip_self_check.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
library kernel.round_trip_test;
import 'self_check_util.dart';
diff --git a/pkg/kernel/test/self_check_util.dart b/pkg/kernel/test/self_check_util.dart
index e742142..1ebdd39 100644
--- a/pkg/kernel/test/self_check_util.dart
+++ b/pkg/kernel/test/self_check_util.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'dart:async';
import 'package:kernel/src/tool/batch_util.dart';
diff --git a/pkg/kernel/test/serialize_bench.dart b/pkg/kernel/test/serialize_bench.dart
index 0a413f9..72853ae 100644
--- a/pkg/kernel/test/serialize_bench.dart
+++ b/pkg/kernel/test/serialize_bench.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:kernel/kernel.dart';
import 'dart:io';
diff --git a/pkg/kernel/test/text_serializer_from_kernel_nodes_test.dart b/pkg/kernel/test/text_serializer_from_kernel_nodes_test.dart
index ddc5c9f..4261086 100644
--- a/pkg/kernel/test/text_serializer_from_kernel_nodes_test.dart
+++ b/pkg/kernel/test/text_serializer_from_kernel_nodes_test.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
library kernel.text_serializer_from_kernel_nodes_test;
import 'package:kernel/ast.dart';
@@ -25,14 +23,17 @@
final TextSerializer<T> serializer;
TestCase(
- {this.name,
- this.node,
- this.expectation,
- this.serializer,
- SerializationState Function() makeSerializationState,
- DeserializationState Function() makeDeserializationState})
+ {required this.name,
+ required this.node,
+ required this.expectation,
+ required this.serializer,
+ SerializationState Function()? makeSerializationState,
+ DeserializationState Function()? makeDeserializationState})
+ // ignore: unnecessary_null_comparison
: assert(node != null),
+ // ignore: unnecessary_null_comparison
assert(expectation != null),
+ // ignore: unnecessary_null_comparison
assert(serializer != null),
this.makeSerializationState = makeSerializationState ??
(() => new SerializationState(new SerializationEnvironment(null))),
@@ -75,12 +76,12 @@
new TestCase<Statement>(
name: 'let dynamic x = 42 in let Null x^0 = null in x;',
node: () {
- VariableDeclaration outterLetVar = new VariableDeclaration('x',
+ VariableDeclaration outerLetVar = new VariableDeclaration('x',
type: const DynamicType(), initializer: new IntLiteral(42));
VariableDeclaration innerLetVar = new VariableDeclaration('x',
type: const NullType(), initializer: new NullLiteral());
- return new ExpressionStatement(new Let(outterLetVar,
- new Let(innerLetVar, new VariableGet(outterLetVar))));
+ return new ExpressionStatement(new Let(
+ outerLetVar, new Let(innerLetVar, new VariableGet(outerLetVar))));
}(),
expectation: ''
'(expr (let "x^0" () (dynamic) (int 42) ()'
@@ -90,12 +91,12 @@
new TestCase<Statement>(
name: 'let dynamic x = 42 in let Null x^0 = null in x^0;',
node: () {
- VariableDeclaration outterLetVar = new VariableDeclaration('x',
+ VariableDeclaration outerLetVar = new VariableDeclaration('x',
type: const DynamicType(), initializer: new IntLiteral(42));
VariableDeclaration innerLetVar = new VariableDeclaration('x',
type: const NullType(), initializer: new NullLiteral());
- return new ExpressionStatement(new Let(outterLetVar,
- new Let(innerLetVar, new VariableGet(innerLetVar))));
+ return new ExpressionStatement(new Let(
+ outerLetVar, new Let(innerLetVar, new VariableGet(innerLetVar))));
}(),
expectation: ''
'(expr (let "x^0" () (dynamic) (int 42) ()'
@@ -133,9 +134,10 @@
node: new ExpressionStatement(new StaticGet(field)),
expectation: ''
'(expr (get-static "package:foo/bar.dart::@getters::field"))',
- makeSerializationState: () => new SerializationState(null),
- makeDeserializationState: () =>
- new DeserializationState(null, component.root),
+ makeSerializationState: () =>
+ new SerializationState(new SerializationEnvironment(null)),
+ makeDeserializationState: () => new DeserializationState(
+ new DeserializationEnvironment(null), component.root),
serializer: statementSerializer);
}(),
() {
@@ -150,9 +152,10 @@
node: new ExpressionStatement(new StaticGet(field)),
expectation: ''
'(expr (get-static "package:foo/bar.dart::@getters::field"))',
- makeSerializationState: () => new SerializationState(null),
- makeDeserializationState: () =>
- new DeserializationState(null, component.root),
+ makeSerializationState: () =>
+ new SerializationState(new SerializationEnvironment(null)),
+ makeDeserializationState: () => new DeserializationState(
+ new DeserializationEnvironment(null), component.root),
serializer: statementSerializer);
}(),
() {
@@ -169,9 +172,10 @@
expectation: ''
'(expr'
' (set-static "package:foo/bar.dart::@setters::field" (int 1)))',
- makeSerializationState: () => new SerializationState(null),
- makeDeserializationState: () =>
- new DeserializationState(null, component.root),
+ makeSerializationState: () =>
+ new SerializationState(new SerializationEnvironment(null)),
+ makeDeserializationState: () => new DeserializationState(
+ new DeserializationEnvironment(null), component.root),
serializer: statementSerializer);
}(),
() {
@@ -197,9 +201,10 @@
expectation: ''
'(expr (invoke-static "package:foo/bar.dart::@methods::foo"'
' () ((int 42)) ()))',
- makeSerializationState: () => new SerializationState(null),
- makeDeserializationState: () =>
- new DeserializationState(null, component.root),
+ makeSerializationState: () =>
+ new SerializationState(new SerializationEnvironment(null)),
+ makeDeserializationState: () => new DeserializationState(
+ new DeserializationEnvironment(null), component.root),
serializer: statementSerializer);
}(),
() {
@@ -222,9 +227,10 @@
'(expr (invoke-const-static'
' "package:foo/bar.dart::A::@factories::foo"'
' () () ()))',
- makeSerializationState: () => new SerializationState(null),
- makeDeserializationState: () =>
- new DeserializationState(null, component.root),
+ makeSerializationState: () =>
+ new SerializationState(new SerializationEnvironment(null)),
+ makeDeserializationState: () => new DeserializationState(
+ new DeserializationEnvironment(null), component.root),
serializer: statementSerializer);
}(),
() {
@@ -240,10 +246,14 @@
new VariableDeclaration('x', type: const DynamicType());
return new TestCase<Statement>(
name: '/* suppose A {dynamic field;} A x; */ x.{A::field};',
- node: new ExpressionStatement(new PropertyGet.byReference(
- new VariableGet(x), field.name, field.getterReference)),
+ node: new ExpressionStatement(new InstanceGet.byReference(
+ InstanceAccessKind.Instance, new VariableGet(x), field.name,
+ interfaceTargetReference: field.getterReference,
+ resultType: field.getterType)),
expectation: ''
- '(expr (get-prop (get-var "x^0" _) (public "field")))',
+ '(expr (get-instance (instance) (get-var "x^0" _) '
+ '(public "field") "package:foo/bar.dart::A::@getters::field" '
+ '(dynamic)))',
makeSerializationState: () =>
new SerializationState(new SerializationEnvironment(null)
..addBinder(x, nameClue: 'x')
@@ -268,10 +278,14 @@
new VariableDeclaration('x', type: const DynamicType());
return new TestCase<Statement>(
name: '/* suppose A {dynamic field;} A x; */ x.{A::field};',
- node: new ExpressionStatement(new PropertyGet.byReference(
- new VariableGet(x), field.name, field.getterReference)),
+ node: new ExpressionStatement(new InstanceGet.byReference(
+ InstanceAccessKind.Instance, new VariableGet(x), field.name,
+ interfaceTargetReference: field.getterReference,
+ resultType: field.getterType)),
expectation: ''
- '(expr (get-prop (get-var "x^0" _) (public "field")))',
+ '(expr (get-instance (instance) (get-var "x^0" _) '
+ '(public "field") "package:foo/bar.dart::A::@getters::field" '
+ '(dynamic)))',
makeSerializationState: () =>
new SerializationState(new SerializationEnvironment(null)
..addBinder(x, nameClue: 'x')
@@ -296,13 +310,16 @@
new VariableDeclaration('x', type: const DynamicType());
return new TestCase<Statement>(
name: '/* suppose A {dynamic field;} A x; */ x.{A::field} = 42;',
- node: new ExpressionStatement(PropertySet.byReference(
+ node: new ExpressionStatement(InstanceSet.byReference(
+ InstanceAccessKind.Instance,
new VariableGet(x),
field.name,
new IntLiteral(42),
- field.setterReference)),
+ interfaceTargetReference: field.setterReference!)),
expectation: ''
- '(expr (set-prop (get-var "x^0" _) (public "field") (int 42)))',
+ '(expr (set-instance (instance) (get-var "x^0" _) '
+ '(public "field") (int 42) '
+ '"package:foo/bar.dart::A::@setters::field"))',
makeSerializationState: () =>
new SerializationState(new SerializationEnvironment(null)
..addBinder(x, nameClue: 'x')
@@ -329,14 +346,18 @@
new VariableDeclaration('x', type: const DynamicType());
return new TestCase<Statement>(
name: '/* suppose A {foo() {...}} A x; */ x.{A::foo}();',
- node: new ExpressionStatement(new MethodInvocation.byReference(
+ node: new ExpressionStatement(new InstanceInvocation.byReference(
+ InstanceAccessKind.Instance,
new VariableGet(x),
method.name,
new Arguments([]),
- method.reference)),
+ interfaceTargetReference: method.reference,
+ functionType: method.getterType as FunctionType)),
expectation: ''
- '(expr (invoke-method (get-var "x^0" _) (public "foo")'
- ' () () ()))',
+ '(expr (invoke-instance (instance) (get-var "x^0" _) '
+ '(public "foo") () () () '
+ '"package:foo/bar.dart::A::@methods::foo" '
+ '(-> () () () () () () (dynamic))))',
makeSerializationState: () =>
new SerializationState(new SerializationEnvironment(null)
..addBinder(x, nameClue: 'x')
@@ -365,9 +386,10 @@
'(expr (invoke-constructor'
' "package:foo/bar.dart::A::@constructors::foo"'
' () () ()))',
- makeSerializationState: () => new SerializationState(null),
- makeDeserializationState: () =>
- new DeserializationState(null, component.root),
+ makeSerializationState: () =>
+ new SerializationState(new SerializationEnvironment(null)),
+ makeDeserializationState: () => new DeserializationState(
+ new DeserializationEnvironment(null), component.root),
serializer: statementSerializer);
}(),
() {
@@ -387,13 +409,14 @@
'(expr (invoke-const-constructor'
' "package:foo/bar.dart::A::@constructors::foo"'
' () () ()))',
- makeSerializationState: () => new SerializationState(null),
- makeDeserializationState: () =>
- new DeserializationState(null, component.root),
+ makeSerializationState: () =>
+ new SerializationState(new SerializationEnvironment(null)),
+ makeDeserializationState: () => new DeserializationState(
+ new DeserializationEnvironment(null), component.root),
serializer: statementSerializer);
}(),
() {
- TypeParameter outterParam =
+ TypeParameter outerParam =
new TypeParameter('T', const DynamicType(), const DynamicType());
TypeParameter innerParam =
new TypeParameter('T', const DynamicType(), const DynamicType());
@@ -407,9 +430,9 @@
Nullability.legacy,
typeParameters: [innerParam])
],
- new TypeParameterType(outterParam, Nullability.legacy),
+ new TypeParameterType(outerParam, Nullability.legacy),
Nullability.legacy,
- typeParameters: [outterParam]))),
+ typeParameters: [outerParam]))),
expectation: ''
'(expr (type (-> ("T^0") ((dynamic)) ((dynamic)) '
'((-> ("T^1") ((dynamic)) ((dynamic)) () () () '
@@ -417,7 +440,7 @@
makeSerializationState: () =>
new SerializationState(new SerializationEnvironment(null)),
makeDeserializationState: () => new DeserializationState(
- new DeserializationEnvironment(null), null),
+ new DeserializationEnvironment(null), new CanonicalName.root()),
serializer: statementSerializer);
}(),
() {
@@ -444,7 +467,7 @@
makeSerializationState: () =>
new SerializationState(new SerializationEnvironment(null)),
makeDeserializationState: () => new DeserializationState(
- new DeserializationEnvironment(null), null),
+ new DeserializationEnvironment(null), new CanonicalName.root()),
serializer: statementSerializer);
}(),
() {
@@ -471,7 +494,7 @@
makeSerializationState: () =>
new SerializationState(new SerializationEnvironment(null)),
makeDeserializationState: () => new DeserializationState(
- new DeserializationEnvironment(null), null),
+ new DeserializationEnvironment(null), component.root),
serializer: memberSerializer);
}(),
() {
@@ -588,7 +611,7 @@
" but expected:\n ${testCase.expectation}");
}
- TreeNode deserialized =
+ Node deserialized =
testCase.readNode(roundTripInput, testCase.makeDeserializationState());
String roundTripOutput =
testCase.writeNode(deserialized, testCase.makeSerializationState());
diff --git a/pkg/kernel/test/text_serializer_test.dart b/pkg/kernel/test/text_serializer_test.dart
index 0a3f209..4fd8305 100644
--- a/pkg/kernel/test/text_serializer_test.dart
+++ b/pkg/kernel/test/text_serializer_test.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
library kernel.text_serializer_test;
import 'package:kernel/ast.dart';
@@ -27,7 +25,9 @@
TextIterator stream = new TextIterator(input, 0);
stream.moveNext();
Expression result = expressionSerializer.readFrom(
- stream, new DeserializationState(null, new CanonicalName.root()));
+ stream,
+ new DeserializationState(
+ new DeserializationEnvironment(null), new CanonicalName.root()));
if (stream.moveNext()) {
throw StateError("extra cruft in basic literal");
}
@@ -36,8 +36,8 @@
String writeExpression(Expression expression) {
StringBuffer buffer = new StringBuffer();
- expressionSerializer.writeTo(
- buffer, expression, new SerializationState(null));
+ expressionSerializer.writeTo(buffer, expression,
+ new SerializationState(new SerializationEnvironment(null)));
return buffer.toString();
}
@@ -45,11 +45,7 @@
final List<String> failures = [];
void run() {
- test('(get-prop (int 0) (public "hashCode"))');
test('(get-super (public "hashCode"))');
- test('(invoke-method (int 0) (public "foo") () ((int 1) (int 2)) ())');
- test('(invoke-method (int 0) (public "foo") ((dynamic) (void)) '
- '((int 1) (int 2)) ("others" (list (dynamic) ((int 3) (int 4)))))');
test('(let "x^0" () (dynamic) (int 0) () (null))');
test('(let "x^0" () (dynamic) _ () (null))');
test('(let "x^0" ((const)) (dynamic) (int 0) () (null))');
diff --git a/pkg/kernel/test/type_hashcode_quality.dart b/pkg/kernel/test/type_hashcode_quality.dart
index f33541e..8bf1f34 100644
--- a/pkg/kernel/test/type_hashcode_quality.dart
+++ b/pkg/kernel/test/type_hashcode_quality.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:kernel/kernel.dart';
import 'dart:io';
@@ -40,7 +38,7 @@
if (hash == 0) {
print('Type has a hash code of zero: $node');
}
- DartType existing = table[hash];
+ DartType? existing = table[hash];
if (existing == null) {
table[hash] = node;
} else if (existing != node) {
diff --git a/pkg/kernel/test/type_hashcode_test.dart b/pkg/kernel/test/type_hashcode_test.dart
index 9a16a72..8d13fe6 100644
--- a/pkg/kernel/test/type_hashcode_test.dart
+++ b/pkg/kernel/test/type_hashcode_test.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:kernel/kernel.dart';
import 'type_parser.dart';
import 'package:test/test.dart';
@@ -55,11 +53,13 @@
String type1;
String type2;
Iterable<String> quantifiedVariables;
- Map<String, String> expectedSubstitution; // Null if unification should fail.
+ Map<String, String?>?
+ expectedSubstitution; // Null if unification should fail.
- TestCase.success(this.type1, this.type2, this.expectedSubstitution) {
- quantifiedVariables = expectedSubstitution.keys;
- }
+ TestCase.success(
+ this.type1, this.type2, Map<String, String?> expectedSubstitution)
+ : this.expectedSubstitution = expectedSubstitution,
+ this.quantifiedVariables = expectedSubstitution.keys;
TestCase.fail(this.type1, this.type2, this.quantifiedVariables);
@@ -68,7 +68,7 @@
String toString() => '∃ ${quantifiedVariables.join(',')}. $type1 = $type2';
}
-TestCase successCase(String type1, String type2, Map<String, String> expected,
+TestCase successCase(String type1, String type2, Map<String, String?> expected,
{bool debug: false}) {
return new TestCase.success(type1, type2, expected);
}
diff --git a/pkg/kernel/test/type_parser.dart b/pkg/kernel/test/type_parser.dart
index 67a4c05..52401b9 100644
--- a/pkg/kernel/test/type_parser.dart
+++ b/pkg/kernel/test/type_parser.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
// A very simple parser for a subset of DartTypes for use in testing type
// algebra.
library kernel.test.type_parser;
@@ -41,14 +39,14 @@
class DartTypeParser {
final String string;
int index = 0;
- String tokenText;
+ String? tokenText;
final TypeEnvironment environment;
final Map<String, TypeParameter> localTypeParameters =
<String, TypeParameter>{};
DartTypeParser(this.string, this.environment);
- TreeNode lookupType(String name) {
+ TreeNode? lookupType(String name) {
return localTypeParameters[name] ?? environment(name);
}
@@ -139,8 +137,8 @@
}
}
- Nullability parseOptionalNullability(
- [Nullability defaultNullability = Nullability.nonNullable]) {
+ Nullability? parseOptionalNullability(
+ [Nullability? defaultNullability = Nullability.nonNullable]) {
int token = peekToken();
switch (token) {
case Token.QuestionMark:
@@ -159,23 +157,23 @@
switch (token) {
case Token.Name:
scanToken();
- String name = this.tokenText;
+ String name = this.tokenText!;
if (name == 'void') return const VoidType();
if (name == 'dynamic') return const DynamicType();
var target = lookupType(name);
if (target == null) {
return fail('Unresolved type $name');
} else if (target is Class) {
- List<DartType> typeArguments = parseOptionalTypeArgumentList();
- Nullability nullability = parseOptionalNullability();
+ List<DartType>? typeArguments = parseOptionalTypeArgumentList();
+ Nullability nullability = parseOptionalNullability()!;
return new InterfaceType(target, nullability, typeArguments);
} else if (target is Typedef) {
- List<DartType> typeArguments = parseOptionalTypeArgumentList();
- Nullability nullability = parseOptionalNullability();
+ List<DartType>? typeArguments = parseOptionalTypeArgumentList();
+ Nullability nullability = parseOptionalNullability()!;
return new TypedefType(target, nullability, typeArguments);
} else if (target is TypeParameter) {
- Nullability nullability = parseOptionalNullability(null);
- DartType promotedBound;
+ Nullability? nullability = parseOptionalNullability(null);
+ DartType? promotedBound;
switch (peekToken()) {
case Token.LeftAngle:
return fail('Attempt to apply type arguments to a type variable');
@@ -199,7 +197,7 @@
List<NamedType> namedParameters = <NamedType>[];
parseParameterList(parameters, namedParameters);
consumeString('=>');
- Nullability nullability = parseOptionalNullability();
+ Nullability nullability = parseOptionalNullability()!;
var returnType = parseType();
return new FunctionType(parameters, returnType, nullability,
namedParameters: namedParameters);
@@ -210,7 +208,7 @@
List<NamedType> namedParameters = <NamedType>[];
parseParameterList(parameters, namedParameters);
consumeString('=>');
- Nullability nullability = parseOptionalNullability();
+ Nullability nullability = parseOptionalNullability()!;
var returnType = parseType();
popTypeParameters(typeParameters);
return new FunctionType(parameters, returnType, nullability,
@@ -246,7 +244,7 @@
if (type is InterfaceType && type.typeArguments.isEmpty) {
return type.classNode.name;
} else if (type is TypeParameterType) {
- return type.parameter.name;
+ return type.parameter.name!;
} else {
return fail('Unexpected colon after $type');
}
@@ -267,12 +265,12 @@
return types;
}
- List<DartType> parseOptionalList(int open, int close) {
+ List<DartType>? parseOptionalList(int open, int close) {
if (peekToken() != open) return null;
return parseTypeList(open, close);
}
- List<DartType> parseOptionalTypeArgumentList() {
+ List<DartType>? parseOptionalTypeArgumentList() {
return parseOptionalList(Token.LeftAngle, Token.RightAngle);
}
@@ -302,14 +300,14 @@
if (localTypeParameters.containsKey(typeParameter.name)) {
return fail('Shadowing a type parameter is not allowed');
}
- localTypeParameters[typeParameter.name] = typeParameter;
+ localTypeParameters[typeParameter.name!] = typeParameter;
var next = peekToken();
if (next == Token.Colon) {
scanToken();
typeParameter.bound = parseType();
} else {
- typeParameter.bound =
- new InterfaceType(lookupType('Object'), Nullability.nullable);
+ typeParameter.bound = new InterfaceType(
+ lookupType('Object') as Class, Nullability.nullable);
}
return typeParameter;
}
@@ -322,7 +320,7 @@
class LazyTypeEnvironment {
final Map<String, Class> classes = <String, Class>{};
final Map<String, TypeParameter> typeParameters = <String, TypeParameter>{};
- Library dummyLibrary;
+ late final Library dummyLibrary;
final Component component = new Component();
LazyTypeEnvironment() {
@@ -360,14 +358,14 @@
for (var typeParameter
in new DartTypeParser('<$typeParametersList>', lookup)
.parseAndPushTypeParameterList()) {
- typeParameters[typeParameter.name] = typeParameter;
+ typeParameters[typeParameter.name!] = typeParameter;
}
}
DartType parse(String type) => parseDartType(type, lookup);
Supertype parseSuper(String type) {
- InterfaceType interfaceType = parse(type);
+ InterfaceType interfaceType = parse(type) as InterfaceType;
return new Supertype(interfaceType.classNode, interfaceType.typeArguments);
}
@@ -376,9 +374,9 @@
return parse(type);
}
- TypeParameter getTypeParameter(String name) {
+ TypeParameter? getTypeParameter(String name) {
if (name.length != 1) throw 'Type parameter names must have length 1';
- return lookup(name);
+ return lookup(name) as TypeParameter?;
}
}
diff --git a/pkg/kernel/test/type_parser_test.dart b/pkg/kernel/test/type_parser_test.dart
index e015daa..5a2e651 100644
--- a/pkg/kernel/test/type_parser_test.dart
+++ b/pkg/kernel/test/type_parser_test.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:expect/expect.dart' show Expect;
import 'package:kernel/testing/type_parser.dart';
diff --git a/pkg/kernel/test/type_substitute_bounds_test.dart b/pkg/kernel/test/type_substitute_bounds_test.dart
index c92d17a..ca16ac0 100644
--- a/pkg/kernel/test/type_substitute_bounds_test.dart
+++ b/pkg/kernel/test/type_substitute_bounds_test.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
library kernel.type_substitute_bounds_test;
import 'package:kernel/kernel.dart';
@@ -45,7 +43,7 @@
String toString() {
var substitution = bounds.keys.map((key) {
- var bound = bounds[key];
+ var bound = bounds[key]!;
return '${bound.lower} <: $key <: ${bound.upper}';
}).join(',');
return '$type [$substitution] <: $expected';
@@ -72,7 +70,7 @@
var upperBounds = <TypeParameter, DartType>{};
var lowerBounds = <TypeParameter, DartType>{};
testCase.bounds.forEach((String name, TypeBound bounds) {
- var parameter = environment.getTypeParameter(name);
+ var parameter = environment.getTypeParameter(name)!;
upperBounds[parameter] = environment.parse(bounds.upper);
lowerBounds[parameter] = environment.parse(bounds.lower);
});
diff --git a/pkg/kernel/test/type_substitution_identity_test.dart b/pkg/kernel/test/type_substitution_identity_test.dart
index 99d7fe7..d8fabbd 100644
--- a/pkg/kernel/test/type_substitution_identity_test.dart
+++ b/pkg/kernel/test/type_substitution_identity_test.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:kernel/kernel.dart';
import 'package:kernel/type_algebra.dart';
import 'type_parser.dart';
diff --git a/pkg/kernel/test/typedef_unalias_test.dart b/pkg/kernel/test/typedef_unalias_test.dart
index aded3c3..196ac3f 100644
--- a/pkg/kernel/test/typedef_unalias_test.dart
+++ b/pkg/kernel/test/typedef_unalias_test.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
library kernel.typedef_unalias_test;
import 'package:kernel/ast.dart';
diff --git a/pkg/kernel/test/union_find_test.dart b/pkg/kernel/test/union_find_test.dart
new file mode 100644
index 0000000..2e5249d
--- /dev/null
+++ b/pkg/kernel/test/union_find_test.dart
@@ -0,0 +1,108 @@
+// 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.
+
+import 'package:kernel/src/union_find.dart';
+
+testSame<T>(UnionFind<T> unionFind, T a, T b, bool expected) {
+ expect(expected, unionFind.nodesInSameSet(unionFind[a], unionFind[b]));
+}
+
+testSets<T>(UnionFind<T> unionFind, Set<Set<T>> sets) {
+ for (Set<T> set in sets) {
+ UnionFindNode<T> root = unionFind.findNode(unionFind[set.first]);
+ for (T value in unionFind.values) {
+ testSame(unionFind, value, root.value, set.contains(value));
+ }
+ }
+}
+
+testFind<T>(UnionFind<T> unionFind, T value, T expected) {
+ expect(expected, unionFind.findNode(unionFind[value]).value);
+}
+
+testUnion<T>(UnionFind<T> unionFind, T a, T b, T expected) {
+ expect(expected, unionFind.unionOfNodes(unionFind[a], unionFind[b]).value);
+}
+
+main() {
+ UnionFind<int> unionFind = new UnionFind();
+ // {0}
+ testFind(unionFind, 0, 0);
+ testSame(unionFind, 0, 0, true);
+ testSets(unionFind, {
+ {0}
+ });
+
+ // {0}, {1}
+ testFind(unionFind, 1, 1);
+ testSame(unionFind, 0, 1, false);
+ testSame(unionFind, 1, 0, false);
+ testSame(unionFind, 1, 1, true);
+ testSets(unionFind, {
+ {0},
+ {1}
+ });
+
+ // {0}, {1}, {2}
+ testFind(unionFind, 2, 2);
+ testSame(unionFind, 0, 2, false);
+ testSame(unionFind, 1, 2, false);
+ testSame(unionFind, 2, 2, true);
+ testSets(unionFind, {
+ {0},
+ {1},
+ {2}
+ });
+
+ // {0}, {1}, {2}
+ testUnion(unionFind, 0, 0, 0);
+ testSame(unionFind, 0, 0, true);
+ testSame(unionFind, 0, 1, false);
+ testSame(unionFind, 0, 2, false);
+ testSets(unionFind, {
+ {0},
+ {1},
+ {2}
+ });
+
+ // {0, 1}, {2}
+ testUnion(unionFind, 0, 1, 0);
+ testSame(unionFind, 0, 0, true);
+ testSame(unionFind, 0, 1, true);
+ testSame(unionFind, 1, 0, true);
+ testSame(unionFind, 0, 2, false);
+ testFind(unionFind, 0, 0);
+ testFind(unionFind, 1, 0);
+ testSets(unionFind, {
+ {0, 1},
+ {2}
+ });
+
+ // {0, 1}, {2, 3}
+ testUnion(unionFind, 2, 3, 2);
+ testSame(unionFind, 0, 0, true);
+ testSame(unionFind, 0, 1, true);
+ testSame(unionFind, 0, 2, false);
+ testSame(unionFind, 0, 3, false);
+ testSame(unionFind, 0, 0, true);
+ testSame(unionFind, 0, 1, true);
+ testSame(unionFind, 0, 2, false);
+ testSame(unionFind, 0, 3, false);
+ testFind(unionFind, 2, 2);
+ testFind(unionFind, 3, 2);
+ testSets(unionFind, {
+ {0, 1},
+ {2, 3}
+ });
+
+ // {0, 1, 2, 3}
+ testUnion(unionFind, 1, 2, 0);
+ testSets(unionFind, {
+ {0, 1, 2, 3}
+ });
+}
+
+expect(expected, actual) {
+ if (expected != actual) throw 'Expected $expected, actual $actual';
+}
diff --git a/pkg/kernel/test/verify_bench.dart b/pkg/kernel/test/verify_bench.dart
index 6326b89..c5fc42e 100644
--- a/pkg/kernel/test/verify_bench.dart
+++ b/pkg/kernel/test/verify_bench.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'dart:io';
import 'package:kernel/kernel.dart';
diff --git a/pkg/kernel/test/verify_self_check.dart b/pkg/kernel/test/verify_self_check.dart
index bb2cd02..bc9b184 100644
--- a/pkg/kernel/test/verify_self_check.dart
+++ b/pkg/kernel/test/verify_self_check.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:kernel/kernel.dart';
import 'package:kernel/verifier.dart';
diff --git a/pkg/kernel/test/verify_test.dart b/pkg/kernel/test/verify_test.dart
index 9803f71..97919d4 100644
--- a/pkg/kernel/test/verify_test.dart
+++ b/pkg/kernel/test/verify_test.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:kernel/ast.dart';
import 'package:kernel/text/ast_to_text.dart';
import 'package:kernel/verifier.dart';
@@ -30,7 +28,7 @@
test.addNode(VariableGet(node));
return node;
},
- (Node node) => "Variable '$node' used out of scope.",
+ (Node? node) => "Variable '$node' used out of scope.",
);
negative1Test(
'VariableSet out of scope',
@@ -39,7 +37,7 @@
test.addNode(VariableSet(variable, new NullLiteral()));
return variable;
},
- (Node node) => "Variable '$node' used out of scope.",
+ (Node? node) => "Variable '$node' used out of scope.",
);
negative1Test(
'Variable block scope',
@@ -51,7 +49,7 @@
]));
return variable;
},
- (Node node) => "Variable '$node' used out of scope.",
+ (Node? node) => "Variable '$node' used out of scope.",
);
negative1Test(
'Variable let scope',
@@ -63,7 +61,7 @@
new VariableGet(variable)));
return variable;
},
- (Node node) => "Variable '$node' used out of scope.",
+ (Node? node) => "Variable '$node' used out of scope.",
);
negative1Test(
'Variable redeclared',
@@ -72,7 +70,7 @@
test.addNode(Block([variable, variable]));
return variable;
},
- (Node node) => "Variable '$node' declared more than once.",
+ (Node? node) => "Variable '$node' declared more than once.",
);
negative1Test(
'Member redeclared',
@@ -86,7 +84,7 @@
fileUri: dummyUri));
return field;
},
- (Node node) => "Member '$node' has been declared more than once.",
+ (Node? node) => "Member '$node' has been declared more than once.",
);
negative1Test(
'Class redeclared',
@@ -96,7 +94,7 @@
otherClass); // Test harness also adds otherClass to component.
return test.otherClass;
},
- (Node node) => "Class '$node' declared more than once.",
+ (Node? node) => "Class '$node' declared more than once.",
);
negative1Test(
'Class type parameter redeclared',
@@ -109,7 +107,7 @@
fileUri: dummyUri));
return parameter;
},
- (Node node) => "Type parameter '$node' redeclared.",
+ (Node? node) => "Type parameter '$node' redeclared.",
);
negative1Test(
'Member type parameter redeclared',
@@ -124,7 +122,7 @@
return parameter;
},
- (Node node) => "Type parameter '$node' redeclared.",
+ (Node? node) => "Type parameter '$node' redeclared.",
);
negative2Test(
'Type parameter out of scope',
@@ -134,9 +132,9 @@
typeArgument: new TypeParameterType(parameter, Nullability.legacy)));
return [parameter, null];
},
- (Node node, Node parent) =>
+ (Node? node, Node? parent) =>
"Type parameter '$node' referenced out of scope,"
- " parent is: '$parent'.",
+ " owner is: '$parent'.",
);
negative2Test(
'Class type parameter from another class',
@@ -146,9 +144,9 @@
TypeLiteral(new TypeParameterType(node, Nullability.legacy)));
return [node, test.otherClass];
},
- (Node node, Node parent) =>
+ (Node? node, Node? parent) =>
"Type parameter '$node' referenced out of scope,"
- " parent is: '$parent'.",
+ " owner is: '$parent'.",
);
negative2Test(
'Class type parameter in static method',
@@ -164,7 +162,7 @@
return [node, test.enclosingClass];
},
- (Node node, Node parent) =>
+ (Node? node, Node? parent) =>
"Type parameter '$node' referenced from static context,"
" parent is: '$parent'.",
);
@@ -179,7 +177,7 @@
fileUri: dummyUri));
return [node, test.enclosingClass];
},
- (Node node, Node parent) =>
+ (Node? node, Node? parent) =>
"Type parameter '$node' referenced from static context,"
" parent is: '$parent'.",
);
@@ -206,9 +204,9 @@
return [parameter, parent];
},
- (Node node, Node parent) =>
+ (Node? node, Node? parent) =>
"Type parameter '$node' referenced out of scope,"
- " parent is: '$parent'.",
+ " owner is: '${(parent as TreeNode).parent}'.",
);
negative1Test(
'Interface type arity too low',
@@ -218,7 +216,7 @@
test.addNode(TypeLiteral(node));
return node;
},
- (Node node) => "Type $node provides 0 type arguments,"
+ (Node? node) => "Type $node provides 0 type arguments,"
" but the class declares 1 parameters.",
);
negative1Test(
@@ -229,7 +227,7 @@
test.addNode(TypeLiteral(node));
return node;
},
- (Node node) => "Type $node provides 2 type arguments,"
+ (Node? node) => "Type $node provides 2 type arguments,"
" but the class declares 1 parameters.",
);
negative1Test(
@@ -240,16 +238,18 @@
new TypeLiteral(new InterfaceType(orphan, Nullability.legacy)));
return orphan;
},
- (Node node) => "Dangling reference to '$node', parent is: 'null'.",
+ (Node? node) => "Dangling reference to '$node', parent is: 'null'.",
);
negative1Test(
'Dangling field get',
(TestHarness test) {
Field orphan = new Field.mutable(new Name('foo'), fileUri: dummyUri);
- test.addNode(new PropertyGet(new NullLiteral(), orphan.name, orphan));
+ test.addNode(new InstanceGet(
+ InstanceAccessKind.Instance, new NullLiteral(), orphan.name,
+ interfaceTarget: orphan, resultType: orphan.getterType));
return orphan;
},
- (Node node) => "Dangling reference to '$node', parent is: 'null'.",
+ (Node? node) => "Dangling reference to '$node', parent is: 'null'.",
);
simpleNegativeTest(
'Missing block parent pointer',
@@ -299,7 +299,7 @@
StaticInvocation(method, new Arguments([new NullLiteral()])));
return method;
},
- (Node node) => "StaticInvocation with incompatible arguments for"
+ (Node? node) => "StaticInvocation with incompatible arguments for"
" '$node'.",
);
negative1Test(
@@ -316,7 +316,7 @@
test.addNode(StaticInvocation(method, new Arguments.empty()));
return method;
},
- (Node node) => "StaticInvocation with incompatible arguments for '$node'.",
+ (Node? node) => "StaticInvocation with incompatible arguments for '$node'.",
);
negative1Test(
'StaticInvocation with unmatched named parameter',
@@ -331,7 +331,7 @@
named: [new NamedExpression('p', new NullLiteral())])));
return method;
},
- (Node node) => "StaticInvocation with incompatible arguments for"
+ (Node? node) => "StaticInvocation with incompatible arguments for"
" '$node'.",
);
negative1Test(
@@ -348,7 +348,7 @@
test.addNode(StaticInvocation(method, new Arguments.empty()));
return method;
},
- (Node node) => "StaticInvocation with wrong number of type arguments for"
+ (Node? node) => "StaticInvocation with wrong number of type arguments for"
" '$node'.",
);
negative1Test(
@@ -360,7 +360,7 @@
test.addNode(ConstructorInvocation(constructor, new Arguments.empty()));
return constructor;
},
- (Node node) =>
+ (Node? node) =>
"ConstructorInvocation with wrong number of type arguments for"
" '$node'.",
);
@@ -433,7 +433,7 @@
test.addNode(typedef_);
return typedef_;
},
- (Node node) => "The typedef '$node' refers to itself",
+ (Node? node) => "The typedef '$node' refers to itself",
);
negative1Test(
'Invalid typedef Foo = `(Foo) => void`',
@@ -446,7 +446,7 @@
test.addNode(typedef_);
return typedef_;
},
- (Node node) => "The typedef '$node' refers to itself",
+ (Node? node) => "The typedef '$node' refers to itself",
);
negative1Test(
'Invalid typedef Foo = `() => Foo`',
@@ -457,7 +457,7 @@
test.addNode(typedef_);
return typedef_;
},
- (Node node) => "The typedef '$node' refers to itself",
+ (Node? node) => "The typedef '$node' refers to itself",
);
negative1Test(
'Invalid typedef Foo = C<Foo>',
@@ -468,7 +468,7 @@
test.addNode(typedef_);
return typedef_;
},
- (Node node) => "The typedef '$node' refers to itself",
+ (Node? node) => "The typedef '$node' refers to itself",
);
negative1Test(
'Invalid typedefs Foo = Bar, Bar = Foo',
@@ -481,7 +481,7 @@
test.enclosingLibrary.addTypedef(bar);
return foo;
},
- (Node foo) => "The typedef '$foo' refers to itself",
+ (Node? foo) => "The typedef '$foo' refers to itself",
);
negative1Test(
'Invalid typedefs Foo = Bar, Bar = C<Foo>',
@@ -495,7 +495,7 @@
test.enclosingLibrary.addTypedef(bar);
return foo;
},
- (Node foo) => "The typedef '$foo' refers to itself",
+ (Node? foo) => "The typedef '$foo' refers to itself",
);
negative1Test(
'Invalid typedefs Foo = C<Bar>, Bar = C<Foo>',
@@ -510,7 +510,7 @@
test.enclosingLibrary.addTypedef(bar);
return foo;
},
- (Node foo) => "The typedef '$foo' refers to itself",
+ (Node? foo) => "The typedef '$foo' refers to itself",
);
positiveTest(
'Valid long typedefs C20 = C19 = ... = C1 = C0 = dynamic',
@@ -541,7 +541,7 @@
first.type = new TypedefType(typedef_, Nullability.legacy);
return firstTypedef;
},
- (Node node) => "The typedef '$node' refers to itself",
+ (Node? node) => "The typedef '$node' refers to itself",
);
positiveTest(
'Valid typedef Foo<T extends C> = C<T>',
@@ -611,7 +611,7 @@
test.enclosingLibrary.addTypedef(bar);
return foo;
},
- (Node foo) => "The typedef '$foo' refers to itself",
+ (Node? foo) => "The typedef '$foo' refers to itself",
);
negative1Test(
'Invalid typedef Foo<T extends Foo<dynamic> = C<T>',
@@ -628,7 +628,7 @@
test.addNode(foo);
return foo;
},
- (Node foo) => "The typedef '$foo' refers to itself",
+ (Node? foo) => "The typedef '$foo' refers to itself",
);
negative1Test(
'Typedef arity error',
@@ -643,7 +643,7 @@
test.enclosingLibrary.addField(field);
return typedefType;
},
- (Node typedefType) =>
+ (Node? typedefType) =>
"The typedef type $typedefType provides 0 type arguments,"
" but the typedef declares 1 parameters.",
);
@@ -659,7 +659,7 @@
test.enclosingLibrary.addField(field);
return foo;
},
- (Node foo) => "Dangling reference to '$foo', parent is: 'null'",
+ (Node? foo) => "Dangling reference to '$foo', parent is: 'null'",
);
negative1Test(
'Non-static top-level field',
@@ -668,7 +668,7 @@
test.enclosingLibrary.addField(field);
return null;
},
- (Node node) => "The top-level field 'field' should be static",
+ (Node? node) => "The top-level field 'field' should be static",
);
}
@@ -683,21 +683,21 @@
}
class TestHarness {
- Component component;
- Class objectClass;
- Library stubLibrary;
+ late Component component;
+ late Class objectClass;
+ late Library stubLibrary;
- TypeParameter classTypeParameter;
+ late TypeParameter classTypeParameter;
- Library enclosingLibrary;
- Class enclosingClass;
- Procedure enclosingMember;
+ late Library enclosingLibrary;
+ late Class enclosingClass;
+ late Procedure enclosingMember;
- Class otherClass;
+ late Class otherClass;
- InterfaceType objectLegacyRawType;
- InterfaceType enclosingLegacyRawType;
- InterfaceType otherLegacyRawType;
+ late InterfaceType objectLegacyRawType;
+ late InterfaceType enclosingLegacyRawType;
+ late InterfaceType otherLegacyRawType;
void addNode(TreeNode node) {
if (node is Expression) {
@@ -729,8 +729,8 @@
enclosingClass.addField(node);
} else if (node is Constructor) {
enclosingClass.addConstructor(node);
- } else if (node is RedirectingFactoryConstructor) {
- enclosingClass.addRedirectingFactoryConstructor(node);
+ } else if (node is RedirectingFactory) {
+ enclosingClass.addRedirectingFactory(node);
} else {
throw "Unexpected class member: ${node.runtimeType}";
}
@@ -756,7 +756,7 @@
VariableDeclaration makeVariable() => new VariableDeclaration(null);
- TypeParameter makeTypeParameter([String name]) {
+ TypeParameter makeTypeParameter([String? name]) {
return new TypeParameter(name, objectLegacyRawType, const DynamicType());
}
@@ -802,10 +802,10 @@
}
}
-negative1Test(String name, Node Function(TestHarness test) nodeProvider,
- dynamic Function(Node node) matcher) {
+negative1Test(String name, Node? Function(TestHarness test) nodeProvider,
+ dynamic Function(Node? node) matcher) {
TestHarness testHarness = new TestHarness();
- Node node = nodeProvider(testHarness);
+ Node? node = nodeProvider(testHarness);
test(
name,
() {
@@ -818,10 +818,10 @@
);
}
-negative2Test(String name, List<Node> Function(TestHarness test) nodeProvider,
- dynamic Function(Node node, Node other) matcher) {
+negative2Test(String name, List<Node?> Function(TestHarness test) nodeProvider,
+ dynamic Function(Node? node, Node? other) matcher) {
TestHarness testHarness = new TestHarness();
- List<Node> nodes = nodeProvider(testHarness);
+ List<Node?> nodes = nodeProvider(testHarness);
if (nodes.length != 2) throw "Needs exactly 2 nodes: Node and other!";
test(
name,
diff --git a/pkg/kernel/tool/smoke_test_quick.dart b/pkg/kernel/tool/smoke_test_quick.dart
index 6ca6e19..b5a0b9a 100644
--- a/pkg/kernel/tool/smoke_test_quick.dart
+++ b/pkg/kernel/tool/smoke_test_quick.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'dart:io';
final String repoDir = _computeRepoDir();
diff --git a/pkg/nnbd_migration/lib/migration_cli.dart b/pkg/nnbd_migration/lib/migration_cli.dart
index a9893c0..9a0a6ec 100644
--- a/pkg/nnbd_migration/lib/migration_cli.dart
+++ b/pkg/nnbd_migration/lib/migration_cli.dart
@@ -1000,7 +1000,7 @@
bool get isPreviewServerRunning => _task?.isPreviewServerRunning ?? false;
LineInfo getLineInfo(String path) =>
- (context.currentSession.getFile2(path) as FileResult).lineInfo;
+ (context.currentSession.getFile(path) as FileResult).lineInfo;
void prepareToRerun() {
var driver = context.driver;
@@ -1015,11 +1015,11 @@
var pathsProcessed = <String?>{};
for (var path in pathsToProcess) {
if (pathsProcessed.contains(path)) continue;
- var result = await driver.getResolvedLibrary2(path);
+ var result = await driver.getResolvedLibrary(path);
// Parts will either be found in a library, below, or if the library
// isn't [isIncluded], will be picked up in the final loop.
if (result is ResolvedLibraryResult) {
- for (var unit in result.units!) {
+ for (var unit in result.units) {
if (!pathsProcessed.contains(unit.path)) {
await process(unit);
pathsProcessed.add(unit.path);
@@ -1029,7 +1029,7 @@
}
for (var path in pathsToProcess.difference(pathsProcessed)) {
- var result = await driver.getResolvedUnit2(path);
+ var result = await driver.getResolvedUnit(path);
if (result is ResolvedUnitResult) {
await process(result);
}
@@ -1049,7 +1049,7 @@
// Process each source file.
bool allSourcesAlreadyMigrated = true;
await processResources((ResolvedUnitResult result) async {
- if (!result.unit!.featureSet.isEnabled(Feature.non_nullable)) {
+ if (!result.unit.featureSet.isEnabled(Feature.non_nullable)) {
allSourcesAlreadyMigrated = false;
}
_progressBar.tick();
@@ -1093,7 +1093,7 @@
});
await processResources((ResolvedUnitResult result) async {
_progressBar.tick();
- if (_migrationCli.shouldBeMigrated(result.path!)) {
+ if (_migrationCli.shouldBeMigrated(result.path)) {
await _task!.finalizeUnit(result);
}
});
diff --git a/pkg/nnbd_migration/lib/nnbd_migration.dart b/pkg/nnbd_migration/lib/nnbd_migration.dart
index e79df1f..aaa17c7 100644
--- a/pkg/nnbd_migration/lib/nnbd_migration.dart
+++ b/pkg/nnbd_migration/lib/nnbd_migration.dart
@@ -175,6 +175,12 @@
'Removed a null-aware assignment, because the target cannot be null',
kind: NullabilityFixKind.removeDeadCode);
+ /// A built_value `@nullable` annotation has been discarded.
+ static const removeNullableAnnotation = NullabilityFixDescription._(
+ appliedMessage: 'Discarded a use of the built_value annotation @nullable',
+ kind: NullabilityFixKind.removeNullableAnnotation,
+ );
+
/// A message used to indicate a fix has been applied.
final String appliedMessage;
@@ -293,6 +299,7 @@
removeAs,
removeDeadCode,
removeLanguageVersionComment,
+ removeNullableAnnotation,
replaceVar,
typeNotMadeNullable,
typeNotMadeNullableDueToHint,
diff --git a/pkg/nnbd_migration/lib/src/edge_builder.dart b/pkg/nnbd_migration/lib/src/edge_builder.dart
index 42249d9..d155843 100644
--- a/pkg/nnbd_migration/lib/src/edge_builder.dart
+++ b/pkg/nnbd_migration/lib/src/edge_builder.dart
@@ -141,6 +141,12 @@
/// return statements.
DecoratedType? _currentFunctionType;
+ /// If the innermost enclosing executable is a constructor with field formal
+ /// parameters, a map from each field's getter to the corresponding field
+ /// formal parameter element. Otherwise, an empty map.
+ Map<PropertyAccessorElement, FieldFormalParameterElement>
+ _currentFieldFormals = const {};
+
FunctionExpression? _currentFunctionExpression;
/// The [ClassElement] or [ExtensionElement] of the current class or extension
@@ -192,7 +198,7 @@
///
/// Note that this is not guaranteed to be complete. It is used to make hard
/// edges on a best-effort basis.
- var _postDominatedLocals = _ScopedLocalSet();
+ var _postDominatedLocals = ScopedSet<Element>();
/// Map whose keys are expressions of the form `a?.b` on the LHS of
/// assignments, and whose values are the nullability nodes corresponding to
@@ -242,6 +248,10 @@
_whereOrNullTransformer =
WhereOrNullTransformer(typeProvider, _typeSystem);
+ /// The synthetic element we use as a stand-in for `this` when analyzing
+ /// extension methods.
+ Element get _extensionThis => DynamicElementImpl.instance;
+
/// Gets the decorated type of [element] from [_variables], performing any
/// necessary substitutions.
///
@@ -319,7 +329,7 @@
source: targetType,
destination: onType,
hard: targetExpression == null ||
- _postDominatedLocals.isReferenceInScope(targetExpression));
+ _isReferenceInScope(targetExpression));
// (3) substitute those decorated types into the declared type of the
// extension method or extension property, so that the caller will match
// up parameter types and the return type appropriately.
@@ -507,8 +517,7 @@
bool isPure = otherOperand is SimpleIdentifier;
var conditionInfo = _ConditionInfo(node,
isPure: isPure,
- postDominatingIntent:
- _postDominatedLocals.isReferenceInScope(otherOperand),
+ postDominatingIntent: _isReferenceInScope(otherOperand),
trueGuard: otherNode,
falseDemonstratesNonNullIntent: otherNode);
_conditionInfo = notEqual ? conditionInfo.not(node) : conditionInfo;
@@ -886,18 +895,20 @@
_dispatch(node.parameters);
var parameterElement = node.declaredElement as FieldFormalParameterElement;
var parameterType = _variables!.decoratedElementType(parameterElement);
- var field = parameterElement.field!;
- _fieldsNotInitializedByConstructor!.remove(field);
- var fieldType = _variables!.decoratedElementType(field);
- var origin = FieldFormalParameterOrigin(source, node);
- if (node.type == null) {
- _linkDecoratedTypes(parameterType, fieldType, origin, isUnion: false);
- _checkAssignment(origin, FixReasonTarget.root,
- source: fieldType, destination: parameterType, hard: false);
- } else {
- _dispatch(node.type);
- _checkAssignment(origin, FixReasonTarget.root,
- source: parameterType, destination: fieldType, hard: true);
+ var field = parameterElement.field;
+ if (field != null) {
+ _fieldsNotInitializedByConstructor!.remove(field);
+ var fieldType = _variables!.decoratedElementType(field);
+ var origin = FieldFormalParameterOrigin(source, node);
+ if (node.type == null) {
+ _linkDecoratedTypes(parameterType, fieldType, origin, isUnion: false);
+ _checkAssignment(origin, FixReasonTarget.root,
+ source: fieldType, destination: parameterType, hard: false);
+ } else {
+ _dispatch(node.type);
+ _checkAssignment(origin, FixReasonTarget.root,
+ source: parameterType, destination: fieldType, hard: true);
+ }
}
return null;
@@ -928,7 +939,7 @@
_elementsWrittenToInLocalFunction;
try {
_elementsWrittenToInLocalFunction = {};
- _postDominatedLocals = _ScopedLocalSet();
+ _postDominatedLocals = ScopedSet<Element>();
_flowAnalysis!.functionExpression_begin(node);
_dispatch(node.functionExpression);
_flowAnalysis!.functionExpression_end();
@@ -983,9 +994,11 @@
_addParametersToFlowAnalysis(node.parameters);
var previousFunction = _currentFunctionExpression;
var previousFunctionType = _currentFunctionType;
+ var previousFieldFormals = _currentFieldFormals;
_currentFunctionExpression = node;
_currentFunctionType =
_variables!.decoratedElementType(node.declaredElement!);
+ _currentFieldFormals = const {};
var previousPostDominatedLocals = _postDominatedLocals;
var previousElementsWrittenToInLocalFunction =
_elementsWrittenToInLocalFunction;
@@ -993,7 +1006,7 @@
if (node.parent is! FunctionDeclaration) {
_elementsWrittenToInLocalFunction = {};
}
- _postDominatedLocals = _ScopedLocalSet();
+ _postDominatedLocals = ScopedSet<Element>();
_postDominatedLocals.doScoped(
elements: node.declaredElement!.parameters,
action: () => _dispatch(node.body));
@@ -1010,6 +1023,7 @@
previousElementsWrittenToInLocalFunction;
}
_currentFunctionType = previousFunctionType;
+ _currentFieldFormals = previousFieldFormals;
_currentFunctionExpression = previousFunction;
_postDominatedLocals = previousPostDominatedLocals;
}
@@ -1238,8 +1252,7 @@
decoratedType.node, IsCheckMainTypeOrigin(source, type));
_conditionInfo = _ConditionInfo(node,
isPure: expression is SimpleIdentifier,
- postDominatingIntent:
- _postDominatedLocals.isReferenceInScope(expression),
+ postDominatingIntent: _isReferenceInScope(expression),
trueDemonstratesNonNullIntent: expressionNode);
if (node.notOperator != null) {
_conditionInfo = _conditionInfo!.not(node);
@@ -1377,7 +1390,7 @@
}
_variables!.recordDecoratedExpressionType(node, expressionType);
}
- _handleArgumentErrorCheckNotNull(node);
+ _handleCustomCheckNotNull(node);
_handleQuiverCheckNotNull(node);
return expressionType;
}
@@ -1645,7 +1658,7 @@
DecoratedType? visitSimpleIdentifier(SimpleIdentifier node) {
DecoratedType? targetType;
DecoratedType? result;
- var staticElement = getWriteOrReadElement(node);
+ var staticElement = _favorFieldFormalElements(getWriteOrReadElement(node));
if (staticElement is PromotableElement) {
if (!node.inDeclarationContext()) {
var promotedType = _flowAnalysis!.variableRead(node, staticElement);
@@ -2004,7 +2017,7 @@
//
// We cannot make a hard edge from y to never in this case.
if (node.variables.length == 1) {
- _postDominatedLocals.add(node.variables.single.declaredElement);
+ _postDominatedLocals.add(node.variables.single.declaredElement!);
}
return null;
@@ -2061,11 +2074,26 @@
// there's nothing to do.
if (_currentExtendedType == null) return;
var origin = ImplicitThisOrigin(source, node);
- var hard =
- _postDominatedLocals.isInScope(_postDominatedLocals.extensionThis);
+ var hard = _postDominatedLocals.isInScope(_extensionThis);
_graph.makeNonNullable(thisType!.node, origin, hard: hard, guards: _guards);
}
+ /// Computes the map to be stored in [_currentFieldFormals] while visiting the
+ /// constructor having the given [constructorElement].
+ Map<PropertyAccessorElement, FieldFormalParameterElement>
+ _computeFieldFormalMap(ConstructorElement constructorElement) {
+ var result = <PropertyAccessorElement, FieldFormalParameterElement>{};
+ for (var parameter in constructorElement.parameters) {
+ if (parameter is FieldFormalParameterElement) {
+ var getter = parameter.field?.getter;
+ if (getter != null) {
+ result[getter] = parameter;
+ }
+ }
+ }
+ return result;
+ }
+
@override
void _connect(NullabilityNode? source, NullabilityNode? destination,
EdgeOrigin origin, FixReasonTarget? edgeTarget,
@@ -2287,6 +2315,24 @@
}
}
+ /// If the innermost enclosing executable is a constructor with field formal
+ /// parameters, and [staticElement] refers to the getter associated with one
+ /// of those fields, returns the corresponding field formal parameter element.
+ /// Otherwise returns [staticElement] unchanged.
+ ///
+ /// This allows us to treat null checks on the field as though they were null
+ /// checks on the field formal parameter, which is not strictly correct, but
+ /// tends to produce migrations that are more in line with user intent.
+ Element? _favorFieldFormalElements(Element? staticElement) {
+ if (staticElement is PropertyAccessorElement) {
+ var fieldFormal = _currentFieldFormals[staticElement];
+ if (fieldFormal != null) {
+ return fieldFormal;
+ }
+ }
+ return staticElement;
+ }
+
DecoratedType _fixNumericTypes(
DecoratedType decoratedType, DartType? undecoratedType) {
if (decoratedType.type!.isDartCoreNum && undecoratedType!.isDartCoreInt) {
@@ -2315,30 +2361,6 @@
.decoratedTypeParameterBound((type.type as TypeParameterType).element);
}
- void _handleArgumentErrorCheckNotNull(MethodInvocation node) {
- var callee = node.methodName.staticElement;
- var calleeIsStatic = callee is ExecutableElement && callee.isStatic;
- var target = node.realTarget;
- bool targetIsArgumentError =
- (target is SimpleIdentifier && target.name == 'ArgumentError') ||
- (target is PrefixedIdentifier &&
- target.identifier.name == 'ArgumentError');
-
- if (calleeIsStatic &&
- targetIsArgumentError &&
- callee!.name == 'checkNotNull' &&
- node.argumentList.arguments.isNotEmpty) {
- var argument = node.argumentList.arguments.first;
- if (argument is SimpleIdentifier &&
- _postDominatedLocals.isReferenceInScope(argument)) {
- var argumentType =
- _variables!.decoratedElementType(argument.staticElement!);
- _graph.makeNonNullable(argumentType.node,
- ArgumentErrorCheckNotNullOrigin(source, argument));
- }
- }
- }
-
/// Creates the necessary constraint(s) for an assignment of the given
/// [expression] to a destination whose type is [destinationType].
///
@@ -2475,8 +2497,7 @@
}
}
if (assignmentExpression != null) {
- var element = _postDominatedLocals
- .referencedElement(assignmentExpression.leftHandSide);
+ var element = _referencedElement(assignmentExpression.leftHandSide);
if (element != null) {
_postDominatedLocals.removeFromAllScopes(element);
_elementsWrittenToInLocalFunction?.add(element);
@@ -2512,6 +2533,32 @@
redirectedClass.typeParameters);
}
+ void _handleCustomCheckNotNull(MethodInvocation node) {
+ var callee = node.methodName.staticElement;
+ if (node.argumentList.arguments.isNotEmpty &&
+ callee is ExecutableElement &&
+ callee.isStatic) {
+ var enclosingElement = callee.enclosingElement;
+ if (enclosingElement is ClassElement) {
+ if (callee.name == 'checkNotNull' &&
+ enclosingElement.name == 'ArgumentError' &&
+ callee.library.isDartCore ||
+ callee.name == 'checkNotNull' &&
+ enclosingElement.name == 'BuiltValueNullFieldError' &&
+ callee.library.source.uri.toString() ==
+ 'package:built_value/built_value.dart') {
+ var argument = node.argumentList.arguments.first;
+ if (argument is SimpleIdentifier && _isReferenceInScope(argument)) {
+ var argumentType = _variables!.decoratedElementType(
+ _favorFieldFormalElements(getWriteOrReadElement(argument))!);
+ _graph.makeNonNullable(argumentType.node,
+ ArgumentErrorCheckNotNullOrigin(source, argument));
+ }
+ }
+ }
+ }
+ }
+
void _handleExecutableDeclaration(
Declaration node,
ExecutableElement declaredElement,
@@ -2522,16 +2569,20 @@
FunctionBody body,
ConstructorName? redirectedConstructor) {
assert(_currentFunctionType == null);
+ assert(_currentFieldFormals.isEmpty);
_dispatchList(metadata);
_dispatch(returnType);
_createFlowAnalysis(node, parameters);
_dispatch(parameters);
_currentFunctionType = _variables!.decoratedElementType(declaredElement);
+ _currentFieldFormals = declaredElement is ConstructorElement
+ ? _computeFieldFormalMap(declaredElement)
+ : const {};
_addParametersToFlowAnalysis(parameters);
// Push a scope of post-dominated declarations on the stack.
_postDominatedLocals.pushScope(elements: declaredElement.parameters);
if (declaredElement.enclosingElement is ExtensionElement) {
- _postDominatedLocals.add(_postDominatedLocals.extensionThis);
+ _postDominatedLocals.add(_extensionThis);
}
try {
_dispatchList(initializers);
@@ -2619,6 +2670,7 @@
_flowAnalysis = null;
_assignedVariables = null;
_currentFunctionType = null;
+ _currentFieldFormals = const {};
_postDominatedLocals.popScope();
}
}
@@ -3090,8 +3142,7 @@
if (isQuiverCheckNull && node.argumentList.arguments.isNotEmpty) {
var argument = node.argumentList.arguments.first;
- if (argument is SimpleIdentifier &&
- _postDominatedLocals.isReferenceInScope(argument)) {
+ if (argument is SimpleIdentifier && _isReferenceInScope(argument)) {
var argumentType =
_variables!.decoratedElementType(argument.staticElement!);
_graph.makeNonNullable(
@@ -3147,6 +3198,11 @@
bool _isPrefix(Expression? e) =>
e is SimpleIdentifier && e.staticElement is PrefixElement;
+ bool _isReferenceInScope(Expression expression) {
+ var element = _referencedElement(expression);
+ return element != null && _postDominatedLocals.isInScope(element);
+ }
+
bool _isUntypedParameter(NormalFormalParameter parameter) {
if (parameter is SimpleFormalParameter) {
return parameter.type == null;
@@ -3261,6 +3317,19 @@
return node;
}
+ /// Returns the element referenced directly by [expression], if any; otherwise
+ /// returns `null`.
+ Element? _referencedElement(Expression expression) {
+ expression = expression.unParenthesized;
+ if (expression is SimpleIdentifier) {
+ return _favorFieldFormalElements(expression.staticElement);
+ } else if (expression is ThisExpression || expression is SuperExpression) {
+ return _extensionThis;
+ } else {
+ return null;
+ }
+ }
+
/// Determines whether uses of [expression] should cause hard edges to be
/// created in the nullability graph.
///
@@ -3288,8 +3357,7 @@
// expression is unconditionally executed, and (b) the expression is a
// reference to a local variable or parameter and it post-dominates the
// declaration of that local variable or parameter.
- return !isConditionallyExecuted &&
- _postDominatedLocals.isReferenceInScope(expression);
+ return !isConditionallyExecuted && _isReferenceInScope(expression);
}
DecoratedType? _thisOrSuper(Expression node) {
@@ -3772,30 +3840,3 @@
trueDemonstratesNonNullIntent: falseDemonstratesNonNullIntent,
falseDemonstratesNonNullIntent: trueDemonstratesNonNullIntent);
}
-
-/// A [ScopedSet] specific to the [Element]s of locals/parameters.
-///
-/// Contains helpers for dealing with expressions as if they were elements.
-class _ScopedLocalSet extends ScopedSet<Element?> {
- /// The synthetic element we use as a stand-in for `this` when analyzing
- /// extension methods.
- Element get extensionThis => DynamicElementImpl.instance;
-
- bool isReferenceInScope(Expression expression) {
- var element = referencedElement(expression);
- return element != null && isInScope(element);
- }
-
- /// Returns the element referenced directly by [expression], if any; otherwise
- /// returns `null`.
- Element? referencedElement(Expression expression) {
- expression = expression.unParenthesized;
- if (expression is SimpleIdentifier) {
- return expression.staticElement;
- } else if (expression is ThisExpression || expression is SuperExpression) {
- return extensionThis;
- } else {
- return null;
- }
- }
-}
diff --git a/pkg/nnbd_migration/lib/src/edit_plan.dart b/pkg/nnbd_migration/lib/src/edit_plan.dart
index 33728b9..b0e55fc 100644
--- a/pkg/nnbd_migration/lib/src/edit_plan.dart
+++ b/pkg/nnbd_migration/lib/src/edit_plan.dart
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'dart:convert';
+import 'dart:math';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/precedence.dart';
@@ -837,6 +838,8 @@
return node.members;
} else if (node is CompilationUnit) {
return [...node.directives, ...node.declarations];
+ } else if (node is MethodDeclaration) {
+ return node.metadata;
} else {
return null;
}
@@ -1424,8 +1427,8 @@
if (firstPlanIndex == 0 && lastPlanIndex == sequenceNodes!.length - 1) {
// We're removing everything. Try to remove additional whitespace so
// that we're left with just `()`, `{}`, or `[]`.
- var candidateFirstRemovalOffset =
- planner._backAcrossWhitespace(firstRemovalOffset, node!.offset);
+ var candidateFirstRemovalOffset = planner._backAcrossWhitespace(
+ firstRemovalOffset, min(firstRemovalOffset, node!.offset));
if (planner
._isJustAfter(candidateFirstRemovalOffset, const ['(', '[', '{'])) {
var candidateLastRemovalEnd =
@@ -1541,7 +1544,8 @@
if (parent is Block ||
parent is ClassDeclaration ||
parent is CompilationUnit ||
- parent is FormalParameter) {
+ parent is FormalParameter ||
+ parent is MethodDeclaration) {
// These parent types don't use separators.
return null;
} else {
diff --git a/pkg/nnbd_migration/lib/src/fix_aggregator.dart b/pkg/nnbd_migration/lib/src/fix_aggregator.dart
index 7e74f7e..ddf1bb4 100644
--- a/pkg/nnbd_migration/lib/src/fix_aggregator.dart
+++ b/pkg/nnbd_migration/lib/src/fix_aggregator.dart
@@ -911,6 +911,34 @@
}
/// Implementation of [NodeChange] specialized for operating on
+/// [MethodDeclaration] nodes.
+class NodeChangeForMethodDeclaration extends NodeChange<MethodDeclaration> {
+ /// If non-null, indicates a `@nullable` annotation which should be removed
+ /// from this node.
+ Annotation? annotationToRemove;
+
+ /// If [annotationToRemove] is non-null, the information that should be
+ /// contained in the edit.
+ AtomicEditInfo? removeAnnotationInfo;
+
+ NodeChangeForMethodDeclaration() : super._();
+
+ @override
+ Iterable<String> get _toStringParts =>
+ [if (annotationToRemove != null) 'annotationToRemove'];
+
+ @override
+ EditPlan _apply(MethodDeclaration node, FixAggregator aggregator) {
+ return aggregator.planner.passThrough(node, innerPlans: [
+ if (annotationToRemove != null)
+ aggregator.planner
+ .removeNode(annotationToRemove!, info: removeAnnotationInfo),
+ ...aggregator.innerPlansForNode(node),
+ ]);
+ }
+}
+
+/// Implementation of [NodeChange] specialized for operating on
/// [MethodInvocation] nodes.
class NodeChangeForMethodInvocation
extends NodeChangeForExpression<MethodInvocation>
@@ -1423,6 +1451,10 @@
NodeChange visitIfStatement(IfStatement node) => NodeChangeForIfStatement();
@override
+ NodeChange visitMethodDeclaration(MethodDeclaration node) =>
+ NodeChangeForMethodDeclaration();
+
+ @override
NodeChange visitMethodInvocation(MethodInvocation node) =>
NodeChangeForMethodInvocation();
diff --git a/pkg/nnbd_migration/lib/src/fix_builder.dart b/pkg/nnbd_migration/lib/src/fix_builder.dart
index 77fc0d3..bcfdef6 100644
--- a/pkg/nnbd_migration/lib/src/fix_builder.dart
+++ b/pkg/nnbd_migration/lib/src/fix_builder.dart
@@ -141,7 +141,7 @@
TypeProvider typeProvider,
TypeSystemImpl typeSystem,
Variables? variables,
- LibraryElement definingLibrary,
+ LibraryElementImpl definingLibrary,
NullabilityMigrationListener? listener,
CompilationUnit? unit,
bool? warnOnWeakCode,
@@ -170,7 +170,7 @@
this._typeSystem,
this._variables,
this.source,
- LibraryElement definingLibrary,
+ LibraryElementImpl definingLibrary,
this.listener,
this.unit,
this.migrationResolutionHooks,
@@ -557,7 +557,7 @@
@override
void setCompoundAssignmentExpressionTypes(CompoundAssignmentExpression node) {
- assert(_assignmentLikeExpressionHandlers[node as Expression] == null);
+ assert(_assignmentLikeExpressionHandlers[node] == null);
if (node is AssignmentExpression) {
var handler = _AssignmentExpressionHandler(node);
_assignmentLikeExpressionHandlers[node] = handler;
@@ -1147,15 +1147,18 @@
// Potentially add an explicit type to a field formal parameter.
var decl = node.declaredElement as FieldFormalParameterElement;
var decoratedType = _fixBuilder._variables!.decoratedElementType(decl);
- var decoratedFieldType =
- _fixBuilder._variables!.decoratedElementType(decl.field!);
- var typeToAdd = _fixBuilder._variables!.toFinalType(decoratedType);
- var fieldFinalType =
- _fixBuilder._variables!.toFinalType(decoratedFieldType);
- if (typeToAdd is InterfaceType &&
- !_fixBuilder._typeSystem.isSubtypeOf(fieldFinalType, typeToAdd)) {
- (_fixBuilder._getChange(node) as NodeChangeForFieldFormalParameter)
- .addExplicitType = typeToAdd;
+ var field = decl.field;
+ if (field != null) {
+ var decoratedFieldType =
+ _fixBuilder._variables!.decoratedElementType(field);
+ var typeToAdd = _fixBuilder._variables!.toFinalType(decoratedType);
+ var fieldFinalType =
+ _fixBuilder._variables!.toFinalType(decoratedFieldType);
+ if (typeToAdd is InterfaceType &&
+ !_fixBuilder._typeSystem.isSubtypeOf(fieldFinalType, typeToAdd)) {
+ (_fixBuilder._getChange(node) as NodeChangeForFieldFormalParameter)
+ .addExplicitType = typeToAdd;
+ }
}
} else if (node.parameters != null) {
// Handle function-typed field formal parameters.
@@ -1198,6 +1201,31 @@
}
@override
+ void visitMethodDeclaration(MethodDeclaration node) {
+ if (node.isGetter && node.isAbstract) {
+ for (var annotation in node.metadata) {
+ if (annotation.arguments == null) {
+ var element = annotation.element;
+ if (element is PropertyAccessorElement &&
+ element.name == 'nullable') {
+ if (element.enclosingElement is CompilationUnitElement) {
+ if (element.library.source.uri.toString() ==
+ 'package:built_value/built_value.dart') {
+ var info = AtomicEditInfo(
+ NullabilityFixDescription.removeNullableAnnotation, {});
+ (_fixBuilder._getChange(node) as NodeChangeForMethodDeclaration)
+ ..annotationToRemove = annotation
+ ..removeAnnotationInfo = info;
+ }
+ }
+ }
+ }
+ }
+ }
+ super.visitMethodDeclaration(node);
+ }
+
+ @override
void visitTypeName(TypeName node) {
var decoratedType = _fixBuilder._variables!
.decoratedTypeAnnotation(_fixBuilder.source, node);
diff --git a/pkg/nnbd_migration/lib/src/front_end/info_builder.dart b/pkg/nnbd_migration/lib/src/front_end/info_builder.dart
index c6f6fb4..c6f4bb7 100644
--- a/pkg/nnbd_migration/lib/src/front_end/info_builder.dart
+++ b/pkg/nnbd_migration/lib/src/front_end/info_builder.dart
@@ -96,11 +96,11 @@
for (var filePath in sources) {
progressBar.tick();
var session = driverProvider!.getAnalysisSession(filePath);
- var result = await session.getResolvedLibrary2(filePath!);
+ var result = await session.getResolvedLibrary(filePath!);
if (result is ResolvedLibraryResult) {
- for (var unitResult in result.units!) {
+ for (var unitResult in result.units) {
var sourceInfo =
- sourceInfoMap[unitResult.unit!.declaredElement!.source];
+ sourceInfoMap[unitResult.unit.declaredElement!.source];
// Note: there might have been no information for this unit in
// sourceInfoMap. That can happen if there's an already-migrated
// library being referenced by the code being migrated, but not all
@@ -111,7 +111,7 @@
// referenced (we'll just skip the entire library because we'll only
// ever see its parts).
sourceInfo ??= SourceInformation();
- var edit = listener!.sourceChange.getFileEdit(unitResult.path!);
+ var edit = listener!.sourceChange.getFileEdit(unitResult.path);
var unit = _explainUnit(sourceInfo, unitResult, edit);
if (_pathsToProcess!.contains(unitResult.path)) {
units.add(unit);
@@ -185,7 +185,7 @@
break;
case NullabilityFixKind.addRequired:
var metaImport =
- _findImportDirective(result.unit!, 'package:meta/meta.dart');
+ _findImportDirective(result.unit, 'package:meta/meta.dart');
if (metaImport == null) {
edits.add(
EditDetail('Add /*required*/ hint', offset, 0, '/*required*/ '));
@@ -265,6 +265,10 @@
case NullabilityFixKind.addThen:
// We don't offer any edits around addition of `.then` to a future.
break;
+ case NullabilityFixKind.removeNullableAnnotation:
+ // We don't offer any edits around removal of built_value `@nullable`
+ // annotations.
+ break;
}
return edits;
}
@@ -273,7 +277,7 @@
List<NavigationSource> _computeNavigationSources(ResolvedUnitResult result) {
var collector = NavigationCollectorImpl();
computeDartNavigation(
- result.session.resourceProvider, collector, result.unit!, null, null);
+ result.session.resourceProvider, collector, result.unit, null, null);
collector.createRegions();
var files = collector.files;
var regions = collector.regions;
@@ -377,8 +381,8 @@
var content = result.content;
unitInfo.diskContent = content;
var alreadyMigrated =
- result.unit!.featureSet.isEnabled(Feature.non_nullable);
- unitInfo.wasExplicitlyOptedOut = result.unit!.languageVersionToken != null;
+ result.unit.featureSet.isEnabled(Feature.non_nullable);
+ unitInfo.wasExplicitlyOptedOut = result.unit.languageVersionToken != null;
if (alreadyMigrated) {
unitInfo.migrationStatus = UnitMigrationStatus.alreadyMigrated;
unitInfo.migrationStatusCanBeChanged = false;
@@ -401,7 +405,7 @@
// before we re-populate the region list.
regions.clear();
- var lineInfo = result.unit!.lineInfo;
+ var lineInfo = result.unit.lineInfo;
var insertions = <int?, List<AtomicEdit>>{};
var infosSeen = Set<AtomicEditInfo>.identity();
@@ -422,7 +426,7 @@
var end = offset + length;
// Insert the replacement text without deleting the replaced text.
if (replacement.isNotEmpty) {
- content = content!.replaceRange(end, end, replacement);
+ content = content.replaceRange(end, end, replacement);
(insertions[sourceOffset] ??= []).add(AtomicEdit.insert(replacement));
}
var info = edit.info;
diff --git a/pkg/nnbd_migration/lib/src/front_end/migration_summary.dart b/pkg/nnbd_migration/lib/src/front_end/migration_summary.dart
index 7a72ee6..90adae8 100644
--- a/pkg/nnbd_migration/lib/src/front_end/migration_summary.dart
+++ b/pkg/nnbd_migration/lib/src/front_end/migration_summary.dart
@@ -113,6 +113,8 @@
return 'typeNotMadeNullable';
case NullabilityFixKind.typeNotMadeNullableDueToHint:
return 'typeNotMadeNullableDueToHint';
+ case NullabilityFixKind.removeNullableAnnotation:
+ return 'removeNullableAnnotation';
}
}
}
diff --git a/pkg/nnbd_migration/lib/src/front_end/non_nullable_fix.dart b/pkg/nnbd_migration/lib/src/front_end/non_nullable_fix.dart
index bed1a35..fea31af 100644
--- a/pkg/nnbd_migration/lib/src/front_end/non_nullable_fix.dart
+++ b/pkg/nnbd_migration/lib/src/front_end/non_nullable_fix.dart
@@ -277,8 +277,8 @@
var edit = SourceEdit(offset, configText.length, newText);
listener.addSourceFileEdit(
'enable Null Safety language feature',
- Location(
- packageConfigFile.path, offset, newText.length, line, 0, 0, 0),
+ Location(packageConfigFile.path, offset, newText.length, line, 0,
+ endLine: 0, endColumn: 0),
SourceFileEdit(packageConfigFile.path, 0, edits: [edit]));
}
} on FormatException catch (e) {
@@ -599,7 +599,8 @@
var edit = SourceEdit(offset, 0, content);
listener.addSourceFileEdit(
'enable Null Safety language feature',
- Location(path, offset, content.length, line, 0, 0, 0),
+ Location(path, offset, content.length, line, 0,
+ endLine: 0, endColumn: 0),
SourceFileEdit(path, 0, edits: [edit]));
}
@@ -609,7 +610,8 @@
var edit = SourceEdit(offset, span.length, content);
listener.addSourceFileEdit(
'enable Null Safety language feature',
- Location(path, offset, content.length, line, 0, 0, 0),
+ Location(path, offset, content.length, line, 0,
+ endLine: 0, endColumn: 0),
SourceFileEdit(path, 0, edits: [edit]));
}
diff --git a/pkg/nnbd_migration/lib/src/front_end/unit_renderer.dart b/pkg/nnbd_migration/lib/src/front_end/unit_renderer.dart
index c5f8ef3..6b6257cc 100644
--- a/pkg/nnbd_migration/lib/src/front_end/unit_renderer.dart
+++ b/pkg/nnbd_migration/lib/src/front_end/unit_renderer.dart
@@ -43,6 +43,7 @@
NullabilityFixKind.removeAs,
NullabilityFixKind.addLate,
NullabilityFixKind.addLateDueToTestSetup,
+ NullabilityFixKind.removeNullableAnnotation,
NullabilityFixKind.addLateDueToHint,
NullabilityFixKind.addLateFinalDueToHint,
NullabilityFixKind.checkExpressionDueToHint,
@@ -337,6 +338,8 @@
return '$count type$s not made nullable';
case NullabilityFixKind.typeNotMadeNullableDueToHint:
return '$count type$s not made nullable due to hint$s';
+ case NullabilityFixKind.removeNullableAnnotation:
+ return '$count @nullable annotation$s removed';
}
}
diff --git a/pkg/nnbd_migration/lib/src/node_builder.dart b/pkg/nnbd_migration/lib/src/node_builder.dart
index 14fd871..b50bed1 100644
--- a/pkg/nnbd_migration/lib/src/node_builder.dart
+++ b/pkg/nnbd_migration/lib/src/node_builder.dart
@@ -446,9 +446,10 @@
@override
DecoratedType? visitMethodDeclaration(MethodDeclaration node) {
- _handleExecutableDeclaration(
+ var declaredElement = node.declaredElement;
+ var decoratedType = _handleExecutableDeclaration(
node,
- node.declaredElement!,
+ declaredElement!,
node.metadata,
node.returnType,
node.typeParameters,
@@ -456,6 +457,19 @@
null,
node.body,
null);
+ if (declaredElement is PropertyAccessorElement) {
+ // Store a decorated type for the synthetic field so that in case we try
+ // to access it later we won't crash (this could happen due to errors in
+ // the source code).
+ if (declaredElement.isGetter) {
+ _variables!.recordDecoratedElementType(
+ declaredElement.variable, decoratedType.returnType);
+ } else {
+ _variables!.recordDecoratedElementType(
+ declaredElement.variable, decoratedType.positionalParameters![0],
+ soft: true);
+ }
+ }
return null;
}
@@ -675,7 +689,7 @@
}
/// Common handling of function and method declarations.
- void _handleExecutableDeclaration(
+ DecoratedType _handleExecutableDeclaration(
AstNode node,
ExecutableElement declaredElement,
NodeList<Annotation>? metadata,
@@ -726,6 +740,7 @@
}
_variables!
.recordDecoratedElementType(declaredElement, decoratedFunctionType);
+ return decoratedFunctionType;
}
DecoratedType? _handleFormalParameter(
diff --git a/pkg/nnbd_migration/lib/src/nullability_migration_impl.dart b/pkg/nnbd_migration/lib/src/nullability_migration_impl.dart
index 07c652a..867f72a 100644
--- a/pkg/nnbd_migration/lib/src/nullability_migration_impl.dart
+++ b/pkg/nnbd_migration/lib/src/nullability_migration_impl.dart
@@ -6,6 +6,7 @@
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/dart/analysis/session.dart';
+import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/type_system.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
@@ -123,7 +124,7 @@
@override
void finalizeInput(ResolvedUnitResult result) {
- if (result.unit!.featureSet.isEnabled(Feature.non_nullable)) {
+ if (result.unit.featureSet.isEnabled(Feature.non_nullable)) {
// This library has already been migrated; nothing more to do.
return;
}
@@ -132,7 +133,7 @@
_propagated = true;
_graph.propagate();
}
- var unit = result.unit!;
+ var unit = result.unit;
var compilationUnit = unit.declaredElement!;
var library = compilationUnit.library;
var source = compilationUnit.source;
@@ -146,7 +147,7 @@
result.typeProvider,
library.typeSystem as TypeSystemImpl,
_variables,
- library,
+ library as LibraryElementImpl,
_permissive! ? listener : null,
unit,
warnOnWeakCode,
@@ -188,7 +189,7 @@
!_queriedUnmigratedDependencies,
'Should only query unmigratedDependencies after all calls to '
'prepareInput');
- if (result.unit!.featureSet.isEnabled(Feature.non_nullable)) {
+ if (result.unit.featureSet.isEnabled(Feature.non_nullable)) {
// This library has already been migrated; nothing more to do.
return;
}
@@ -202,7 +203,7 @@
instrumentation: _instrumentation);
_decoratedClassHierarchy = DecoratedClassHierarchy(_variables, _graph);
}
- var unit = result.unit!;
+ var unit = result.unit;
try {
DecoratedTypeParameterBounds.current = _decoratedTypeParameterBounds;
unit.accept(NodeBuilder(
@@ -219,12 +220,12 @@
}
void processInput(ResolvedUnitResult result) {
- if (result.unit!.featureSet.isEnabled(Feature.non_nullable)) {
+ if (result.unit.featureSet.isEnabled(Feature.non_nullable)) {
// This library has already been migrated; nothing more to do.
return;
}
ExperimentStatusException.sanityCheck(result);
- var unit = result.unit!;
+ var unit = result.unit;
try {
DecoratedTypeParameterBounds.current = _decoratedTypeParameterBounds;
unit.accept(EdgeBuilder(
@@ -270,8 +271,8 @@
edit.length,
startLocation.lineNumber,
startLocation.columnNumber,
- endLocation.lineNumber,
- endLocation.columnNumber,
+ endLine: endLocation.lineNumber,
+ endColumn: endLocation.columnNumber,
);
return location;
}
diff --git a/pkg/nnbd_migration/lib/src/variables.dart b/pkg/nnbd_migration/lib/src/variables.dart
index 44d0475..7222753 100644
--- a/pkg/nnbd_migration/lib/src/variables.dart
+++ b/pkg/nnbd_migration/lib/src/variables.dart
@@ -214,7 +214,8 @@
}
/// Associates decorated type information with the given [element].
- void recordDecoratedElementType(Element? element, DecoratedType? type) {
+ void recordDecoratedElementType(Element? element, DecoratedType? type,
+ {bool soft = false}) {
assert(() {
assert(element is! TypeParameterElement,
'Use recordDecoratedTypeParameterBound instead');
@@ -227,6 +228,9 @@
}
return true;
}());
+ if (soft && _decoratedElementTypes.containsKey(element)) {
+ return;
+ }
_decoratedElementTypes[element] = type;
}
diff --git a/pkg/nnbd_migration/test/abstract_context.dart b/pkg/nnbd_migration/test/abstract_context.dart
index 1b2b8a3..4e7b83e 100644
--- a/pkg/nnbd_migration/test/abstract_context.dart
+++ b/pkg/nnbd_migration/test/abstract_context.dart
@@ -45,6 +45,17 @@
String get testsPath => '$homePath/tests';
+ void addBuiltValuePackage() {
+ addPackageFile('built_value', 'built_value.dart', '''
+abstract class Built<V extends Built<V, B>, B extends Builder<V, B>> {}
+abstract class Builder<V extends Built<V, B>, B extends Builder<V, B>> {}
+const String nullable = 'nullable';
+class BuiltValueNullFieldError extends Error {
+ static T checkNotNull<T>(T? value, String type, String field) => value!;
+}
+''');
+ }
+
void addMetaPackage() {
addPackageFile('meta', 'meta.dart', r'''
library meta;
@@ -120,7 +131,7 @@
}
LineInfo getLineInfo(String path) =>
- (session.getFile2(path) as FileResult).lineInfo;
+ (session.getFile(path) as FileResult).lineInfo;
void setUp() {
setupResourceProvider();
diff --git a/pkg/nnbd_migration/test/abstract_single_unit.dart b/pkg/nnbd_migration/test/abstract_single_unit.dart
index dc9049a..7934ab3 100644
--- a/pkg/nnbd_migration/test/abstract_single_unit.dart
+++ b/pkg/nnbd_migration/test/abstract_single_unit.dart
@@ -38,7 +38,7 @@
Future<void> resolveTestUnit(String code) async {
addTestSource(code, testUri);
testAnalysisResult =
- await session.getResolvedUnit2(testFile) as ResolvedUnitResult;
+ await session.getResolvedUnit(testFile) as ResolvedUnitResult;
testUnit = testAnalysisResult.unit;
if (verifyNoTestUnitErrors) {
expect(testAnalysisResult.errors.where((AnalysisError error) {
diff --git a/pkg/nnbd_migration/test/api_test.dart b/pkg/nnbd_migration/test/api_test.dart
index 6d1fe57..cc1bc01 100644
--- a/pkg/nnbd_migration/test/api_test.dart
+++ b/pkg/nnbd_migration/test/api_test.dart
@@ -48,7 +48,7 @@
/// Optional parameter [removeViaComments] indicates whether dead code should
/// be removed in its entirety (the default) or removed by commenting it out.
Future<void> _checkMultipleFileChanges(
- Map<String, String> input, Map<String, String> expectedOutput,
+ Map<String, String> input, Map<String, dynamic> expectedOutput,
{Map<String, String> migratedInput = const {},
bool removeViaComments = false,
bool warnOnWeakCode = false,
@@ -65,9 +65,9 @@
removeViaComments: removeViaComments,
warnOnWeakCode: warnOnWeakCode);
for (var path in input.keys) {
- var resolvedLibrary = await session.getResolvedLibrary2(path);
+ var resolvedLibrary = await session.getResolvedLibrary(path);
if (resolvedLibrary is ResolvedLibraryResult) {
- for (var unit in resolvedLibrary.units!) {
+ for (var unit in resolvedLibrary.units) {
var errors =
unit.errors.where((e) => e.severity == Severity.error).toList();
if (!allowErrors && errors.isNotEmpty) {
@@ -80,18 +80,18 @@
expect(migration.unmigratedDependencies, isEmpty);
_betweenStages();
for (var path in input.keys) {
- var resolvedLibrary = await session.getResolvedLibrary2(path);
+ var resolvedLibrary = await session.getResolvedLibrary(path);
if (resolvedLibrary is ResolvedLibraryResult) {
- for (var unit in resolvedLibrary.units!) {
+ for (var unit in resolvedLibrary.units) {
migration.processInput(unit);
}
}
}
_betweenStages();
for (var path in input.keys) {
- var resolvedLibrary = await session.getResolvedLibrary2(path);
+ var resolvedLibrary = await session.getResolvedLibrary(path);
if (resolvedLibrary is ResolvedLibraryResult) {
- for (var unit in resolvedLibrary.units!) {
+ for (var unit in resolvedLibrary.units) {
migration.finalizeInput(unit);
}
}
@@ -116,7 +116,7 @@
///
/// Optional parameter [removeViaComments] indicates whether dead code should
/// be removed in its entirety (the default) or removed by commenting it out.
- Future<void> _checkSingleFileChanges(String content, String expected,
+ Future<void> _checkSingleFileChanges(String content, dynamic expected,
{Map<String, String> migratedInput = const {},
bool removeViaComments = false,
bool warnOnWeakCode = false,
@@ -495,6 +495,111 @@
await _checkSingleFileChanges(content, expected);
}
+ Future<void> test_built_value_non_nullable_getter() async {
+ addBuiltValuePackage();
+ var root = '$projectPath/lib';
+ var path1 = convertPath('$root/lib.dart');
+ var file1 = r'''
+import 'package:built_value/built_value.dart';
+
+part 'lib.g.dart';
+
+abstract class Foo implements Built<Foo, FooBuilder> {
+ int get value;
+ Foo._();
+ factory Foo([void Function(FooBuilder) updates]) = _$Foo;
+}
+''';
+ var expected1 = r'''
+import 'package:built_value/built_value.dart';
+
+part 'lib.g.dart';
+
+abstract class Foo implements Built<Foo, FooBuilder> {
+ int get value;
+ Foo._();
+ factory Foo([void Function(FooBuilder) updates]) = _$Foo;
+}
+''';
+ // Note: in a real-world scenario the generated file would be in a different
+ // directory but we don't need to simulate that detail for this test. Also,
+ // the generated file would have a lot more code in it, but we don't need to
+ // simulate all the details of what is generated.
+ var path2 = convertPath('$root/lib.g.dart');
+ var file2 = r'''
+part of 'lib.dart';
+
+class _$Foo extends Foo {
+ @override
+ final int value;
+
+ factory _$Foo([void Function(FooBuilder) updates]) => throw '';
+
+ _$Foo._({this.value}) : super._() {
+ BuiltValueNullFieldError.checkNotNull(value, 'Foo', 'value');
+ }
+}
+
+class FooBuilder implements Builder<Foo, FooBuilder> {
+ int get value => throw '';
+}
+''';
+ await _checkMultipleFileChanges(
+ {path1: file1, path2: file2}, {path1: expected1, path2: anything});
+ }
+
+ Future<void> test_built_value_nullable_getter() async {
+ addBuiltValuePackage();
+ var root = '$projectPath/lib';
+ var path1 = convertPath('$root/lib.dart');
+ var file1 = r'''
+import 'package:built_value/built_value.dart';
+
+part 'lib.g.dart';
+
+abstract class Foo implements Built<Foo, FooBuilder> {
+ @nullable
+ int get value;
+ Foo._();
+ factory Foo([void Function(FooBuilder) updates]) = _$Foo;
+}
+''';
+ var expected1 = r'''
+import 'package:built_value/built_value.dart';
+
+part 'lib.g.dart';
+
+abstract class Foo implements Built<Foo, FooBuilder> {
+ int? get value;
+ Foo._();
+ factory Foo([void Function(FooBuilder) updates]) = _$Foo;
+}
+''';
+ // Note: in a real-world scenario the generated file would be in a different
+ // directory but we don't need to simulate that detail for this test. Also,
+ // the generated file would have a lot more code in it, but we don't need to
+ // simulate all the details of what is generated.
+ var path2 = convertPath('$root/lib.g.dart');
+ var file2 = r'''
+part of 'lib.dart';
+
+class _$Foo extends Foo {
+ @override
+ final int value;
+
+ factory _$Foo([void Function(FooBuilder) updates]) => throw '';
+
+ _$Foo._({this.value}) : super._();
+}
+
+class FooBuilder implements Builder<Foo, FooBuilder> {
+ int get value => throw '';
+}
+''';
+ await _checkMultipleFileChanges(
+ {path1: file1, path2: file2}, {path1: expected1, path2: anything});
+ }
+
Future<void> test_call_already_migrated_extension() async {
var content = '''
import 'already_migrated.dart';
@@ -1111,6 +1216,41 @@
await _checkSingleFileChanges(content, expected);
}
+ Future<void> test_constructor_field_formal_resolves_to_getter() async {
+ var content = '''
+class C {
+ int get i => 0;
+ C(this.i);
+}
+''';
+ // It doesn't matter what the migration produces; we just want to make sure
+ // there isn't a crash.
+ await _checkSingleFileChanges(content, anything, allowErrors: true);
+ }
+
+ Future<void> test_constructor_field_formal_resolves_to_setter() async {
+ var content = '''
+class C {
+ set i(int value) {}
+ C(this.i);
+}
+''';
+ // It doesn't matter what the migration produces; we just want to make sure
+ // there isn't a crash.
+ await _checkSingleFileChanges(content, anything, allowErrors: true);
+ }
+
+ Future<void> test_constructor_field_formal_unresolved() async {
+ var content = '''
+class C {
+ C(this.i);
+}
+''';
+ // It doesn't matter what the migration produces; we just want to make sure
+ // there isn't a crash.
+ await _checkSingleFileChanges(content, anything, allowErrors: true);
+ }
+
Future<void> test_constructor_optional_param_factory() async {
var content = '''
class C {
@@ -6106,6 +6246,84 @@
await _checkSingleFileChanges(content, expected);
}
+ Future<void> test_non_null_intent_field_formal_assert() async {
+ var content = '''
+class C {
+ int i;
+ C(this.i) {
+ assert(i != null);
+ }
+}
+f(int j, bool b) {
+ if (b) {
+ C(j);
+ }
+}
+g() {
+ f(null, false);
+}
+''';
+ var expected = '''
+class C {
+ int i;
+ C(this.i) {
+ assert(i != null);
+ }
+}
+f(int? j, bool b) {
+ if (b) {
+ C(j!);
+ }
+}
+g() {
+ f(null, false);
+}
+''';
+ await _checkSingleFileChanges(content, expected);
+ }
+
+ Future<void> test_non_null_intent_field_formal_use() async {
+ var content = '''
+class C {
+ int i;
+ C(this.i) {
+ f(i);
+ }
+}
+f(int j) {
+ assert(j != null);
+}
+g(int k, bool b) {
+ if (b) {
+ C(k);
+ }
+}
+h() {
+ g(null, false);
+}
+''';
+ var expected = '''
+class C {
+ int i;
+ C(this.i) {
+ f(i);
+ }
+}
+f(int j) {
+ assert(j != null);
+}
+g(int? k, bool b) {
+ if (b) {
+ C(k!);
+ }
+}
+h() {
+ g(null, false);
+}
+''';
+ await _checkSingleFileChanges(content, expected);
+ }
+
Future<void>
test_non_null_intent_propagated_through_substitution_nodes() async {
var content = '''
diff --git a/pkg/nnbd_migration/test/edit_plan_test.dart b/pkg/nnbd_migration/test/edit_plan_test.dart
index 3cc00e7..135ec47 100644
--- a/pkg/nnbd_migration/test/edit_plan_test.dart
+++ b/pkg/nnbd_migration/test/edit_plan_test.dart
@@ -888,6 +888,39 @@
expect(changes.keys, [entry.offset]);
}
+ Future<void>
+ test_remove_metadata_from_defaultFormalParameter_all_full_line() async {
+ await analyze('''
+f({
+ @deprecated
+ int? x}) {}''');
+ var deprecated = findNode.annotation('@deprecated');
+ checkPlan(
+ planner!.passThrough(deprecated.parent,
+ innerPlans: [planner!.removeNode(deprecated)]),
+ '''
+f({
+ int? x}) {}''');
+ }
+
+ Future<void> test_remove_metadata_from_method_declaration() async {
+ await analyze('''
+class C {
+ @deprecated
+ f() {}
+}
+''');
+ var deprecated = findNode.annotation('@deprecated');
+ checkPlan(
+ planner!.passThrough(deprecated.parent,
+ innerPlans: [planner!.removeNode(deprecated)]),
+ '''
+class C {
+ f() {}
+}
+''');
+ }
+
Future<void> test_remove_parameter() async {
await analyze('f(int x, int y, int z) => null;');
var parameter = findNode.simple('y').parent!;
diff --git a/pkg/nnbd_migration/test/fix_builder_test.dart b/pkg/nnbd_migration/test/fix_builder_test.dart
index a9026b2..74fa1a8 100644
--- a/pkg/nnbd_migration/test/fix_builder_test.dart
+++ b/pkg/nnbd_migration/test/fix_builder_test.dart
@@ -5,6 +5,7 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/dart/element/type_provider.dart';
+import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/type_provider.dart';
import 'package:analyzer/src/dart/error/hint_codes.dart';
import 'package:analyzer/src/generated/element_type_provider.dart';
@@ -3886,7 +3887,7 @@
typeProvider,
typeSystem,
variables,
- definingLibrary,
+ definingLibrary as LibraryElementImpl,
null,
scope.thisOrAncestorOfType<CompilationUnit>(),
warnOnWeakCode,
diff --git a/pkg/nnbd_migration/test/front_end/info_builder_test.dart b/pkg/nnbd_migration/test/front_end/info_builder_test.dart
index e4da1b7..23a7900 100644
--- a/pkg/nnbd_migration/test/front_end/info_builder_test.dart
+++ b/pkg/nnbd_migration/test/front_end/info_builder_test.dart
@@ -24,7 +24,7 @@
@reflectiveTest
class BuildEnclosingMemberDescriptionTest extends AbstractAnalysisTest {
Future<ResolvedUnitResult> resolveTestFile() async {
- return await session.getResolvedUnit2(testFile!) as ResolvedUnitResult;
+ return await session.getResolvedUnit(testFile!) as ResolvedUnitResult;
}
Future<void> test_classConstructor_named() async {
@@ -35,7 +35,7 @@
''');
var result = await resolveTestFile();
ClassDeclaration class_ =
- result.unit!.declarations.single as ClassDeclaration;
+ result.unit.declarations.single as ClassDeclaration;
var constructor = class_.members.single;
expect(InfoBuilder.buildEnclosingMemberDescription(constructor),
equals("the constructor 'C.aaa'"));
@@ -49,7 +49,7 @@
''');
var result = await resolveTestFile();
ClassDeclaration class_ =
- result.unit!.declarations.single as ClassDeclaration;
+ result.unit.declarations.single as ClassDeclaration;
var constructor = class_.members.single;
expect(InfoBuilder.buildEnclosingMemberDescription(constructor),
equals("the default constructor of 'C'"));
@@ -63,7 +63,7 @@
''');
var result = await resolveTestFile();
ClassDeclaration class_ =
- result.unit!.declarations.single as ClassDeclaration;
+ result.unit.declarations.single as ClassDeclaration;
FieldDeclaration fieldDeclaration =
class_.members.single as FieldDeclaration;
var field = fieldDeclaration.fields.variables[0];
@@ -79,7 +79,7 @@
''');
var result = await resolveTestFile();
ClassDeclaration class_ =
- result.unit!.declarations.single as ClassDeclaration;
+ result.unit.declarations.single as ClassDeclaration;
FieldDeclaration fieldDeclaration =
class_.members.single as FieldDeclaration;
var type = fieldDeclaration.fields.type;
@@ -95,7 +95,7 @@
''');
var result = await resolveTestFile();
ClassDeclaration class_ =
- result.unit!.declarations.single as ClassDeclaration;
+ result.unit.declarations.single as ClassDeclaration;
var getter = class_.members.single;
expect(InfoBuilder.buildEnclosingMemberDescription(getter),
equals("the getter 'C.aaa'"));
@@ -109,7 +109,7 @@
''');
var result = await resolveTestFile();
ClassDeclaration class_ =
- result.unit!.declarations.single as ClassDeclaration;
+ result.unit.declarations.single as ClassDeclaration;
var method = class_.members.single;
expect(InfoBuilder.buildEnclosingMemberDescription(method),
equals("the method 'C.aaa'"));
@@ -123,7 +123,7 @@
''');
var result = await resolveTestFile();
ClassDeclaration class_ =
- result.unit!.declarations.single as ClassDeclaration;
+ result.unit.declarations.single as ClassDeclaration;
var operator = class_.members.single;
expect(InfoBuilder.buildEnclosingMemberDescription(operator),
equals("the operator 'C.=='"));
@@ -137,7 +137,7 @@
''');
var result = await resolveTestFile();
ClassDeclaration class_ =
- result.unit!.declarations.single as ClassDeclaration;
+ result.unit.declarations.single as ClassDeclaration;
var setter = class_.members.single;
expect(InfoBuilder.buildEnclosingMemberDescription(setter),
equals("the setter 'C.aaa='"));
@@ -151,7 +151,7 @@
''');
var result = await resolveTestFile();
ExtensionDeclaration extension_ =
- result.unit!.declarations.single as ExtensionDeclaration;
+ result.unit.declarations.single as ExtensionDeclaration;
var method = extension_.members.single;
expect(InfoBuilder.buildEnclosingMemberDescription(method),
equals("the method 'E.aaa'"));
@@ -165,7 +165,7 @@
''');
var result = await resolveTestFile();
ExtensionDeclaration extension_ =
- result.unit!.declarations.single as ExtensionDeclaration;
+ result.unit.declarations.single as ExtensionDeclaration;
var method = extension_.members.single;
expect(InfoBuilder.buildEnclosingMemberDescription(method),
equals("the method 'aaa' in unnamed extension on List<dynamic>"));
@@ -179,7 +179,7 @@
''');
var result = await resolveTestFile();
MixinDeclaration mixin_ =
- result.unit!.declarations.single as MixinDeclaration;
+ result.unit.declarations.single as MixinDeclaration;
var method = mixin_.members.single;
expect(InfoBuilder.buildEnclosingMemberDescription(method),
equals("the method 'C.aaa'"));
@@ -190,7 +190,7 @@
void aaa(value) {}
''');
var result = await resolveTestFile();
- var function = result.unit!.declarations.single;
+ var function = result.unit.declarations.single;
expect(InfoBuilder.buildEnclosingMemberDescription(function),
equals("the function 'aaa'"));
}
@@ -200,7 +200,7 @@
int get aaa => 7;
''');
var result = await resolveTestFile();
- var getter = result.unit!.declarations.single;
+ var getter = result.unit.declarations.single;
expect(InfoBuilder.buildEnclosingMemberDescription(getter),
equals("the getter 'aaa'"));
}
@@ -210,7 +210,7 @@
void set aaa(value) {}
''');
var result = await resolveTestFile();
- var setter = result.unit!.declarations.single;
+ var setter = result.unit.declarations.single;
expect(InfoBuilder.buildEnclosingMemberDescription(setter),
equals("the setter 'aaa='"));
}
@@ -221,7 +221,7 @@
''');
var result = await resolveTestFile();
TopLevelVariableDeclaration topLevelVariableDeclaration =
- result.unit!.declarations.single as TopLevelVariableDeclaration;
+ result.unit.declarations.single as TopLevelVariableDeclaration;
var variable = topLevelVariableDeclaration.variables.variables[0];
expect(InfoBuilder.buildEnclosingMemberDescription(variable),
equals("the variable 'i'"));
@@ -233,7 +233,7 @@
''');
var result = await resolveTestFile();
TopLevelVariableDeclaration topLevelVariableDeclaration =
- result.unit!.declarations.single as TopLevelVariableDeclaration;
+ result.unit.declarations.single as TopLevelVariableDeclaration;
var type = topLevelVariableDeclaration.variables.type;
expect(InfoBuilder.buildEnclosingMemberDescription(type),
equals("the variable 'i'"));
diff --git a/pkg/nnbd_migration/test/front_end/nnbd_migration_test_base.dart b/pkg/nnbd_migration/test/front_end/nnbd_migration_test_base.dart
index 96c987d..451a1d7 100644
--- a/pkg/nnbd_migration/test/front_end/nnbd_migration_test_base.dart
+++ b/pkg/nnbd_migration/test/front_end/nnbd_migration_test_base.dart
@@ -236,7 +236,7 @@
Future<void> _forEachPath(
void Function(ResolvedUnitResult) callback) async {
for (var testPath in testPaths) {
- var result = await driver!.currentSession.getResolvedUnit2(testPath!)
+ var result = await driver!.currentSession.getResolvedUnit(testPath!)
as ResolvedUnitResult;
callback(result);
}
diff --git a/pkg/nnbd_migration/test/instrumentation_test.dart b/pkg/nnbd_migration/test/instrumentation_test.dart
index be4ba0d..821b21c 100644
--- a/pkg/nnbd_migration/test/instrumentation_test.dart
+++ b/pkg/nnbd_migration/test/instrumentation_test.dart
@@ -149,9 +149,9 @@
removeViaComments: removeViaComments,
warnOnWeakCode: warnOnWeakCode);
var result =
- await session.getResolvedUnit2(sourcePath) as ResolvedUnitResult;
- source = result.unit!.declaredElement!.source;
- findNode = FindNode(content, result.unit!);
+ await session.getResolvedUnit(sourcePath) as ResolvedUnitResult;
+ source = result.unit.declaredElement!.source;
+ findNode = FindNode(content, result.unit);
migration.prepareInput(result);
expect(migration.unmigratedDependencies, isEmpty);
migration.processInput(result);
diff --git a/pkg/nnbd_migration/test/preview/preview_site_test.dart b/pkg/nnbd_migration/test/preview/preview_site_test.dart
index aeee9da..872d4d0 100644
--- a/pkg/nnbd_migration/test/preview/preview_site_test.dart
+++ b/pkg/nnbd_migration/test/preview/preview_site_test.dart
@@ -65,7 +65,7 @@
// Add a source change for analysis_options, which has no UnitInfo.
dartfixListener!.addSourceFileEdit(
'enable experiment',
- Location(analysisOptionsPath, 9, 0, 1, 9, 1, 9),
+ Location(analysisOptionsPath, 9, 0, 1, 9, endLine: 1, endColumn: 9),
SourceFileEdit(analysisOptionsPath, 0, edits: [
SourceEdit(9, 0, '\n enable-experiment:\n - non-nullable')
]));
@@ -100,7 +100,7 @@
file.writeAsStringSync(currentContent);
dartfixListener!.addSourceFileEdit(
'test change',
- Location(path, 10, 0, 1, 10, 1, 10),
+ Location(path, 10, 0, 1, 10, endLine: 1, endColumn: 10),
SourceFileEdit(path, 0, edits: [SourceEdit(10, 0, 'List args')]));
expect(() => site.performApply([]), throwsA(isA<StateError>()));
expect(file.readAsStringSync(), currentContent);
@@ -115,7 +115,7 @@
site.unitInfoMap[path] = UnitInfo(path)..diskContent = content;
dartfixListener!.addSourceFileEdit(
'test change',
- Location(path, 10, 0, 1, 10, 1, 10),
+ Location(path, 10, 0, 1, 10, endLine: 1, endColumn: 10),
SourceFileEdit(path, 0, edits: [
SourceEdit(10, 0, 'List args'),
SourceEdit(13, 0, '\n print(args);\n')
@@ -136,7 +136,7 @@
site.unitInfoMap[path] = UnitInfo(path)..diskContent = content;
dartfixListener!.addSourceFileEdit(
'test change',
- Location(path, 10, 0, 1, 10, 1, 10),
+ Location(path, 10, 0, 1, 10, endLine: 1, endColumn: 10),
SourceFileEdit(path, 0, edits: [SourceEdit(10, 0, 'List args')]));
site.performApply([]);
expect(file.readAsStringSync(), 'void main(List args) {}');
@@ -430,7 +430,7 @@
..wasExplicitlyOptedOut = true;
dartfixListener!.addSourceFileEdit(
'remove DLV comment',
- Location(path, 0, 14, 1, 1, 3, 1),
+ Location(path, 0, 14, 1, 1, endLine: 3, endColumn: 1),
SourceFileEdit(path, 0, edits: [SourceEdit(0, 14, '')]));
var navigationTree =
NavigationTreeRenderer(migrationInfo, state!.pathMapper).render();
@@ -471,7 +471,7 @@
..wasExplicitlyOptedOut = false;
dartfixListener!.addSourceFileEdit(
'test change',
- Location(path, 10, 0, 1, 10, 1, 10),
+ Location(path, 10, 0, 1, 10, endLine: 1, endColumn: 10),
SourceFileEdit(path, 0, edits: [SourceEdit(10, 0, 'List args')]));
var navigationTree =
NavigationTreeRenderer(migrationInfo, state!.pathMapper).render();
@@ -525,11 +525,11 @@
..wasExplicitlyOptedOut = false;
dartfixListener!.addSourceFileEdit(
'test change',
- Location(pathA, 10, 0, 1, 10, 1, 10),
+ Location(pathA, 10, 0, 1, 10, endLine: 1, endColumn: 10),
SourceFileEdit(pathA, 0, edits: [SourceEdit(10, 0, 'List args')]));
dartfixListener!.addSourceFileEdit(
'test change',
- Location(pathB, 10, 0, 1, 10, 1, 10),
+ Location(pathB, 10, 0, 1, 10, endLine: 1, endColumn: 10),
SourceFileEdit(pathB, 0, edits: [SourceEdit(10, 0, 'List args')]));
var navigationTree =
NavigationTreeRenderer(migrationInfo, state!.pathMapper).render();
@@ -563,7 +563,7 @@
..wasExplicitlyOptedOut = true;
dartfixListener!.addSourceFileEdit(
'remove DLV comment',
- Location(path, 0, 14, 1, 1, 3, 1),
+ Location(path, 0, 14, 1, 1, endLine: 3, endColumn: 1),
SourceFileEdit(path, 0, edits: [SourceEdit(0, 14, '')]));
var navigationTree =
NavigationTreeRenderer(migrationInfo, state!.pathMapper).render();
diff --git a/pkg/nnbd_migration/tool/trial_migration.dart b/pkg/nnbd_migration/tool/trial_migration.dart
index 4422c58..982cbf7 100644
--- a/pkg/nnbd_migration/tool/trial_migration.dart
+++ b/pkg/nnbd_migration/tool/trial_migration.dart
@@ -67,12 +67,12 @@
files.addAll(localFiles);
var session = context.currentSession;
LineInfo getLineInfo(String path) =>
- (session.getFile2(path) as FileResult).lineInfo;
+ (session.getFile(path) as FileResult).lineInfo;
var migration =
NullabilityMigration(listener, getLineInfo, permissive: true);
for (var file in localFiles) {
var resolvedUnit =
- await session.getResolvedUnit2(file) as ResolvedUnitResult;
+ await session.getResolvedUnit(file) as ResolvedUnitResult;
if (!resolvedUnit.errors.any((e) => e.severity == Severity.error)) {
migration.prepareInput(resolvedUnit);
} else {
@@ -81,14 +81,14 @@
}
for (var file in localFiles) {
var resolvedUnit =
- await session.getResolvedUnit2(file) as ResolvedUnitResult;
+ await session.getResolvedUnit(file) as ResolvedUnitResult;
if (!resolvedUnit.errors.any((e) => e.severity == Severity.error)) {
migration.processInput(resolvedUnit);
}
}
for (var file in localFiles) {
var resolvedUnit =
- await session.getResolvedUnit2(file) as ResolvedUnitResult;
+ await session.getResolvedUnit(file) as ResolvedUnitResult;
if (!resolvedUnit.errors.any((e) => e.severity == Severity.error)) {
migration.finalizeInput(resolvedUnit);
}
diff --git a/pkg/pkg.status b/pkg/pkg.status
index 79e9538..8386f5a 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -66,6 +66,7 @@
kernel/testcases/*: Skip # These are not tests but input for tests.
vm/test/transformations/type_flow/transformer_test: Slow, Pass
vm/testcases/*: SkipByDesign # These are not tests but input for tests.
+vm_service/test/cpu_samples_stream_test: Slow, Pass # Requires CPU sample buffer to fill.
wasm/*: SkipByDesign # These can't be run without running wasm:setup first.
[ $compiler == dart2analyzer ]
diff --git a/pkg/scrape/example/annotation_arguments.dart b/pkg/scrape/example/annotation_arguments.dart
new file mode 100644
index 0000000..cf5da95
--- /dev/null
+++ b/pkg/scrape/example/annotation_arguments.dart
@@ -0,0 +1,81 @@
+// 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.
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:scrape/scrape.dart';
+
+void main(List<String> arguments) {
+ Scrape()
+ ..addHistogram('Has argument list?')
+ ..addHistogram('Arguments', order: SortOrder.numeric)
+ ..addHistogram('Argument type')
+ ..addHistogram('Argument identifier')
+ ..addHistogram('Annotation')
+ ..addVisitor(() => AnnotationVisitor())
+ ..runCommandLine(arguments);
+}
+
+class AnnotationVisitor extends ScrapeVisitor {
+ @override
+ void visitAnnotation(Annotation node) {
+ record('Annotation', node.name.name);
+
+ var arguments = node.arguments;
+ if (arguments != null) {
+ record('Has argument list?', 'yes');
+ record('Arguments', arguments.arguments.length);
+ arguments.arguments.forEach(_recordArgument);
+ } else {
+ record('Has argument list?', 'no');
+ }
+
+ super.visitAnnotation(node);
+ }
+
+ void _recordArgument(AstNode? node) {
+ if (node is NamedExpression) {
+ _recordArgument(node.expression);
+ } else if (node is IfElement) {
+ _recordArgument(node.thenElement);
+ _recordArgument(node.elseElement);
+ } else if (node is ForElement) {
+ _recordArgument(node.body);
+ } else if (node is SpreadElement) {
+ _recordArgument(node.expression);
+ } else if (node is MapLiteralEntry) {
+ _recordArgument(node.key);
+ _recordArgument(node.value);
+ } else if (node is SimpleIdentifier || node is PrefixedIdentifier) {
+ record('Argument identifier', node.toString());
+ record('Argument type', 'identifier');
+ } else if (node is PrefixExpression) {
+ record('Argument type', 'unary operator');
+ } else if (node is BinaryExpression) {
+ record('Argument type', 'binary operator');
+ } else if (node is BooleanLiteral) {
+ record('Argument type', 'bool');
+ } else if (node is DoubleLiteral) {
+ record('Argument type', 'double');
+ } else if (node is IntegerLiteral) {
+ record('Argument type', 'int');
+ } else if (node is ListLiteral) {
+ record('Argument type', 'list');
+ node.elements.forEach(_recordArgument);
+ } else if (node is MethodInvocation) {
+ record('Argument type', 'method call');
+ } else if (node is NullLiteral) {
+ record('Argument type', 'null');
+ } else if (node is SetOrMapLiteral) {
+ record('Argument type', 'set or map');
+ node.elements.forEach(_recordArgument);
+ } else if (node is StringLiteral) {
+ record('Argument type', 'string');
+ } else if (node is SymbolLiteral) {
+ record('Argument type', 'symbol');
+ } else if (node == null) {
+ // Do nothing. Only happens for null else elements.
+ } else {
+ record('Argument type', node.runtimeType.toString());
+ }
+ }
+}
diff --git a/pkg/scrape/lib/src/histogram.dart b/pkg/scrape/lib/src/histogram.dart
index 74e35df..e27f137 100644
--- a/pkg/scrape/lib/src/histogram.dart
+++ b/pkg/scrape/lib/src/histogram.dart
@@ -86,14 +86,25 @@
}
}
- if (skipped > 0) print('And $skipped more less than 0.1%...');
+ if (skipped > 0) print('And $skipped more...');
// If we're counting numeric keys, show other statistics too.
if (_order == SortOrder.numeric && keys.isNotEmpty) {
var sum = keys.fold<int>(
0, (result, key) => result + (key as int) * _counts[key]!);
var average = sum / total;
- var median = _counts[keys[keys.length ~/ 2]];
+
+ // Find the median key where half the total count is below it.
+ var count = 0;
+ var median = -1;
+ for (var key in keys) {
+ count += _counts[key]!;
+ if (count >= total ~/ 2) {
+ median = key as int;
+ break;
+ }
+ }
+
print('Sum $sum, average ${average.toStringAsFixed(3)}, median $median');
}
}
diff --git a/pkg/test_runner/tool/orphan_files.dart b/pkg/test_runner/tool/orphan_files.dart
index 8d7e8f6..968458b 100644
--- a/pkg/test_runner/tool/orphan_files.dart
+++ b/pkg/test_runner/tool/orphan_files.dart
@@ -74,7 +74,7 @@
void _parseReferences(Set<String> importedPaths, String filePath) {
var absolute = Path(filePath).absolute.toNativePath();
- var parseResult = _analysisContext.currentSession.getParsedUnit2(absolute);
+ var parseResult = _analysisContext.currentSession.getParsedUnit(absolute);
var unit = (parseResult as ParsedUnitResult).unit;
void add(String importPath) {
diff --git a/pkg/testing/lib/src/analyze.dart b/pkg/testing/lib/src/analyze.dart
index 099d020..05009ec 100644
--- a/pkg/testing/lib/src/analyze.dart
+++ b/pkg/testing/lib/src/analyze.dart
@@ -18,21 +18,21 @@
import 'suite.dart' show Suite;
class Analyze extends Suite {
- final Uri analysisOptions;
+ final Uri? analysisOptions;
final List<Uri> uris;
final List<RegExp> exclude;
- final List<String> gitGrepPathspecs;
+ final List<String>? gitGrepPathspecs;
- final List<String> gitGrepPatterns;
+ final List<String>? gitGrepPatterns;
Analyze(this.analysisOptions, this.uris, this.exclude, this.gitGrepPathspecs,
this.gitGrepPatterns)
: super("analyze", "analyze", null);
- Future<Null> run(Uri packages, List<Uri> extraUris) {
+ Future<Null> run(Uri packages, List<Uri>? extraUris) {
List<Uri> allUris = new List<Uri>.from(uris);
if (extraUris != null) {
allUris.addAll(extraUris);
@@ -43,8 +43,8 @@
static Future<Analyze> fromJsonMap(
Uri base, Map json, List<Suite> suites) async {
- String optionsPath = json["options"];
- Uri optionsUri = optionsPath == null ? null : base.resolve(optionsPath);
+ String? optionsPath = json["options"];
+ Uri? optionsUri = optionsPath == null ? null : base.resolve(optionsPath);
List<Uri> uris = json["uris"].map<Uri>((relative) {
String r = relative;
@@ -54,9 +54,9 @@
List<RegExp> exclude =
json["exclude"].map<RegExp>((p) => new RegExp(p)).toList();
- Map gitGrep = json["git grep"];
- List<String> gitGrepPathspecs;
- List<String> gitGrepPatterns;
+ Map? gitGrep = json["git grep"];
+ List<String>? gitGrepPathspecs;
+ List<String>? gitGrepPatterns;
if (gitGrep != null) {
gitGrepPathspecs = gitGrep["pathspecs"] == null
? const <String>["."]
@@ -73,13 +73,13 @@
}
class AnalyzerDiagnostic {
- final String kind;
+ final String? kind;
- final String detailedKind;
+ final String? detailedKind;
- final String code;
+ final String? code;
- final Uri uri;
+ final Uri? uri;
final int line;
@@ -106,7 +106,7 @@
addPart() {
parts.add(line
.substring(start, index == -1 ? null : index)
- .replaceAllMapped(unescapePattern, (Match m) => m[1]));
+ .replaceAllMapped(unescapePattern, (Match m) => m[1]!));
}
while (index != -1) {
@@ -136,8 +136,8 @@
String toString() {
return kind == null
? "Malformed output from dartanalyzer:\n$message"
- : "${uri.toFilePath()}:$line:$startColumn: "
- "${kind == 'INFO' ? 'warning: hint' : kind.toLowerCase()}:\n"
+ : "${uri!.toFilePath()}:$line:$startColumn: "
+ "${kind == 'INFO' ? 'warning: hint' : kind!.toLowerCase()}:\n"
"[$code] $message";
}
}
@@ -154,12 +154,12 @@
/// Run dartanalyzer on all tests in [uris].
Future<Null> analyzeUris(
- Uri analysisOptions,
+ Uri? analysisOptions,
Uri packages,
List<Uri> uris,
List<RegExp> exclude,
- List<String> gitGrepPathspecs,
- List<String> gitGrepPatterns) async {
+ List<String>? gitGrepPathspecs,
+ List<String>? gitGrepPatterns) async {
if (uris.isEmpty) return;
String topLevel;
try {
@@ -205,7 +205,7 @@
arguments.addAll(
gitGrepPatterns.expand((String pattern) => <String>["-e", pattern]));
arguments.add("--");
- arguments.addAll(gitGrepPathspecs);
+ arguments.addAll(gitGrepPathspecs!);
filesToAnalyze.addAll(splitLines(await git("grep", arguments))
.map((String line) => line.trimRight()));
}
@@ -245,7 +245,7 @@
processAnalyzerOutput(Stream<AnalyzerDiagnostic> diagnostics) async {
await for (AnalyzerDiagnostic diagnostic in diagnostics) {
if (diagnostic.uri != null) {
- String path = toFilePath(diagnostic.uri);
+ String path = toFilePath(diagnostic.uri!);
if (!filesToAnalyze.contains(path)) continue;
}
String message = "$diagnostic";
@@ -283,7 +283,7 @@
}
Future<String> git(String command, Iterable<String> arguments,
- {String workingDirectory}) async {
+ {String? workingDirectory}) async {
ProcessResult result = await Process.run(
Platform.isWindows ? "git.bat" : "git",
<String>[command]..addAll(arguments),
diff --git a/pkg/testing/lib/src/chain.dart b/pkg/testing/lib/src/chain.dart
index c56fc21..8ab797b 100644
--- a/pkg/testing/lib/src/chain.dart
+++ b/pkg/testing/lib/src/chain.dart
@@ -115,7 +115,7 @@
.map((s) => s.substring(0, s.length - 3))
.toList();
TestExpectations expectations = await ReadTestExpectations(
- <String>[suite.statusFile.toFilePath()], {}, expectationSet);
+ <String>[suite.statusFile!.toFilePath()], {}, expectationSet);
Stream<TestDescription> stream = list(suite);
if (suite.processMultitests) {
stream = stream.transform(new MultitestTransformer());
@@ -149,12 +149,12 @@
final Set<Expectation> expectedOutcomes = processExpectedOutcomes(
expectations.expectations(description.shortName), description);
final StringBuffer sb = new StringBuffer();
- final Step lastStep = steps.isNotEmpty ? steps.last : null;
+ final Step? lastStep = steps.isNotEmpty ? steps.last : null;
final Iterator<Step> iterator = steps.iterator;
- Result result;
+ Result? result;
// Records the outcome of the last step that was run.
- Step lastStepRun;
+ Step? lastStepRun;
/// Performs one step of [iterator].
///
@@ -194,30 +194,30 @@
future = new Future.value(null);
}
future = future.then((_currentResult) async {
- Result currentResult = _currentResult;
+ Result? currentResult = _currentResult;
if (currentResult != null) {
logger.logStepComplete(completed, unexpectedResults.length,
- descriptions.length, suite, description, lastStepRun);
+ descriptions.length, suite, description, lastStepRun!);
result = currentResult;
if (currentResult.outcome == Expectation.Pass) {
// The input to the next step is the output of this step.
- return doStep(result.output);
+ return doStep(result!.output);
}
}
- await cleanUp(description, result);
+ await cleanUp(description, result!);
result =
- processTestResult(description, result, lastStep == lastStepRun);
- if (!expectedOutcomes.contains(result.outcome) &&
- !expectedOutcomes.contains(result.outcome.canonical)) {
- result.addLog("$sb");
- unexpectedResults[description] = result;
+ processTestResult(description, result!, lastStep == lastStepRun);
+ if (!expectedOutcomes.contains(result!.outcome) &&
+ !expectedOutcomes.contains(result!.outcome.canonical)) {
+ result!.addLog("$sb");
+ unexpectedResults[description] = result!;
unexpectedOutcomes[description] = expectedOutcomes;
logger.logUnexpectedResult(
- suite, description, result, expectedOutcomes);
+ suite, description, result!, expectedOutcomes);
exitCode = 1;
} else {
logger.logExpectedResult(
- suite, description, result, expectedOutcomes);
+ suite, description, result!, expectedOutcomes);
logger.logMessage(sb);
}
logger.logTestComplete(++completed, unexpectedResults.length,
@@ -241,7 +241,7 @@
if (unexpectedResults.isNotEmpty) {
unexpectedResults.forEach((TestDescription description, Result result) {
logger.logUnexpectedResult(
- suite, description, result, unexpectedOutcomes[description]);
+ suite, description, result, unexpectedOutcomes[description]!);
});
print("${unexpectedResults.length} failed:");
unexpectedResults.forEach((TestDescription description, Result result) {
@@ -278,7 +278,7 @@
TestDescription description, Result result, bool last) {
if (description is FileBasedTestDescription &&
description.multitestExpectations != null) {
- if (isError(description.multitestExpectations)) {
+ if (isError(description.multitestExpectations!)) {
result =
toNegativeTestResult(result, description.multitestExpectations);
}
@@ -286,14 +286,14 @@
if (result.outcome == Expectation.Pass) {
result.addLog("Negative test didn't report an error.\n");
} else if (result.outcome == Expectation.Fail) {
- result.addLog("Negative test reported an error as expeceted.\n");
+ result.addLog("Negative test reported an error as expected.\n");
}
result = toNegativeTestResult(result);
}
return result;
}
- Result toNegativeTestResult(Result result, [Set<String> expectations]) {
+ Result toNegativeTestResult(Result result, [Set<String>? expectations]) {
Expectation outcome = result.outcome;
if (outcome == Expectation.Pass) {
if (expectations == null) {
@@ -312,9 +312,9 @@
return result.copyWithOutcome(outcome);
}
- Future<void> cleanUp(TestDescription description, Result result) => null;
+ Future<void> cleanUp(TestDescription description, Result result) async {}
- Future<void> postRun() => null;
+ Future<void> postRun() async {}
}
abstract class Step<I, O, C extends ChainContext> {
@@ -355,25 +355,25 @@
Result<O> crash(error, StackTrace trace) => new Result<O>.crash(error, trace);
- Result<O> fail(O output, [error, StackTrace trace]) {
+ Result<O> fail(O output, [error, StackTrace? trace]) {
return new Result<O>.fail(output, error, trace);
}
}
class Result<O> {
- final O output;
+ final O? output;
final Expectation outcome;
final error;
- final StackTrace trace;
+ final StackTrace? trace;
final List<String> logs = <String>[];
/// If set, running the test with '-D$autoFixCommand' will automatically
/// update the test to match new expectations.
- final String autoFixCommand;
+ final String? autoFixCommand;
/// If set, the test can be fixed by running
///
@@ -391,7 +391,7 @@
Result.crash(error, StackTrace trace)
: this(null, Expectation.Crash, error, trace: trace);
- Result.fail(O output, [error, StackTrace trace])
+ Result.fail(O output, [error, StackTrace? trace])
: this(output, Expectation.Fail, error, trace: trace);
bool get isPass => outcome == Expectation.Pass;
@@ -420,7 +420,8 @@
Future<Null> runChain(CreateContext f, Map<String, String> environment,
Set<String> selectors, String jsonText) {
return withErrorHandling(() async {
- Chain suite = new Suite.fromJsonMap(Uri.base, json.decode(jsonText));
+ Chain suite =
+ new Suite.fromJsonMap(Uri.base, json.decode(jsonText)) as Chain;
print("Running ${suite.name}");
ChainContext context = await f(suite, environment);
return context.run(suite, selectors);
diff --git a/pkg/testing/lib/src/discover.dart b/pkg/testing/lib/src/discover.dart
index 3fd09e9..6b761ab 100644
--- a/pkg/testing/lib/src/discover.dart
+++ b/pkg/testing/lib/src/discover.dart
@@ -20,10 +20,10 @@
<String>["-c", "--packages=${packageConfig.toFilePath()}"];
Stream<FileBasedTestDescription> listTests(List<Uri> testRoots,
- {Pattern pattern}) {
+ {Pattern? pattern}) {
StreamController<FileBasedTestDescription> controller =
new StreamController<FileBasedTestDescription>();
- Map<Uri, StreamSubscription> subscriptions = <Uri, StreamSubscription>{};
+ Map<Uri, StreamSubscription?> subscriptions = <Uri, StreamSubscription>{};
for (Uri testRootUri in testRoots) {
subscriptions[testRootUri] = null;
Directory testRoot = new Directory.fromUri(testRootUri);
@@ -32,8 +32,9 @@
Stream<FileSystemEntity> stream =
testRoot.list(recursive: true, followLinks: false);
var subscription = stream.listen((FileSystemEntity entity) {
- FileBasedTestDescription description = FileBasedTestDescription
- .from(testRootUri, entity, pattern: pattern);
+ FileBasedTestDescription? description = FileBasedTestDescription.from(
+ testRootUri, entity,
+ pattern: pattern);
if (description != null) {
controller.add(description);
}
@@ -59,7 +60,7 @@
}
Uri computePackageConfig() {
- String path = Platform.packageConfig;
+ String? path = Platform.packageConfig;
if (path != null) return Uri.base.resolve(path);
return Uri.base.resolve(".packages");
}
@@ -72,7 +73,7 @@
: null;
Uri computeDartSdk() {
- String dartSdkPath = Platform.environment["DART_SDK"] ?? _dartSdk;
+ String? dartSdkPath = Platform.environment["DART_SDK"] ?? _dartSdk;
if (dartSdkPath != null) {
return Uri.base.resolveUri(new Uri.file(dartSdkPath));
} else {
@@ -83,7 +84,7 @@
}
Future<Process> startDart(Uri program,
- [List<String> arguments, List<String> vmArguments]) {
+ [List<String>? arguments, List<String>? vmArguments]) {
List<String> allArguments = <String>[];
allArguments.addAll(vmArguments ?? dartArguments);
allArguments.add(program.toFilePath());
diff --git a/pkg/testing/lib/src/error_handling.dart b/pkg/testing/lib/src/error_handling.dart
index 452e4b7..872f2f0 100644
--- a/pkg/testing/lib/src/error_handling.dart
+++ b/pkg/testing/lib/src/error_handling.dart
@@ -12,13 +12,14 @@
import 'log.dart';
-Future<T> withErrorHandling<T>(Future<T> f(), {Logger logger}) async {
+Future<T?> withErrorHandling<T>(Future<T> f(), {Logger? logger}) async {
final ReceivePort port = new ReceivePort();
try {
return await f();
} catch (e, trace) {
exitCode = 1;
stderr.writeln(e);
+ // ignore: unnecessary_null_comparison
if (trace != null) {
stderr.writeln(trace);
}
diff --git a/pkg/testing/lib/src/expectation.dart b/pkg/testing/lib/src/expectation.dart
index 58efce8..153adee 100644
--- a/pkg/testing/lib/src/expectation.dart
+++ b/pkg/testing/lib/src/expectation.dart
@@ -42,7 +42,7 @@
String toString() => name;
- static Expectation fromGroup(ExpectationGroup group) {
+ static Expectation? fromGroup(ExpectationGroup group) {
switch (group) {
case ExpectationGroup.Crash:
return Expectation.Crash;
@@ -57,7 +57,6 @@
case ExpectationGroup.Timeout:
return Expectation.Timeout;
}
- throw "Unhandled group: '$group'.";
}
}
@@ -89,8 +88,8 @@
Map<String, Expectation> internalMap =
new Map<String, Expectation>.from(Default.internalMap);
for (Map map in data) {
- String name;
- String group;
+ String? name;
+ String? group;
map.forEach((_key, _value) {
String key = _key;
String value = _value;
@@ -113,12 +112,12 @@
if (group == null) {
throw "No group provided in '$map'";
}
- Expectation expectation = new Expectation(name, groupFromString(group));
- name = name.toLowerCase();
+ Expectation expectation = new Expectation(name!, groupFromString(group!));
+ name = name!.toLowerCase();
if (internalMap.containsKey(name)) {
throw "Duplicated expectation name: '$name'.";
}
- internalMap[name] = expectation;
+ internalMap[name!] = expectation;
}
return new ExpectationSet(internalMap);
}
diff --git a/pkg/testing/lib/src/log.dart b/pkg/testing/lib/src/log.dart
index 7e6fafd..d46ab0a 100644
--- a/pkg/testing/lib/src/log.dart
+++ b/pkg/testing/lib/src/log.dart
@@ -78,19 +78,19 @@
class StdoutLogger implements Logger {
const StdoutLogger();
- void logTestStart(int completed, int failed, int total, Suite suite,
- TestDescription description) {}
+ void logTestStart(int completed, int failed, int total, Suite? suite,
+ TestDescription? description) {}
- void logTestComplete(int completed, int failed, int total, Suite suite,
- TestDescription description) {
+ void logTestComplete(int completed, int failed, int total, Suite? suite,
+ TestDescription? description) {
String message = formatProgress(completed, failed, total);
if (suite != null) {
- message += ": ${formatTestDescription(suite, description)}";
+ message += ": ${formatTestDescription(suite, description!)}";
}
logProgress(message);
}
- void logStepStart(int completed, int failed, int total, Suite suite,
+ void logStepStart(int completed, int failed, int total, Suite? suite,
TestDescription description, Step step) {
String message = formatProgress(completed, failed, total);
if (suite != null) {
@@ -102,7 +102,7 @@
logProgress(message);
}
- void logStepComplete(int completed, int failed, int total, Suite suite,
+ void logStepComplete(int completed, int failed, int total, Suite? suite,
TestDescription description, Step step) {
if (!step.isAsync) return;
String message = formatProgress(completed, failed, total);
@@ -152,7 +152,7 @@
void logUnexpectedResult(Suite suite, TestDescription description,
Result result, Set<Expectation> expectedOutcomes) {
print("${eraseLine}UNEXPECTED: ${suite.name}/${description.shortName}");
- Uri statusFile = suite.statusFile;
+ Uri? statusFile = suite.statusFile;
if (statusFile != null) {
String path = statusFile.toFilePath();
if (result.outcome == Expectation.Pass) {
@@ -186,6 +186,7 @@
void logUncaughtError(error, StackTrace stackTrace) {
logMessage(error);
+ // ignore: unnecessary_null_comparison
if (stackTrace != null) {
logMessage(stackTrace);
}
diff --git a/pkg/testing/lib/src/multitest.dart b/pkg/testing/lib/src/multitest.dart
index d87ac1b..62bb63e 100644
--- a/pkg/testing/lib/src/multitest.dart
+++ b/pkg/testing/lib/src/multitest.dart
@@ -51,8 +51,8 @@
nextTest:
await for (TestDescription test in stream) {
- FileBasedTestDescription multitest;
- String contents;
+ FileBasedTestDescription? multitest;
+ String? contents;
if (test is FileBasedTestDescription) {
contents = await test.file.readAsString();
if (contents.contains(multitestMarker)) {
@@ -73,11 +73,11 @@
"none": new Set<String>(),
};
int lineNumber = 0;
- for (String line in splitLines(contents)) {
+ for (String line in splitLines(contents!)) {
lineNumber++;
int index = line.indexOf(multitestMarker);
- String subtestName;
- List<String> subtestOutcomesList;
+ String? subtestName;
+ List<String>? subtestOutcomesList;
if (index != -1) {
String annotationText =
line.substring(index + _multitestMarkerLength).trim();
@@ -102,7 +102,7 @@
lines.add(line);
Set<String> subtestOutcomes =
outcomes.putIfAbsent(subtestName, () => new Set<String>());
- if (subtestOutcomesList.length != 1 ||
+ if (subtestOutcomesList!.length != 1 ||
subtestOutcomesList.single != "continued") {
for (String outcome in subtestOutcomesList) {
if (validOutcomes.contains(outcome)) {
@@ -125,8 +125,9 @@
Directory generated =
new Directory.fromUri(root.resolve(multitest.shortName));
generated = await generated.create(recursive: true);
- for (String name in testsAsLines.keys) {
- List<String> lines = testsAsLines[name];
+ for (MapEntry<String, List<String>> entry in testsAsLines.entries) {
+ String name = entry.key;
+ List<String> lines = entry.value;
Uri uri = generated.uri.resolve("${name}_generated.dart");
FileBasedTestDescription subtest =
new FileBasedTestDescription(root, new File.fromUri(uri));
diff --git a/pkg/testing/lib/src/run.dart b/pkg/testing/lib/src/run.dart
index 7ce9bd0..4567236 100644
--- a/pkg/testing/lib/src/run.dart
+++ b/pkg/testing/lib/src/run.dart
@@ -34,10 +34,10 @@
import 'run_tests.dart' show CommandLine;
-Future<TestRoot> computeTestRoot(String configurationPath, Uri base) {
+Future<TestRoot> computeTestRoot(String? configurationPath, Uri? base) {
Uri configuration = configurationPath == null
? Uri.base.resolve("testing.json")
- : base.resolve(configurationPath);
+ : base!.resolve(configurationPath);
return TestRoot.fromUri(configuration);
}
@@ -50,8 +50,8 @@
/// `testing.json` isn't located in the current working directory and is a path
/// relative to [me] which defaults to `Platform.script`.
Future<Null> runMe(List<String> arguments, CreateContext f,
- {String configurationPath,
- Uri me,
+ {String? configurationPath,
+ Uri? me,
int shards = 1,
int shard = 0,
Logger logger: const StdoutLogger()}) {
@@ -98,7 +98,7 @@
/// `testing.json` isn't located in the current working directory and is a path
/// relative to `Uri.base`.
Future<Null> run(List<String> arguments, List<String> suiteNames,
- [String configurationPath]) {
+ [String? configurationPath]) {
return withErrorHandling(() async {
TestRoot root = await computeTestRoot(configurationPath, Uri.base);
List<Suite> suites = root.suites
@@ -106,7 +106,7 @@
.toList();
SuiteRunner runner = new SuiteRunner(suites, <String, String>{},
const <String>[], new Set<String>(), new Set<String>());
- String program = await runner.generateDartProgram();
+ String? program = await runner.generateDartProgram();
await runner.analyze(root.packages);
if (program != null) {
await runProgram(program, root.packages);
@@ -125,7 +125,7 @@
errorsAreFatal: false,
checked: true,
packageConfig: packages);
- List error;
+ List? error;
var subscription = isolate.errors.listen((data) {
error = data;
exitPort.close();
@@ -137,7 +137,7 @@
subscription.cancel();
return error == null
? null
- : new Future<Null>.error(error[0], new StackTrace.fromString(error[1]));
+ : new Future<Null>.error(error![0], new StackTrace.fromString(error![1]));
}
class SuiteRunner {
@@ -162,7 +162,7 @@
(selectedSuites.isEmpty || selectedSuites.contains(suite.name));
}
- Future<String> generateDartProgram() async {
+ Future<String?> generateDartProgram() async {
testUris.clear();
StringBuffer imports = new StringBuffer();
StringBuffer dart = new StringBuffer();
@@ -238,10 +238,10 @@
}
Stream<FileBasedTestDescription> listDescriptions() async* {
- for (Dart suite in suites.where((Suite suite) => suite is Dart)) {
+ for (Dart suite in suites.whereType<Dart>()) {
await for (FileBasedTestDescription description
in listTests(<Uri>[suite.uri], pattern: "")) {
- testUris.add(await Isolate.resolvePackageUri(description.uri));
+ testUris.add((await Isolate.resolvePackageUri(description.uri))!);
if (shouldRunSuite(suite)) {
String path = description.file.uri.path;
if (suite.exclude.any((RegExp r) => path.contains(r))) continue;
@@ -254,19 +254,19 @@
}
Stream<Chain> listChainSuites() async* {
- for (Chain suite in suites.where((Suite suite) => suite is Chain)) {
- testUris.add(await Isolate.resolvePackageUri(suite.source));
+ for (Chain suite in suites.whereType<Chain>()) {
+ testUris.add((await Isolate.resolvePackageUri(suite.source))!);
if (shouldRunSuite(suite)) {
yield suite;
}
}
}
- Iterable<Suite> listTestDartSuites() {
- return suites.where((Suite suite) => suite is TestDart);
+ Iterable<TestDart> listTestDartSuites() {
+ return suites.whereType<TestDart>();
}
- Iterable<Suite> listAnalyzerSuites() {
- return suites.where((Suite suite) => suite is Analyze);
+ Iterable<Analyze> listAnalyzerSuites() {
+ return suites.whereType<Analyze>();
}
}
diff --git a/pkg/testing/lib/src/run_tests.dart b/pkg/testing/lib/src/run_tests.dart
index b4ccd3b..03d5d3d 100644
--- a/pkg/testing/lib/src/run_tests.dart
+++ b/pkg/testing/lib/src/run_tests.dart
@@ -64,7 +64,7 @@
Iterable<String> get selectors => arguments;
- Future<Uri> get configuration async {
+ Future<Uri?> get configuration async {
const String configPrefix = "--config=";
List<String> configurationPaths = options
.where((String option) => option.startsWith(configPrefix))
@@ -111,7 +111,7 @@
}
const StdoutLogger()
.logMessage("Reading configuration file '$configurationPath'.");
- Uri configuration =
+ Uri? configuration =
await Isolate.resolvePackageUri(Uri.base.resolve(configurationPath));
if (configuration == null ||
!await new File.fromUri(configuration).exists()) {
@@ -147,7 +147,7 @@
enableVerboseOutput();
}
Map<String, String> environment = cl.environment;
- Uri configuration = await cl.configuration;
+ Uri? configuration = await cl.configuration;
if (configuration == null) return;
if (!isVerbose) {
print("Use --verbose to display more details.");
@@ -155,7 +155,7 @@
TestRoot root = await TestRoot.fromUri(configuration);
SuiteRunner runner = new SuiteRunner(
root.suites, environment, cl.selectors, cl.selectedSuites, cl.skip);
- String program = await runner.generateDartProgram();
+ String? program = await runner.generateDartProgram();
bool hasAnalyzerSuites = await runner.analyze(root.packages);
Stopwatch sw = new Stopwatch()..start();
if (program == null) {
@@ -178,7 +178,7 @@
try {
await runGuarded(() {
print("Running test $name");
- return tests[name]();
+ return tests[name]!();
}, printLineOnStdout: sb.writeln);
const StdoutLogger().logMessage(sb);
} catch (e) {
diff --git a/pkg/testing/lib/src/stdio_process.dart b/pkg/testing/lib/src/stdio_process.dart
index 16bbfdf..587a07f 100644
--- a/pkg/testing/lib/src/stdio_process.dart
+++ b/pkg/testing/lib/src/stdio_process.dart
@@ -41,13 +41,13 @@
}
static Future<StdioProcess> run(String executable, List<String> arguments,
- {String input,
- Duration timeout: const Duration(seconds: 60),
+ {String? input,
+ Duration? timeout: const Duration(seconds: 60),
bool suppressOutput: true,
bool runInShell: false}) async {
Process process =
await Process.start(executable, arguments, runInShell: runInShell);
- Timer timer;
+ Timer? timer;
StringBuffer sb = new StringBuffer();
if (timeout != null) {
timer = new Timer(timeout, () {
@@ -75,8 +75,8 @@
stdoutStream = stdoutStream.transform(transformToStdio(io.stdout));
stderrStream = stderrStream.transform(transformToStdio(io.stderr));
}
- Future<List<String>> stdoutFuture = stdoutStream.toList();
- Future<List<String>> stderrFuture = stderrStream.toList();
+ Future<List<String>> stdoutFuture = stdoutStream.toList() as Future<List<String>>;
+ Future<List<String>> stderrFuture = stderrStream.toList() as Future<List<String>>;
int exitCode = await process.exitCode;
timer?.cancel();
sb.writeAll(await stdoutFuture);
diff --git a/pkg/testing/lib/src/suite.dart b/pkg/testing/lib/src/suite.dart
index 54aa7c8..b159797 100644
--- a/pkg/testing/lib/src/suite.dart
+++ b/pkg/testing/lib/src/suite.dart
@@ -14,7 +14,7 @@
final String kind;
- final Uri statusFile;
+ final Uri? statusFile;
Suite(this.name, this.kind, this.statusFile);
diff --git a/pkg/testing/lib/src/test_dart/path.dart b/pkg/testing/lib/src/test_dart/path.dart
index 3c5fbea..f0b5b51 100644
--- a/pkg/testing/lib/src/test_dart/path.dart
+++ b/pkg/testing/lib/src/test_dart/path.dart
@@ -192,7 +192,7 @@
Path makeCanonical() {
bool isAbs = isAbsolute;
List segs = segments();
- String drive;
+ String? drive;
if (isAbs && !segs.isEmpty && segs[0].length == 2 && segs[0][1] == ':') {
drive = segs[0];
segs.removeRange(0, 1);
@@ -267,7 +267,7 @@
}
List<String> segments() {
- List result = _path.split('/');
+ List<String> result = _path.split('/');
if (isAbsolute) result.removeRange(0, 1);
if (hasTrailingSeparator) result.removeLast();
return result;
diff --git a/pkg/testing/lib/src/test_dart/status_expression.dart b/pkg/testing/lib/src/test_dart/status_expression.dart
index 200d241..395483a 100644
--- a/pkg/testing/lib/src/test_dart/status_expression.dart
+++ b/pkg/testing/lib/src/test_dart/status_expression.dart
@@ -64,7 +64,9 @@
if (!testRegexp.hasMatch(expression)) {
throw new FormatException("Syntax error in '$expression'");
}
- for (Match match in regexp.allMatches(expression)) tokens.add(match[0]);
+ for (Match match in regexp.allMatches(expression)) {
+ tokens.add(match[0]!);
+ }
return tokens;
}
}
@@ -179,8 +181,8 @@
// An iterator that allows peeking at the current token.
class Scanner {
List<String> tokens;
- Iterator tokenIterator;
- String current;
+ late Iterator tokenIterator;
+ String? current;
Scanner(this.tokens) {
tokenIterator = tokens.iterator;
@@ -241,11 +243,11 @@
scanner.advance();
return value;
}
- if (!new RegExp(r"^\w+$").hasMatch(scanner.current)) {
+ if (!new RegExp(r"^\w+$").hasMatch(scanner.current!)) {
throw new FormatException(
"Expected identifier in expression, got ${scanner.current}");
}
- SetExpression value = new SetConstant(scanner.current);
+ SetExpression value = new SetConstant(scanner.current!);
scanner.advance();
return value;
}
@@ -290,21 +292,21 @@
"Expected \$ in expression, got ${scanner.current}");
}
scanner.advance();
- if (!new RegExp(r"^\w+$").hasMatch(scanner.current)) {
+ if (!new RegExp(r"^\w+$").hasMatch(scanner.current!)) {
throw new FormatException(
"Expected identifier in expression, got ${scanner.current}");
}
- TermVariable left = new TermVariable(scanner.current);
+ TermVariable left = new TermVariable(scanner.current!);
scanner.advance();
if (scanner.current == Token.EQUALS ||
scanner.current == Token.NOT_EQUALS) {
bool negate = scanner.current == Token.NOT_EQUALS;
scanner.advance();
- if (!new RegExp(r"^\w+$").hasMatch(scanner.current)) {
+ if (!new RegExp(r"^\w+$").hasMatch(scanner.current!)) {
throw new FormatException(
"Expected value in expression, got ${scanner.current}");
}
- TermConstant right = new TermConstant(scanner.current);
+ TermConstant right = new TermConstant(scanner.current!);
scanner.advance();
return new Comparison(left, right, negate);
} else {
diff --git a/pkg/testing/lib/src/test_dart/status_file_parser.dart b/pkg/testing/lib/src/test_dart/status_file_parser.dart
index 1ce711f..a3d2f58 100644
--- a/pkg/testing/lib/src/test_dart/status_file_parser.dart
+++ b/pkg/testing/lib/src/test_dart/status_file_parser.dart
@@ -29,7 +29,7 @@
class Section {
final StatusFile statusFile;
- final BooleanExpression condition;
+ final BooleanExpression? condition;
final List<TestRule> testRules;
final int lineNumber;
@@ -40,7 +40,7 @@
: testRules = <TestRule>[];
bool isEnabled(Map<String, String> environment) =>
- condition == null || condition.evaluate(environment);
+ condition == null || condition!.evaluate(environment);
String toString() {
return "Section: $condition";
@@ -93,17 +93,17 @@
lines.listen((String line) {
lineNumber++;
- Match match = SplitComment.firstMatch(line);
- line = (match == null) ? "" : match[1];
+ Match? match = SplitComment.firstMatch(line);
+ line = (match == null) ? "" : match[1]!;
line = line.trim();
if (line.isEmpty) return;
// Extract the comment to get the issue number if needed.
- String comment = (match == null || match[2] == null) ? "" : match[2];
+ String comment = (match == null || match[2] == null) ? "" : match[2]!;
match = HeaderPattern.firstMatch(line);
if (match != null) {
- String condition_string = match[1].trim();
+ String condition_string = match[1]!.trim();
List<String> tokens = new Tokenizer(condition_string).tokenize();
ExpressionParser parser = new ExpressionParser(new Scanner(tokens));
currentSection =
@@ -114,21 +114,21 @@
match = RulePattern.firstMatch(line);
if (match != null) {
- String name = match[1].trim();
+ String name = match[1]!.trim();
// TODO(whesse): Handle test names ending in a wildcard (*).
- String expression_string = match[2].trim();
+ String expression_string = match[2]!.trim();
List<String> tokens = new Tokenizer(expression_string).tokenize();
SetExpression expression =
new ExpressionParser(new Scanner(tokens)).parseSetExpression();
// Look for issue number in comment.
- String issueString = null;
+ String? issueString = null;
match = IssueNumberPattern.firstMatch(comment);
if (match != null) {
issueString = match[1];
if (issueString == null) issueString = match[2];
}
- int issue = issueString != null ? int.parse(issueString) : null;
+ int? issue = issueString != null ? int.parse(issueString) : null;
currentSection.testRules
.add(new TestRule(name, expression, issue, lineNumber));
return;
@@ -141,7 +141,7 @@
class TestRule {
String name;
SetExpression expression;
- int issue;
+ int? issue;
int lineNumber;
TestRule(this.name, this.expression, this.issue, this.lineNumber);
@@ -161,8 +161,8 @@
Map<String, Set<Expectation>> _map;
bool _preprocessed = false;
- Map<String, RegExp> _regExpCache;
- Map<String, List<RegExp>> _keyToRegExps;
+ Map<String, RegExp>? _regExpCache;
+ Map<String, List<RegExp>>? _keyToRegExps;
/**
* Create a TestExpectations object. See the [expectations] method
@@ -203,7 +203,7 @@
_preprocessForMatching();
_map.forEach((key, expectation) {
- List regExps = _keyToRegExps[key];
+ List<RegExp> regExps = _keyToRegExps![key]!;
if (regExps.length > splitFilename.length) return;
for (var i = 0; i < regExps.length; i++) {
if (!regExps[i].hasMatch(splitFilename[i])) return;
@@ -231,20 +231,19 @@
_regExpCache = {};
_map.forEach((key, expectations) {
- if (_keyToRegExps[key] != null) return;
+ if (_keyToRegExps![key] != null) return;
var splitKey = key.split('/');
- var regExps = new List<RegExp>.filled(splitKey.length, null);
- for (var i = 0; i < splitKey.length; i++) {
+ var regExps = new List<RegExp>.generate(splitKey.length, (int i) {
var component = splitKey[i];
- var regExp = _regExpCache[component];
+ var regExp = _regExpCache![component];
if (regExp == null) {
var pattern = "^${splitKey[i]}\$".replaceAll('*', '.*');
regExp = new RegExp(pattern);
- _regExpCache[component] = regExp;
+ _regExpCache![component] = regExp;
}
- regExps[i] = regExp;
- }
- _keyToRegExps[key] = regExps;
+ return regExp;
+ }, growable: false);
+ _keyToRegExps![key] = regExps;
});
_regExpCache = null;
diff --git a/pkg/testing/lib/src/test_description.dart b/pkg/testing/lib/src/test_description.dart
index 7480ee0..1fe0ac1 100644
--- a/pkg/testing/lib/src/test_description.dart
+++ b/pkg/testing/lib/src/test_description.dart
@@ -17,11 +17,11 @@
class FileBasedTestDescription extends TestDescription {
final Uri root;
final File file;
- final Uri output;
+ final Uri? output;
/// If non-null, this is a generated multitest, and the set contains the
/// expected outcomes.
- Set<String> multitestExpectations;
+ Set<String>? multitestExpectations;
FileBasedTestDescription(this.root, this.file, {this.output});
@@ -52,8 +52,8 @@
sink.writeln('.main,');
}
- static FileBasedTestDescription from(Uri root, FileSystemEntity entity,
- {Pattern pattern}) {
+ static FileBasedTestDescription? from(Uri root, FileSystemEntity entity,
+ {Pattern? pattern}) {
if (entity is! File) return null;
pattern ??= "_test.dart";
String path = entity.uri.path;
diff --git a/pkg/testing/lib/src/test_root.dart b/pkg/testing/lib/src/test_root.dart
index 9e3b65e..554abee 100644
--- a/pkg/testing/lib/src/test_root.dart
+++ b/pkg/testing/lib/src/test_root.dart
@@ -49,7 +49,7 @@
TestRoot(this.packages, this.suites);
- Analyze get analyze => suites.last;
+ Analyze get analyze => suites.last as Analyze;
List<Uri> get urisToAnalyze => analyze.uris;
diff --git a/pkg/testing/lib/src/zone_helper.dart b/pkg/testing/lib/src/zone_helper.dart
index d8d7d39..a378d7a 100644
--- a/pkg/testing/lib/src/zone_helper.dart
+++ b/pkg/testing/lib/src/zone_helper.dart
@@ -14,8 +14,8 @@
import 'log.dart' show StdoutLogger;
Future runGuarded(Future f(),
- {void printLineOnStdout(line),
- void handleLateError(error, StackTrace stackTrace)}) {
+ {void Function(String)? printLineOnStdout,
+ void Function(dynamic, StackTrace)? handleLateError}) {
var printWrapper;
if (printLineOnStdout != null) {
printWrapper = (_1, _2, _3, String line) {
@@ -39,6 +39,7 @@
// Ignored.
}
stderr
+ // ignore: unnecessary_null_comparison
.write("$errorString\n" + (stackTrace == null ? "" : "$stackTrace"));
stderr.flush();
exit(255);
@@ -81,7 +82,7 @@
/// Ping [isolate] to ensure control messages have been delivered. Control
/// messages are things like [Isolate.addErrorListener] and
/// [Isolate.addOnExitListener].
-Future acknowledgeControlMessages(Isolate isolate, {Capability resume}) {
+Future acknowledgeControlMessages(Isolate isolate, {Capability? resume}) {
ReceivePort ping = new ReceivePort();
Isolate.current.ping(ping.sendPort);
if (resume == null) {
diff --git a/pkg/testing/pubspec.yaml b/pkg/testing/pubspec.yaml
index f012946..d85f43f 100644
--- a/pkg/testing/pubspec.yaml
+++ b/pkg/testing/pubspec.yaml
@@ -4,4 +4,4 @@
# This package is not intended for consumption on pub.dev. DO NOT publish.
publish_to: none
environment:
- sdk: '>=2.0.0 <3.0.0'
+ sdk: '>=2.12.0 <3.0.0'
diff --git a/pkg/vm/bin/kernel_service.dart b/pkg/vm/bin/kernel_service.dart
index 4c46e9e..e3a221e 100644
--- a/pkg/vm/bin/kernel_service.dart
+++ b/pkg/vm/bin/kernel_service.dart
@@ -18,7 +18,6 @@
/// dart pkg/vm/bin/kernel_service.dart --train <source-file>
///
///
-library runtime.tools.kernel_service;
import 'dart:async' show Future, ZoneSpecification, runZoned;
import 'dart:collection' show UnmodifiableMapBase;
@@ -88,11 +87,11 @@
CompilerOptions setupCompilerOptions(
FileSystem fileSystem,
- Uri platformKernelPath,
+ Uri? platformKernelPath,
bool enableAsserts,
int nullSafety,
- List<String> experimentalFlags,
- Uri packagesUri,
+ List<String>? experimentalFlags,
+ Uri? packagesUri,
List<String> errorsPlain,
List<String> errorsColorized,
String invocationModes,
@@ -159,11 +158,11 @@
abstract class Compiler {
final int isolateGroupId;
final FileSystem fileSystem;
- final Uri platformKernelPath;
+ final Uri? platformKernelPath;
final bool enableAsserts;
final int nullSafety;
- final List<String> experimentalFlags;
- final String packageConfig;
+ final List<String>? experimentalFlags;
+ final String? packageConfig;
final String invocationModes;
final String verbosityLevel;
@@ -175,7 +174,7 @@
final List<String> errorsPlain = <String>[];
final List<String> errorsColorized = <String>[];
- CompilerOptions options;
+ late final CompilerOptions options;
Compiler(this.isolateGroupId, this.fileSystem, this.platformKernelPath,
{this.enableAsserts: false,
@@ -186,11 +185,10 @@
this.packageConfig: null,
this.invocationModes: '',
this.verbosityLevel: Verbosity.defaultValue}) {
- Uri packagesUri = null;
+ Uri? packagesUri = null;
+ final packageConfig = this.packageConfig ?? Platform.packageConfig;
if (packageConfig != null) {
packagesUri = Uri.parse(packageConfig);
- } else if (Platform.packageConfig != null) {
- packagesUri = Uri.parse(Platform.packageConfig);
}
if (verbose) {
@@ -216,7 +214,7 @@
Future<CompilerResult> compile(Uri script) {
return runWithPrintToStderr(() async {
final CompilerResult compilerResult = await compileInternal(script);
- final Component component = compilerResult.component;
+ final Component? component = compilerResult.component;
if (errorsPlain.isEmpty) {
// Record dependencies only if compilation was error free.
@@ -231,20 +229,16 @@
}
class CompilerResult {
- final Component component;
+ final Component? component;
/// Set of libraries loaded from .dill, with or without the SDK depending on
/// the compilation settings.
final Set<Library> loadedLibraries;
- final ClassHierarchy classHierarchy;
- final CoreTypes coreTypes;
+ final ClassHierarchy? classHierarchy;
+ final CoreTypes? coreTypes;
- CompilerResult(
- this.component, this.loadedLibraries, this.classHierarchy, this.coreTypes)
- : assert(component != null),
- assert(loadedLibraries != null),
- assert(classHierarchy != null),
- assert(coreTypes != null);
+ CompilerResult(this.component, this.loadedLibraries, this.classHierarchy,
+ this.coreTypes);
}
// Environment map which looks up environment defines in the VM environment
@@ -255,17 +249,17 @@
// the full (isolate specific) environment as a finite, static map.
class EnvironmentMap extends UnmodifiableMapBase<String, String> {
@override
- bool containsKey(Object key) {
- return new bool.hasEnvironment(key);
+ bool containsKey(Object? key) {
+ return key is String && new bool.hasEnvironment(key);
}
@override
- String operator [](Object key) {
+ String? operator [](Object? key) {
// The fromEnvironment constructor is specified to throw when called using
// new. However, the VM implementation actually looks up the given name in
// the environment.
if (containsKey(key)) {
- return new String.fromEnvironment(key);
+ return new String.fromEnvironment(key as String);
}
return null;
}
@@ -292,14 +286,14 @@
}
class IncrementalCompilerWrapper extends Compiler {
- IncrementalCompiler generator;
+ IncrementalCompiler? generator;
IncrementalCompilerWrapper(
- int isolateGroupId, FileSystem fileSystem, Uri platformKernelPath,
+ int isolateGroupId, FileSystem fileSystem, Uri? platformKernelPath,
{bool enableAsserts: false,
int nullSafety: kNullSafetyOptionUnspecified,
- List<String> experimentalFlags: null,
- String packageConfig: null,
+ List<String>? experimentalFlags,
+ String? packageConfig,
String invocationModes: '',
String verbosityLevel: Verbosity.defaultValue})
: super(isolateGroupId, fileSystem, platformKernelPath,
@@ -316,10 +310,10 @@
Component component,
int isolateGroupId,
FileSystem fileSystem,
- Uri platformKernelPath,
+ Uri? platformKernelPath,
{bool enableAsserts: false,
- List<String> experimentalFlags: null,
- String packageConfig: null,
+ List<String>? experimentalFlags,
+ String? packageConfig,
String invocationModes: ''}) {
IncrementalCompilerWrapper result = IncrementalCompilerWrapper(
isolateGroupId, fileSystem, platformKernelPath,
@@ -330,15 +324,13 @@
result.generator = new IncrementalCompiler.forExpressionCompilationOnly(
component,
result.options,
- component.mainMethod?.enclosingLibrary?.fileUri);
+ component.mainMethod!.enclosingLibrary.fileUri);
return result;
}
@override
Future<CompilerResult> compileInternal(Uri script) async {
- if (generator == null) {
- generator = new IncrementalCompiler(options, script);
- }
+ final generator = this.generator ??= IncrementalCompiler(options, script);
errorsPlain.clear();
errorsColorized.clear();
final component = await generator.compile(entryPoint: script);
@@ -346,8 +338,8 @@
generator.getClassHierarchy(), generator.getCoreTypes());
}
- void accept() => generator.accept();
- void invalidate(Uri uri) => generator.invalidate(uri);
+ void accept() => generator!.accept();
+ void invalidate(Uri uri) => generator!.invalidate(uri);
Future<IncrementalCompilerWrapper> clone(int isolateGroupId) async {
IncrementalCompilerWrapper clone = IncrementalCompilerWrapper(
@@ -357,6 +349,7 @@
experimentalFlags: experimentalFlags,
packageConfig: packageConfig,
invocationModes: invocationModes);
+ final generator = this.generator!;
// TODO(VM TEAM): This does not seem safe. What if cloning while having
// pending deltas for instance?
generator.resetDeltaState();
@@ -367,9 +360,10 @@
MemoryFileSystem memoryFileSystem = (fileSystem as HybridFileSystem).memory;
String filename = 'full-component-$isolateGroupId.dill';
- Sink sink = FileSink(memoryFileSystem.entityForUri(Uri.file(filename)));
+ Sink<List<int>> sink =
+ FileSink(memoryFileSystem.entityForUri(Uri.file(filename)));
new BinaryPrinter(sink).writeComponentFile(fullComponent);
- await sink.close();
+ sink.close();
clone.generator = new IncrementalCompiler(options, generator.entryPoint,
initializeFromDillUri: Uri.file(filename));
@@ -385,8 +379,8 @@
{this.requireMain: false,
bool enableAsserts: false,
int nullSafety: kNullSafetyOptionUnspecified,
- List<String> experimentalFlags: null,
- String packageConfig: null,
+ List<String>? experimentalFlags,
+ String? packageConfig,
String invocationModes: '',
String verbosityLevel: Verbosity.defaultValue})
: super(isolateGroupId, fileSystem, platformKernelPath,
@@ -399,12 +393,15 @@
@override
Future<CompilerResult> compileInternal(Uri script) async {
- fe.CompilerResult compilerResult = requireMain
+ final fe.CompilerResult? compilerResult = requireMain
? await kernelForProgram(script, options)
: await kernelForModule([script], options);
+ if (compilerResult == null) {
+ return CompilerResult(null, const {}, null, null);
+ }
Set<Library> loadedLibraries = createLoadedLibrariesSet(
- compilerResult?.loadedComponents, compilerResult?.sdkComponent,
+ compilerResult.loadedComponents, compilerResult.sdkComponent,
includePlatform: !options.omitPlatform);
return new CompilerResult(compilerResult.component, loadedLibraries,
@@ -416,21 +413,21 @@
final Map<int, List<Uri>> isolateDependencies = {};
final Map<int, _ExpressionCompilationFromDillSettings> isolateLoadNotifies = {};
-IncrementalCompilerWrapper lookupIncrementalCompiler(int isolateGroupId) {
+IncrementalCompilerWrapper? lookupIncrementalCompiler(int isolateGroupId) {
return isolateCompilers[isolateGroupId];
}
Future<Compiler> lookupOrBuildNewIncrementalCompiler(int isolateGroupId,
- List sourceFiles, Uri platformKernelPath, List<int> platformKernel,
+ List sourceFiles, Uri platformKernelPath, List<int>? platformKernel,
{bool enableAsserts: false,
int nullSafety: kNullSafetyOptionUnspecified,
- List<String> experimentalFlags: null,
- String packageConfig: null,
- String multirootFilepaths,
- String multirootScheme,
+ List<String>? experimentalFlags,
+ String? packageConfig,
+ String? multirootFilepaths,
+ String? multirootScheme,
String invocationModes: '',
String verbosityLevel: Verbosity.defaultValue}) async {
- IncrementalCompilerWrapper compiler =
+ IncrementalCompilerWrapper? compiler =
lookupIncrementalCompiler(isolateGroupId);
if (compiler != null) {
updateSources(compiler, sourceFiles);
@@ -439,9 +436,7 @@
// This is how identify scenario where child isolate hot reload requests
// requires setting up actual compiler first: non-empty sourceFiles list has
// no actual content specified for the source file.
- if (sourceFiles != null &&
- sourceFiles.length > 0 &&
- sourceFiles[1] == null) {
+ if (sourceFiles.isNotEmpty && sourceFiles[1] == null) {
// Just use first compiler that should represent main isolate as a source for cloning.
var source = isolateCompilers.entries.first;
compiler = await source.value.clone(isolateGroupId);
@@ -473,7 +468,7 @@
final FileSystem fs = compiler.fileSystem;
for (int i = 0; i < sourceFiles.length ~/ 2; i++) {
Uri uri = Uri.parse(sourceFiles[i * 2]);
- List<int> source = sourceFiles[i * 2 + 1];
+ List<int>? source = sourceFiles[i * 2 + 1];
// The source is only provided by unit tests and is normally empty.
// Don't add an entry for the uri so the compiler will fallback to the
// real file system for the updated source.
@@ -505,23 +500,24 @@
final List<String> definitions = request[5].cast<String>();
final List<String> typeDefinitions = request[6].cast<String>();
final String libraryUri = request[7];
- final String klass = request[8]; // might be null
+ final String? klass = request[8];
final bool isStatic = request[9];
- final List dillData = request[10];
+ final List<List<int>> dillData = request[10].cast<List<int>>();
final int blobLoadCount = request[11];
final bool enableAsserts = request[12];
- final List<String> experimentalFlags =
+ final List<String>? experimentalFlags =
request[13] != null ? request[13].cast<String>() : null;
- IncrementalCompilerWrapper compiler = isolateCompilers[isolateGroupId];
+ IncrementalCompilerWrapper? compiler = isolateCompilers[isolateGroupId];
- _ExpressionCompilationFromDillSettings isolateLoadDillData =
+ _ExpressionCompilationFromDillSettings? isolateLoadDillData =
isolateLoadNotifies[isolateGroupId];
if (isolateLoadDillData != null) {
// Check if we can reuse the compiler.
if (isolateLoadDillData.blobLoadCount != blobLoadCount ||
isolateLoadDillData.prevDillCount != dillData.length) {
- compiler = isolateCompilers[isolateGroupId] = null;
+ isolateCompilers.remove(isolateGroupId);
+ compiler = null;
}
}
@@ -558,7 +554,7 @@
}
}
if (!foundDartCore) {
- List<int> platformKernel = null;
+ List<int> platformKernel;
if (dart_platform_kernel is List<int>) {
platformKernel = dart_platform_kernel;
} else {
@@ -596,7 +592,7 @@
packageConfig: dotPackagesFile);
isolateCompilers[isolateGroupId] = compiler;
await compiler.compile(
- component.mainMethod?.enclosingLibrary?.importUri ??
+ component.mainMethod?.enclosingLibrary.importUri ??
component.libraries.last.importUri);
} catch (e) {
port.send(new CompilationResult.errors([
@@ -621,7 +617,7 @@
CompilationResult result;
try {
- Procedure procedure = await compiler.generator.compileExpression(
+ Procedure? procedure = await compiler.generator!.compileExpression(
expression, definitions, typeDefinitions, libraryUri, klass, isStatic);
if (procedure == null) {
@@ -649,7 +645,7 @@
}
void _recordDependencies(
- int isolateGroupId, Component component, Uri packageConfig) {
+ int isolateGroupId, Component? component, Uri? packageConfig) {
final dependencies = isolateDependencies[isolateGroupId] ??= <Uri>[];
if (component != null) {
@@ -678,8 +674,8 @@
return uri.toFilePath().replaceAll("\\", "\\\\").replaceAll(" ", "\\ ");
}
-List<int> _serializeDependencies(List<Uri> uris) {
- return utf8.encode(uris.map(_escapeDependency).join(" "));
+Uint8List _serializeDependencies(List<Uri> uris) {
+ return utf8.encode(uris.map(_escapeDependency).join(" ")) as Uint8List;
}
Future _processListDependenciesRequest(
@@ -750,23 +746,23 @@
return;
}
- final String inputFileUri = request[2];
- final Uri script =
+ final String? inputFileUri = request[2];
+ final Uri? script =
inputFileUri != null ? Uri.base.resolve(inputFileUri) : null;
final bool incremental = request[4];
final bool snapshot = request[5];
final int nullSafety = request[6];
final List sourceFiles = request[8];
final bool enableAsserts = request[9];
- final List<String> experimentalFlags =
+ final List<String>? experimentalFlags =
request[10] != null ? request[10].cast<String>() : null;
- final String packageConfig = request[11];
- final String multirootFilepaths = request[12];
- final String multirootScheme = request[13];
- final String workingDirectory = request[14];
+ final String? packageConfig = request[11];
+ final String? multirootFilepaths = request[12];
+ final String? multirootScheme = request[13];
+ final String? workingDirectory = request[14];
final String verbosityLevel = request[15];
- Uri platformKernelPath = null;
- List<int> platformKernel = null;
+ Uri platformKernelPath;
+ List<int>? platformKernel = null;
if (request[3] is String) {
platformKernelPath = Uri.base.resolveUri(new Uri.file(request[3]));
} else if (request[3] is List<int>) {
@@ -779,7 +775,7 @@
final String invocationModes = snapshot ? 'compile' : '';
- Compiler compiler;
+ Compiler? compiler;
// Update the in-memory file system with the provided sources. Currently, only
// unit tests compile sources that are not on the file system, so this can only
@@ -794,7 +790,7 @@
.toResponse());
return;
}
- updateSources(compiler, sourceFiles);
+ updateSources(compiler as IncrementalCompilerWrapper, sourceFiles);
port.send(new CompilationResult.ok(null).toResponse());
return;
} else if (tag == kAcceptTag) {
@@ -811,16 +807,15 @@
} else if (tag == kDetectNullabilityTag) {
FileSystem fileSystem = _buildFileSystem(
sourceFiles, platformKernel, multirootFilepaths, multirootScheme);
- Uri packagesUri = null;
- if (packageConfig != null) {
- packagesUri = Uri.parse(packageConfig);
- } else if (Platform.packageConfig != null) {
- packagesUri = Uri.parse(Platform.packageConfig);
+ Uri? packagesUri = null;
+ final packageConfigWithDefault = packageConfig ?? Platform.packageConfig;
+ if (packageConfigWithDefault != null) {
+ packagesUri = Uri.parse(packageConfigWithDefault);
}
if (packagesUri != null && packagesUri.scheme == '') {
// Script does not have a scheme, assume that it is a path,
// resolve it against the working directory.
- packagesUri = Uri.directory(workingDirectory).resolveUri(packagesUri);
+ packagesUri = Uri.directory(workingDirectory!).resolveUri(packagesUri);
}
final List<String> errorsPlain = <String>[];
final List<String> errorsColorized = <String>[];
@@ -837,8 +832,7 @@
verbosityLevel);
// script should only be null for kUpdateSourcesTag.
- assert(script != null);
- await autoDetectNullSafetyMode(script, options);
+ await autoDetectNullSafetyMode(script!, options);
bool value = options.nnbdMode == NnbdMode.Strong;
port.send(new CompilationResult.nullSafety(value).toResponse());
return;
@@ -882,7 +876,7 @@
print("DFE: scriptUri: ${script}");
}
- CompilerResult compilerResult = await compiler.compile(script);
+ CompilerResult compilerResult = await compiler.compile(script!);
Set<Library> loadedLibraries = compilerResult.loadedLibraries;
assert(compiler.errorsPlain.length == compiler.errorsColorized.length);
@@ -894,10 +888,11 @@
if (compiler.errorsColorized.isNotEmpty) {
final List<String> errors =
(enableColors) ? compiler.errorsColorized : compiler.errorsPlain;
- if (compilerResult.component != null) {
+ final component = compilerResult.component;
+ if (component != null) {
result = new CompilationResult.errors(
errors,
- serializeComponent(compilerResult.component,
+ serializeComponent(component,
filter: (lib) => !loadedLibraries.contains(lib)));
} else {
result = new CompilationResult.errors(errors, null);
@@ -908,7 +903,7 @@
// [kernelForProgram] is marked `external`, so we can use that bit to
// decide what to exclude.
result = new CompilationResult.ok(serializeComponent(
- compilerResult.component,
+ compilerResult.component!,
filter: (lib) => !loadedLibraries.contains(lib)));
}
} catch (error, stack) {
@@ -920,7 +915,7 @@
if (tag == kTrainTag) {
// In training mode make sure to read the sdk a few more times...
ProcessedOptions p = new ProcessedOptions(options: compiler.options);
- var bytes = await p.loadSdkSummaryBytes();
+ final bytes = (await p.loadSdkSummaryBytes())!;
for (int i = 0; i < 5; i++) {
p.loadComponent(bytes, null);
}
@@ -949,19 +944,17 @@
///
/// The result can be used instead of StandardFileSystem.instance by the
/// frontend.
-FileSystem _buildFileSystem(List sourceFiles, List<int> platformKernel,
- String multirootFilepaths, String multirootScheme) {
+FileSystem _buildFileSystem(List sourceFiles, List<int>? platformKernel,
+ String? multirootFilepaths, String? multirootScheme) {
FileSystem fileSystem = new HttpAwareFileSystem(StandardFileSystem.instance);
if (!sourceFiles.isEmpty || platformKernel != null) {
MemoryFileSystem memoryFileSystem =
new MemoryFileSystem(Uri.parse('file:///'));
- if (sourceFiles != null) {
- for (int i = 0; i < sourceFiles.length ~/ 2; i++) {
- memoryFileSystem
- .entityForUri(Uri.parse(sourceFiles[i * 2]))
- .writeAsBytesSync(sourceFiles[i * 2 + 1]);
- }
+ for (int i = 0; i < sourceFiles.length ~/ 2; i++) {
+ memoryFileSystem
+ .entityForUri(Uri.parse(sourceFiles[i * 2]))
+ .writeAsBytesSync(sourceFiles[i * 2 + 1]);
}
if (platformKernel != null) {
memoryFileSystem
@@ -982,7 +975,7 @@
return fileSystem;
}
-train(String scriptUri, String platformKernelPath) async {
+train(String scriptUri, String? platformKernelPath) async {
// Train on program asked to train on.
await trainInternal(scriptUri, platformKernelPath);
@@ -1005,7 +998,7 @@
}
}
-Future trainInternal(String scriptUri, String platformKernelPath) async {
+Future trainInternal(String scriptUri, String? platformKernelPath) async {
var tag = kTrainTag;
var responsePort = new RawReceivePort();
responsePort.handler = (response) {
@@ -1048,7 +1041,7 @@
// 2) Optional platform kernel path.
int argIndex = 1;
final String script = args[argIndex++];
- final String platform = (argIndex < args.length) ? args[argIndex] : null;
+ final String? platform = (argIndex < args.length) ? args[argIndex] : null;
train(script, platform);
} else {
// Entry point for the Kernel isolate.
@@ -1075,11 +1068,11 @@
abstract class CompilationResult {
CompilationResult._();
- factory CompilationResult.ok(Uint8List bytes) = _CompilationOk;
+ factory CompilationResult.ok(Uint8List? bytes) = _CompilationOk;
factory CompilationResult.nullSafety(bool val) = _CompilationNullSafety;
- factory CompilationResult.errors(List<String> errors, Uint8List bytes) =
+ factory CompilationResult.errors(List<String> errors, Uint8List? bytes) =
_CompilationError;
factory CompilationResult.crash(Object exception, StackTrace stack) =
@@ -1093,11 +1086,14 @@
}
class _CompilationOk extends CompilationResult {
- final Uint8List bytes;
+ final Uint8List? bytes;
_CompilationOk(this.bytes) : super._() {
- if (dumpKernel && bytes != null) {
- _debugDumpKernel(bytes);
+ if (dumpKernel) {
+ final bytes = this.bytes;
+ if (bytes != null) {
+ _debugDumpKernel(bytes);
+ }
}
}
@@ -1107,7 +1103,7 @@
@override
get payload => bytes;
- String toString() => "_CompilationOk(${bytes.length} bytes)";
+ String toString() => "_CompilationOk(${bytes?.length ?? 0} bytes)";
}
class _CompilationNullSafety extends CompilationResult {
@@ -1134,7 +1130,7 @@
}
class _CompilationError extends _CompilationFail {
- final Uint8List bytes;
+ final Uint8List? bytes;
final List<String> errors;
_CompilationError(this.errors, this.bytes);
diff --git a/pkg/vm/bin/protobuf_aware_treeshaker.dart b/pkg/vm/bin/protobuf_aware_treeshaker.dart
index 69aa466..3af79b6 100644
--- a/pkg/vm/bin/protobuf_aware_treeshaker.dart
+++ b/pkg/vm/bin/protobuf_aware_treeshaker.dart
@@ -34,7 +34,6 @@
import 'package:vm/kernel_front_end.dart'
show runGlobalTransformations, ErrorDetector;
import 'package:kernel/target/targets.dart' show TargetFlags, getTarget;
-import 'package:meta/meta.dart';
import 'package:vm/target/install.dart' show installAdditionalTargets;
import 'package:vm/transformations/type_flow/transformer.dart' as globalTypeFlow
show transformComponent;
@@ -69,7 +68,7 @@
help: 'Write to stdout about what classes and fields where remeoved')
..addFlag('help', help: 'Prints this help', negatable: false);
- ArgResults argResults;
+ ArgResults? argResults;
try {
argResults = argParser.parse(args);
} on FormatException catch (e) {
@@ -109,7 +108,7 @@
installAdditionalTargets();
- final target = getTarget(argResults['target'], TargetFlags());
+ final target = getTarget(argResults['target'], TargetFlags())!;
// The [component] is treeshaken and has TFA annotations. Write output.
if (argResults['aot']) {
@@ -156,7 +155,7 @@
}
Future writeComponent(Component component, String filename,
- {@required bool removeCoreLibs, @required bool removeSource}) async {
+ {required bool removeCoreLibs, required bool removeSource}) async {
if (removeSource) {
component.uriToSource.clear();
}
diff --git a/pkg/vm/lib/dominators.dart b/pkg/vm/lib/dominators.dart
index 19c5d84..81309d3 100644
--- a/pkg/vm/lib/dominators.dart
+++ b/pkg/vm/lib/dominators.dart
@@ -2,18 +2,16 @@
// 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.
-library vm.dominators;
-
class Vertex<T extends Vertex<T>> {
// Input: vertices directly reachable from this vertex.
final List<T> successors = <T>[];
// Output: the nearest vertex that all paths from the root must go through to
// reach this vertex.
- T dominator;
+ T? dominator;
bool isDominatedBy(T other) {
- var d = this;
+ Vertex<T>? d = this;
while (d != null) {
if (d == other) {
return true;
@@ -26,17 +24,17 @@
// Temporaries. See Lengauer and Tarjan.
final List<T> _predecessors = <T>[];
int _semi = 0;
- T _label;
- T _ancestor;
- T _parent;
- List<T> _bucket;
+ T? _label;
+ T? _ancestor;
+ T? _parent;
+ List<T>? _bucket;
}
// T. Lengauer and R. E. Tarjan. "A Fast Algorithm for Finding Dominators
// in a Flowgraph."
computeDominators<T extends Vertex<T>>(T root) {
// Lengauer and Tarjan Step 1.
- final vertex = <T>[];
+ final vertex = <T?>[];
vertex.add(null);
var n = 0;
@@ -60,33 +58,35 @@
dfs(root);
forestCompress(T v) {
- if (v._ancestor._ancestor != null) {
- forestCompress(v._ancestor);
- if (v._ancestor._label._semi < v._label._semi) {
- v._label = v._ancestor._label;
+ T ancestor = v._ancestor!;
+ if (ancestor._ancestor != null) {
+ forestCompress(ancestor);
+ ancestor = v._ancestor!;
+ if (ancestor._label!._semi < v._label!._semi) {
+ v._label = ancestor._label;
}
- v._ancestor = v._ancestor._ancestor;
+ v._ancestor = ancestor._ancestor;
}
}
- forestEval(T v) {
+ T forestEval(T v) {
if (v._ancestor == null) {
return v;
} else {
forestCompress(v);
- return v._label;
+ return v._label!;
}
}
- forestLink(T v, T w) {
+ forestLink(T? v, T w) {
w._ancestor = v;
}
for (var i = vertex.length - 1; i > 1; i--) {
- Vertex<T> w = vertex[i];
+ final T w = vertex[i]!;
// Lengauer and Tarjan Step 2.
- for (Vertex<T> v in w._predecessors) {
+ for (T v in w._predecessors) {
if (v._semi == 0) continue; // Unreachable
final u = forestEval(v);
@@ -95,7 +95,7 @@
}
}
- Vertex<T> z = vertex[w._semi];
+ Vertex<T> z = vertex[w._semi]!;
var b = z._bucket;
if (b == null) {
z._bucket = b = <T>[];
@@ -104,8 +104,7 @@
forestLink(w._parent, w);
// Lengauer and Tarjan Step 3.
- z = w._parent;
- assert(z != null);
+ z = w._parent!;
b = z._bucket;
z._bucket = null;
if (b != null) {
@@ -118,9 +117,9 @@
// Lengauer and Tarjan Step 4.
for (var i = 2; i < vertex.length; i++) {
- final w = vertex[i];
+ final T w = vertex[i]!;
if (w.dominator != vertex[w._semi]) {
- w.dominator = w.dominator.dominator;
+ w.dominator = w.dominator!.dominator;
}
}
}
diff --git a/pkg/vm/lib/http_filesystem.dart b/pkg/vm/lib/http_filesystem.dart
index cd8e42a..18ee3e1 100644
--- a/pkg/vm/lib/http_filesystem.dart
+++ b/pkg/vm/lib/http_filesystem.dart
@@ -1,3 +1,7 @@
+// 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.
+
import 'dart:async';
import 'dart:io' as io;
@@ -60,7 +64,7 @@
}
Future<T> connectAndRun<T>(Future<T> body(io.HttpClient httpClient)) async {
- io.HttpClient httpClient;
+ io.HttpClient? httpClient;
try {
httpClient = new io.HttpClient();
// Set timeout to be shorter than anticipated OS default
diff --git a/pkg/vm/lib/incremental_compiler.dart b/pkg/vm/lib/incremental_compiler.dart
index f2f483f..a8d3271 100644
--- a/pkg/vm/lib/incremental_compiler.dart
+++ b/pkg/vm/lib/incremental_compiler.dart
@@ -18,23 +18,23 @@
/// deltas and combines them together into resultant program until it is
/// accepted.
class IncrementalCompiler {
- IncrementalKernelGenerator _generator;
- IncrementalSerializer incrementalSerializer;
+ late IncrementalKernelGenerator _generator;
+ IncrementalSerializer? incrementalSerializer;
// Component that reflect the state that was most recently accepted by the
// client. Is [null], if no compilation results were accepted by the client.
- Component _lastKnownGood;
- List<Component> _pendingDeltas;
+ Component? _lastKnownGood;
+ late List<Component> _pendingDeltas;
CompilerOptions _compilerOptions;
bool initialized = false;
bool fullComponent = false;
- Uri initializeFromDillUri;
+ Uri? initializeFromDillUri;
Uri _entryPoint;
final bool forExpressionCompilationOnly;
Uri get entryPoint => _entryPoint;
IncrementalKernelGenerator get generator => _generator;
- Component get lastKnownGoodComponent => _lastKnownGood;
+ Component? get lastKnownGoodComponent => _lastKnownGood;
IncrementalCompiler(this._compilerOptions, this._entryPoint,
{this.initializeFromDillUri, bool incrementalSerialization: true})
@@ -59,12 +59,12 @@
///
/// If [entryPoint] is specified, that points to new entry point for the
/// compilation. Otherwise, previously set entryPoint is used.
- Future<Component> compile({Uri entryPoint}) async {
+ Future<Component> compile({Uri? entryPoint}) async {
final task = new TimelineTask();
try {
task.start("IncrementalCompiler.compile");
_entryPoint = entryPoint ?? _entryPoint;
- List<Uri> entryPoints;
+ List<Uri>? entryPoints;
if (entryPoint != null) entryPoints = [entryPoint];
Component component = await _generator.computeDelta(
entryPoints: entryPoints, fullComponent: fullComponent);
@@ -78,8 +78,9 @@
}
_combinePendingDeltas(bool includePlatform) {
- Procedure mainMethod;
- NonNullableByDefaultCompiledMode compilationMode;
+ Procedure? mainMethod;
+ NonNullableByDefaultCompiledMode compilationMode =
+ NonNullableByDefaultCompiledMode.Invalid;
Map<Uri, Library> combined = <Uri, Library>{};
Map<Uri, Source> uriToSource = new Map<Uri, Source>();
for (Component delta in _pendingDeltas) {
@@ -102,8 +103,8 @@
..setMainMethodAndMode(mainMethod?.reference, true, compilationMode);
}
- CoreTypes getCoreTypes() => _generator.getCoreTypes();
- ClassHierarchy getClassHierarchy() => _generator.getClassHierarchy();
+ CoreTypes? getCoreTypes() => _generator.getCoreTypes();
+ ClassHierarchy? getClassHierarchy() => _generator.getClassHierarchy();
/// This lets incremental compiler know that results of last [compile] call
/// were accepted, don't need to be included into subsequent [compile] calls
@@ -116,13 +117,14 @@
Map<Uri, Library> combined = <Uri, Library>{};
Map<Uri, Source> uriToSource = <Uri, Source>{};
- if (_lastKnownGood != null) {
+ Component? lastKnownGood = _lastKnownGood;
+ if (lastKnownGood != null) {
// TODO(aam): Figure out how to skip no-longer-used libraries from
// [_lastKnownGood] libraries.
- for (Library library in _lastKnownGood.libraries) {
+ for (Library library in lastKnownGood.libraries) {
combined[library.importUri] = library;
}
- uriToSource.addAll(_lastKnownGood.uriToSource);
+ uriToSource.addAll(lastKnownGood.uriToSource);
}
Component candidate = _combinePendingDeltas(true);
@@ -131,13 +133,13 @@
}
uriToSource.addAll(candidate.uriToSource);
- _lastKnownGood = new Component(
+ _lastKnownGood = lastKnownGood = new Component(
libraries: combined.values.toList(),
uriToSource: uriToSource,
)..setMainMethodAndMode(
candidate.mainMethod?.reference, true, candidate.mode);
for (final repo in candidate.metadata.values) {
- _lastKnownGood.addMetadataRepository(repo);
+ lastKnownGood.addMetadataRepository(repo);
}
_pendingDeltas.clear();
}
@@ -180,12 +182,12 @@
fullComponent = true;
}
- Future<Procedure> compileExpression(
+ Future<Procedure?> compileExpression(
String expression,
List<String> definitions,
List<String> typeDefinitions,
String libraryUri,
- String klass,
+ String? klass,
bool isStatic) {
Map<String, DartType> completeDefinitions = {};
for (String name in definitions) {
@@ -200,7 +202,6 @@
}
Uri library = Uri.parse(libraryUri);
- if (library == null) return null;
return _generator.compileExpression(expression, completeDefinitions,
typeParameters, kDebugProcedureName, library, klass, isStatic);
diff --git a/pkg/vm/lib/kernel_front_end.dart b/pkg/vm/lib/kernel_front_end.dart
index 0458451..51ed004 100644
--- a/pkg/vm/lib/kernel_front_end.dart
+++ b/pkg/vm/lib/kernel_front_end.dart
@@ -3,7 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
/// Defines the VM-specific translation of Dart source code to kernel binaries.
-library vm.kernel_front_end;
import 'dart:async';
import 'dart:io' show File, IOSink;
@@ -160,7 +159,7 @@
/// Run kernel compiler tool with given [options] and [usage]
/// and return exit code.
Future<int> runCompiler(ArgResults options, String usage) async {
- final String platformKernel = options['platform'];
+ final String? platformKernel = options['platform'];
if (options['help']) {
print(usage);
@@ -174,26 +173,26 @@
final String input = options.rest.single;
final String outputFileName = options['output'] ?? "$input.dill";
- final String packages = options['packages'];
+ final String? packages = options['packages'];
final String targetName = options['target'];
- final String fileSystemScheme = options['filesystem-scheme'];
- final String depfile = options['depfile'];
- final String fromDillFile = options['from-dill'];
- final List<String> fileSystemRoots = options['filesystem-root'];
+ final String? fileSystemScheme = options['filesystem-scheme'];
+ final String? depfile = options['depfile'];
+ final String? fromDillFile = options['from-dill'];
+ final List<String>? fileSystemRoots = options['filesystem-root'];
final bool aot = options['aot'];
final bool tfa = options['tfa'];
final bool linkPlatform = options['link-platform'];
final bool embedSources = options['embed-sources'];
final bool enableAsserts = options['enable-asserts'];
- final bool nullSafety = options['sound-null-safety'];
+ final bool? nullSafety = options['sound-null-safety'];
final bool useProtobufTreeShakerV2 = options['protobuf-tree-shaker-v2'];
final bool splitOutputByPackages = options['split-output-by-packages'];
- final String manifestFilename = options['manifest'];
- final String dataDir = options['component-name'] ?? options['data-dir'];
+ final String? manifestFilename = options['manifest'];
+ final String? dataDir = options['component-name'] ?? options['data-dir'];
final bool minimalKernel = options['minimal-kernel'];
final bool treeShakeWriteOnlyFields = options['tree-shake-write-only-fields'];
- final List<String> experimentalFlags = options['enable-experiment'];
+ final List<String>? experimentalFlags = options['enable-experiment'];
final Map<String, String> environmentDefines = {};
if (!parseCommandLineDefines(options['define'], environmentDefines, usage)) {
@@ -215,7 +214,7 @@
final fileSystem =
createFrontEndFileSystem(fileSystemScheme, fileSystemRoots);
- final Uri packagesUri = packages != null ? resolveInputUri(packages) : null;
+ final Uri? packagesUri = packages != null ? resolveInputUri(packages) : null;
final platformKernelUri = Uri.base.resolveUri(new Uri.file(platformKernel));
final List<Uri> additionalDills = <Uri>[];
@@ -230,7 +229,8 @@
final verbosity = Verbosity.parseArgument(options['verbosity']);
final errorPrinter = new ErrorPrinter(verbosity);
- final errorDetector = new ErrorDetector(previousErrorHandler: errorPrinter);
+ final errorDetector =
+ new ErrorDetector(previousErrorHandler: errorPrinter.call);
final CompilerOptions compilerOptions = new CompilerOptions()
..sdkSummary = platformKernelUri
@@ -278,19 +278,20 @@
errorPrinter.printCompilationMessages();
- if (errorDetector.hasCompilationErrors || (results.component == null)) {
+ final Component? component = results.component;
+ if (errorDetector.hasCompilationErrors || (component == null)) {
return compileTimeErrorExitCode;
}
final IOSink sink = new File(outputFileName).openWrite();
final BinaryPrinter printer = new BinaryPrinter(sink,
libraryFilter: (lib) => !results.loadedLibraries.contains(lib));
- printer.writeComponentFile(results.component);
+ printer.writeComponentFile(component);
await sink.close();
if (depfile != null) {
await writeDepfile(
- fileSystem, results.compiledSources, outputFileName, depfile);
+ fileSystem, results.compiledSources!, outputFileName, depfile);
}
if (splitOutputByPackages) {
@@ -312,14 +313,14 @@
/// Results of [compileToKernel]: generated kernel [Component] and
/// collection of compiled sources.
class KernelCompilationResults {
- final Component component;
+ final Component? component;
/// Set of libraries loaded from .dill, with or without the SDK depending on
/// the compilation settings.
final Set<Library> loadedLibraries;
- final ClassHierarchy classHierarchy;
- final CoreTypes coreTypes;
- final Iterable<Uri> compiledSources;
+ final ClassHierarchy? classHierarchy;
+ final CoreTypes? coreTypes;
+ final Iterable<Uri>? compiledSources;
KernelCompilationResults(this.component, this.loadedLibraries,
this.classHierarchy, this.coreTypes, this.compiledSources);
@@ -336,29 +337,30 @@
List<String> deleteToStringPackageUris: const <String>[],
bool aot: false,
bool useGlobalTypeFlowAnalysis: false,
- Map<String, String> environmentDefines,
+ required Map<String, String> environmentDefines,
bool enableAsserts: true,
bool useProtobufTreeShakerV2: false,
bool minimalKernel: false,
bool treeShakeWriteOnlyFields: false,
- String fromDillFile: null}) async {
+ String? fromDillFile: null}) async {
// Replace error handler to detect if there are compilation errors.
final errorDetector =
new ErrorDetector(previousErrorHandler: options.onDiagnostic);
- options.onDiagnostic = errorDetector;
+ options.onDiagnostic = errorDetector.call;
+ final target = options.target!;
options.environmentDefines =
- options.target.updateEnvironmentDefines(environmentDefines);
+ target.updateEnvironmentDefines(environmentDefines);
- CompilerResult compilerResult;
+ CompilerResult? compilerResult;
if (fromDillFile != null) {
compilerResult =
await loadKernel(options.fileSystem, resolveInputUri(fromDillFile));
} else {
compilerResult = await kernelForProgram(source, options);
}
- Component component = compilerResult?.component;
- Iterable<Uri> compiledSources = component?.uriToSource?.keys;
+ final Component? component = compilerResult?.component;
+ Iterable<Uri>? compiledSources = component?.uriToSource.keys;
Set<Library> loadedLibraries = createLoadedLibrariesSet(
compilerResult?.loadedComponents, compilerResult?.sdkComponent,
@@ -371,13 +373,8 @@
// Run global transformations only if component is correct.
if ((aot || minimalKernel) && component != null) {
- await runGlobalTransformations(
- options.target,
- component,
- useGlobalTypeFlowAnalysis,
- enableAsserts,
- useProtobufTreeShakerV2,
- errorDetector,
+ await runGlobalTransformations(target, component, useGlobalTypeFlowAnalysis,
+ enableAsserts, useProtobufTreeShakerV2, errorDetector,
minimalKernel: minimalKernel,
treeShakeWriteOnlyFields: treeShakeWriteOnlyFields);
@@ -385,7 +382,7 @@
// compiledSources is component.uriToSource.keys.
// Make a copy of compiledSources to detach it from
// component.uriToSource which is cleared below.
- compiledSources = compiledSources.toList();
+ compiledSources = compiledSources!.toList();
component.metadata.clear();
component.uriToSource.clear();
@@ -404,7 +401,7 @@
}
Set<Library> createLoadedLibrariesSet(
- List<Component> loadedComponents, Component sdkComponent,
+ List<Component>? loadedComponents, Component? sdkComponent,
{bool includePlatform: false}) {
final Set<Library> loadedLibraries = {};
if (loadedComponents != null) {
@@ -479,8 +476,11 @@
/// Runs given [action] with [CompilerContext]. This is needed to
/// be able to report compile-time errors.
-Future<T> runWithFrontEndCompilerContext<T>(Uri source,
- CompilerOptions compilerOptions, Component component, T action()) async {
+Future<T> runWithFrontEndCompilerContext<T>(
+ Uri source,
+ CompilerOptions compilerOptions,
+ Component component,
+ Future<T> action()) async {
final processedOptions =
new ProcessedOptions(options: compilerOptions, inputs: [source]);
@@ -496,7 +496,7 @@
}
class ErrorDetector {
- final DiagnosticMessageHandler previousErrorHandler;
+ final DiagnosticMessageHandler? previousErrorHandler;
bool hasCompilationErrors = false;
ErrorDetector({this.previousErrorHandler});
@@ -512,8 +512,9 @@
class ErrorPrinter {
final Verbosity verbosity;
- final DiagnosticMessageHandler previousErrorHandler;
- final compilationMessages = <Uri, List<DiagnosticMessage>>{};
+ final DiagnosticMessageHandler? previousErrorHandler;
+ final Map<Uri?, List<DiagnosticMessage>> compilationMessages =
+ <Uri?, List<DiagnosticMessage>>{};
ErrorPrinter(this.verbosity, {this.previousErrorHandler});
@@ -537,8 +538,8 @@
}
return 0;
});
- for (final Uri sourceUri in sortedUris) {
- for (final DiagnosticMessage message in compilationMessages[sourceUri]) {
+ for (final Uri? sourceUri in sortedUris) {
+ for (final DiagnosticMessage message in compilationMessages[sourceUri]!) {
if (Verbosity.shouldPrint(verbosity, message)) {
printDiagnosticMessage(message, print);
}
@@ -574,7 +575,7 @@
}
/// Create front-end target with given name.
-Target createFrontEndTarget(String targetName,
+Target? createFrontEndTarget(String targetName,
{bool trackWidgetCreation = false, bool nullSafety = false}) {
// Make sure VM-specific targets are available.
installAdditionalTargets();
@@ -589,9 +590,8 @@
/// If requested, create a virtual mutli-root file system and/or an http aware
/// file system.
FileSystem createFrontEndFileSystem(
- String multiRootFileSystemScheme, List<String> multiRootFileSystemRoots,
- {bool allowHttp}) {
- allowHttp ??= false;
+ String? multiRootFileSystemScheme, List<String>? multiRootFileSystemRoots,
+ {bool allowHttp = false}) {
FileSystem fileSystem = StandardFileSystem.instance;
if (allowHttp) {
fileSystem = HttpAwareFileSystem(fileSystem);
@@ -613,7 +613,7 @@
Future<Uri> asFileUri(FileSystem fileSystem, Uri uri) async {
FileSystemEntity fse = fileSystem.entityForUri(uri);
if (fse is MultiRootFileSystemEntity) {
- fse = await (fse as MultiRootFileSystemEntity).delegate;
+ fse = await fse.delegate;
}
return fse.uri;
}
@@ -643,8 +643,9 @@
Future writeOutputSplitByPackages(Uri source, CompilerOptions compilerOptions,
KernelCompilationResults compilationResults, String outputFileName) async {
final packages = <String>[];
- await runWithFrontEndCompilerContext(
- source, compilerOptions, compilationResults.component, () async {
+ final Component component = compilationResults.component!;
+ await runWithFrontEndCompilerContext(source, compilerOptions, component,
+ () async {
// When loading a kernel file list, flutter_runner and dart_runner expect
// 'main' to be last.
await forEachPackage(compilationResults,
@@ -653,12 +654,10 @@
final String filename = '$outputFileName-$package.dilp';
final IOSink sink = new File(filename).openWrite();
- Component partComponent = compilationResults.component;
-
final BinaryPrinter printer = new BinaryPrinter(sink,
libraryFilter: (lib) =>
packageFor(lib, compilationResults.loadedLibraries) == package);
- printer.writeComponentFile(partComponent);
+ printer.writeComponentFile(component);
await sink.close();
}, mainFirst: false);
@@ -671,7 +670,7 @@
await packagesList.close();
}
-String packageFor(Library lib, Set<Library> loadedLibraries) {
+String? packageFor(Library lib, Set<Library> loadedLibraries) {
// Core libraries are not written into any package kernel binaries.
if (loadedLibraries.contains(lib)) return null;
@@ -699,23 +698,25 @@
}
}
-Future<Null> forEachPackage<T>(KernelCompilationResults results,
- T action(String package, List<Library> libraries),
- {bool mainFirst}) async {
- final Component component = results.component;
+Future<void> forEachPackage(KernelCompilationResults results,
+ Future<void> action(String package, List<Library> libraries),
+ {required bool mainFirst}) async {
+ final Component component = results.component!;
final Set<Library> loadedLibraries = results.loadedLibraries;
sortComponent(component);
- final packages = new Map<String, List<Library>>();
+ final Map<String, List<Library>> packages = <String, List<Library>>{};
packages['main'] = <Library>[]; // Always create 'main'.
for (Library lib in component.libraries) {
- packages
- .putIfAbsent(packageFor(lib, loadedLibraries), () => <Library>[])
- .add(lib);
+ final String? package = packageFor(lib, loadedLibraries);
+ // Ignore external libraries.
+ if (package == null) {
+ continue;
+ }
+ packages.putIfAbsent(package, () => <Library>[]).add(lib);
}
- packages.remove(null); // Ignore external libraries.
- final mainLibraries = packages.remove('main');
+ final mainLibraries = packages.remove('main')!;
if (mainFirst) {
await action('main', mainLibraries);
}
@@ -726,7 +727,7 @@
component.setMainMethodAndMode(null, true, compilationMode);
component.problemsAsJson = null;
for (String package in packages.keys) {
- await action(package, packages[package]);
+ await action(package, packages[package]!);
}
component.setMainMethodAndMode(mainMethod?.reference, true, compilationMode);
component.problemsAsJson = problemsAsJson;
@@ -748,8 +749,8 @@
file.write(_escapePath(output));
file.write(':');
for (Uri dep in compiledSources) {
- // Skip empty or corelib dependencies.
- if (dep == null || dep.scheme == 'org-dartlang-sdk') continue;
+ // Skip corelib dependencies.
+ if (dep.scheme == 'org-dartlang-sdk') continue;
Uri uri = await asFileUri(fileSystem, dep);
file.write(' ');
file.write(_escapePath(uri.toFilePath()));
@@ -759,7 +760,7 @@
}
Future<void> createFarManifest(
- String output, String dataDir, String packageManifestFilename) async {
+ String output, String? dataDir, String packageManifestFilename) async {
List<String> packages = await File('$output-packages').readAsLines();
// Make sure the 'main' package is the last (convention with package loader).
@@ -789,7 +790,7 @@
'typed_data',
'vector_math'
]) {
- Digest digest;
+ Digest? digest;
if (packages.contains(package)) {
final filenameInBuild = '$output-$package.dilp';
final bytes = await File(filenameInBuild).readAsBytes();
@@ -811,11 +812,20 @@
CompilerResultLoadedFromKernel(this.component);
- List<int> get summary => null;
+ @override
+ List<int>? get summary => null;
+
+ @override
List<Component> get loadedComponents => const <Component>[];
+
+ @override
List<Uri> get deps => const <Uri>[];
- CoreTypes get coreTypes => null;
- ClassHierarchy get classHierarchy => null;
+
+ @override
+ CoreTypes? get coreTypes => null;
+
+ @override
+ ClassHierarchy? get classHierarchy => null;
}
Future<CompilerResult> loadKernel(
diff --git a/pkg/vm/lib/metadata/call_site_attributes.dart b/pkg/vm/lib/metadata/call_site_attributes.dart
index 7ef8c93..23733d8 100644
--- a/pkg/vm/lib/metadata/call_site_attributes.dart
+++ b/pkg/vm/lib/metadata/call_site_attributes.dart
@@ -2,10 +2,6 @@
// 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.
-// @dart=2.12
-
-library vm.metadata.call_site_attributes;
-
import 'package:kernel/ast.dart';
import 'package:kernel/src/printer.dart';
diff --git a/pkg/vm/lib/metadata/direct_call.dart b/pkg/vm/lib/metadata/direct_call.dart
index 8e4298b..3539978 100644
--- a/pkg/vm/lib/metadata/direct_call.dart
+++ b/pkg/vm/lib/metadata/direct_call.dart
@@ -14,7 +14,7 @@
DirectCallMetadata(Member target, bool checkReceiverForNull)
: this.byReference(
- getMemberReferenceGetter(target), checkReceiverForNull);
+ getNonNullableMemberReferenceGetter(target), checkReceiverForNull);
DirectCallMetadata.byReference(
this._targetReference, this.checkReceiverForNull);
diff --git a/pkg/vm/lib/metadata/inferred_type.dart b/pkg/vm/lib/metadata/inferred_type.dart
index 4d609fd..6f23f6e 100644
--- a/pkg/vm/lib/metadata/inferred_type.dart
+++ b/pkg/vm/lib/metadata/inferred_type.dart
@@ -9,8 +9,8 @@
/// Metadata for annotating nodes with an inferred type information.
class InferredType {
- final Reference _concreteClassReference;
- final Constant _constantValue;
+ final Reference? _concreteClassReference;
+ final Constant? _constantValue;
final int _flags;
static const int flagNullable = 1 << 0;
@@ -31,11 +31,11 @@
//
// Otherwise, a non-null type argument indicates that that particular type
// argument (in the runtime type) is always exactly a particular `DartType`.
- final List<DartType> exactTypeArguments;
+ final List<DartType?>? exactTypeArguments;
InferredType(
- Class concreteClass, bool nullable, bool isInt, Constant constantValue,
- {List<DartType> exactTypeArguments,
+ Class? concreteClass, bool nullable, bool isInt, Constant? constantValue,
+ {List<DartType?>? exactTypeArguments,
bool skipCheck: false,
bool receiverNotInt: false})
: this._byReference(
@@ -54,9 +54,9 @@
assert(_constantValue == null || _concreteClassReference != null);
}
- Class get concreteClass => _concreteClassReference?.asClass;
+ Class? get concreteClass => _concreteClassReference?.asClass;
- Constant get constantValue => _constantValue;
+ Constant? get constantValue => _constantValue;
bool get nullable => (_flags & flagNullable) != 0;
bool get isInt => (_flags & flagInt) != 0;
@@ -69,7 +69,7 @@
String toString() {
final StringBuffer buf = new StringBuffer();
if (concreteClass != null) {
- buf.write(concreteClass.toText(astTextStrategyForTesting));
+ buf.write(concreteClass!.toText(astTextStrategyForTesting));
} else if (isInt) {
buf.write('int');
} else {
@@ -80,7 +80,7 @@
}
if (exactTypeArguments != null) {
buf.write('<');
- buf.write(exactTypeArguments
+ buf.write(exactTypeArguments!
.map(
(t) => t != null ? "${t.toText(astTextStrategyForTesting)}" : "?")
.join(", "));
@@ -91,7 +91,7 @@
}
if (_constantValue != null) {
buf.write(
- ' (value: ${_constantValue.toText(astTextStrategyForTesting)})');
+ ' (value: ${_constantValue!.toText(astTextStrategyForTesting)})');
}
if (receiverNotInt) {
buf.write(' (receiver not int)');
@@ -115,11 +115,11 @@
// TODO(sjindel/tfa): Implement serialization of type arguments when can use
// them for optimizations.
sink.writeNullAllowedCanonicalNameReference(metadata.concreteClass != null
- ? getCanonicalNameOfClass(metadata.concreteClass)
+ ? getCanonicalNameOfClass(metadata.concreteClass!)
: null);
sink.writeByte(metadata._flags);
if (metadata.constantValue != null) {
- sink.writeConstantReference(metadata.constantValue);
+ sink.writeConstantReference(metadata.constantValue!);
}
}
diff --git a/pkg/vm/lib/metadata/unboxing_info.dart b/pkg/vm/lib/metadata/unboxing_info.dart
index 7069c05..64646a7 100644
--- a/pkg/vm/lib/metadata/unboxing_info.dart
+++ b/pkg/vm/lib/metadata/unboxing_info.dart
@@ -14,11 +14,12 @@
final List<int> unboxedArgsInfo;
int returnInfo;
- UnboxingInfoMetadata(int argsLen) : unboxedArgsInfo = [] {
+ UnboxingInfoMetadata(int argsLen)
+ : unboxedArgsInfo = [],
+ returnInfo = kUnboxingCandidate {
for (int i = 0; i < argsLen; i++) {
unboxedArgsInfo.add(kUnboxingCandidate);
}
- returnInfo = kUnboxingCandidate;
}
UnboxingInfoMetadata.readFromBinary(BinarySource source)
diff --git a/pkg/vm/lib/target/dart_runner.dart b/pkg/vm/lib/target/dart_runner.dart
index 928863c..995d484 100644
--- a/pkg/vm/lib/target/dart_runner.dart
+++ b/pkg/vm/lib/target/dart_runner.dart
@@ -1,7 +1,6 @@
// 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.
-library vm.target.dart_runner;
import 'package:kernel/target/targets.dart';
import 'package:vm/target/vm.dart' show VmTarget;
diff --git a/pkg/vm/lib/target/flutter.dart b/pkg/vm/lib/target/flutter.dart
index 7746e98..1eadf20 100644
--- a/pkg/vm/lib/target/flutter.dart
+++ b/pkg/vm/lib/target/flutter.dart
@@ -1,7 +1,6 @@
// Copyright (c) 2016, 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.
-library vm.target.flutter;
import 'package:kernel/ast.dart' show Component, Library;
import 'package:kernel/core_types.dart' show CoreTypes;
@@ -13,7 +12,7 @@
class FlutterTarget extends VmTarget {
FlutterTarget(TargetFlags flags) : super(flags);
- WidgetCreatorTracker _widgetTracker;
+ late final WidgetCreatorTracker _widgetTracker = WidgetCreatorTracker();
@override
String get name => 'flutter';
@@ -56,15 +55,12 @@
CoreTypes coreTypes,
List<Library> libraries,
DiagnosticReporter diagnosticReporter,
- {void logger(String msg),
- ChangedStructureNotifier changedStructureNotifier}) {
+ {void Function(String msg)? logger,
+ ChangedStructureNotifier? changedStructureNotifier}) {
super.performPreConstantEvaluationTransformations(
component, coreTypes, libraries, diagnosticReporter,
logger: logger, changedStructureNotifier: changedStructureNotifier);
if (flags.trackWidgetCreation) {
- if (_widgetTracker == null) {
- _widgetTracker = WidgetCreatorTracker();
- }
_widgetTracker.transform(component, libraries, changedStructureNotifier);
}
}
diff --git a/pkg/vm/lib/target/flutter_runner.dart b/pkg/vm/lib/target/flutter_runner.dart
index 9a2b477..addd766 100644
--- a/pkg/vm/lib/target/flutter_runner.dart
+++ b/pkg/vm/lib/target/flutter_runner.dart
@@ -1,7 +1,6 @@
// 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.
-library vm.target.flutter_runner;
import 'package:kernel/target/targets.dart';
import 'package:vm/target/vm.dart' show VmTarget;
diff --git a/pkg/vm/lib/target/install.dart b/pkg/vm/lib/target/install.dart
index 4973418..b22d469 100644
--- a/pkg/vm/lib/target/install.dart
+++ b/pkg/vm/lib/target/install.dart
@@ -2,8 +2,6 @@
// 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.
-library vm.target.install;
-
import 'package:kernel/target/targets.dart' show targets, TargetFlags;
import 'package:vm/target/dart_runner.dart' show DartRunnerTarget;
import 'package:vm/target/flutter.dart' show FlutterTarget;
diff --git a/pkg/vm/lib/target/vm.dart b/pkg/vm/lib/target/vm.dart
index 3230605..01def63 100644
--- a/pkg/vm/lib/target/vm.dart
+++ b/pkg/vm/lib/target/vm.dart
@@ -1,7 +1,6 @@
// Copyright (c) 2016, 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.
-library vm.target.vm;
import 'package:kernel/ast.dart';
import 'package:kernel/clone.dart';
@@ -33,14 +32,14 @@
class VmTarget extends Target {
final TargetFlags flags;
- Class _growableList;
- Class _immutableList;
- Class _internalLinkedHashMap;
- Class _immutableMap;
- Class _oneByteString;
- Class _twoByteString;
- Class _smi;
- Class _double; // _Double, not double.
+ Class? _growableList;
+ Class? _immutableList;
+ Class? _internalLinkedHashMap;
+ Class? _immutableMap;
+ Class? _oneByteString;
+ Class? _twoByteString;
+ Class? _smi;
+ Class? _double; // _Double, not double.
VmTarget(this.flags);
@@ -65,9 +64,6 @@
!flags.forceNoExplicitGetterCallsForTesting;
@override
- bool get supportsNewMethodInvocationEncoding => true;
-
- @override
int get enabledConstructorTearOffLowerings =>
flags.forceConstructorTearOffLoweringForTesting;
@@ -111,11 +107,11 @@
// support patching fields.
// See http://dartbug.com/32836 for the background.
final Field host =
- coreTypes.index.getMember('dart:typed_data', 'Endian', 'host');
+ coreTypes.index.getField('dart:typed_data', 'Endian', 'host');
final Field little =
- coreTypes.index.getMember('dart:typed_data', 'Endian', 'little');
+ coreTypes.index.getField('dart:typed_data', 'Endian', 'little');
host.isConst = true;
- host.initializer = new CloneVisitorNotMembers().clone(little.initializer)
+ host.initializer = new CloneVisitorNotMembers().clone(little.initializer!)
..parent = host;
}
@@ -125,8 +121,8 @@
CoreTypes coreTypes,
List<Library> libraries,
DiagnosticReporter diagnosticReporter,
- {void logger(String msg),
- ChangedStructureNotifier changedStructureNotifier}) {
+ {void Function(String msg)? logger,
+ ChangedStructureNotifier? changedStructureNotifier}) {
super.performPreConstantEvaluationTransformations(
component, coreTypes, libraries, diagnosticReporter,
logger: logger, changedStructureNotifier: changedStructureNotifier);
@@ -151,11 +147,11 @@
CoreTypes coreTypes,
ClassHierarchy hierarchy,
List<Library> libraries,
- Map<String, String> environmentDefines,
+ Map<String, String>? environmentDefines,
DiagnosticReporter diagnosticReporter,
- ReferenceFromIndex referenceFromIndex,
- {void logger(String msg),
- ChangedStructureNotifier changedStructureNotifier}) {
+ ReferenceFromIndex? referenceFromIndex,
+ {void Function(String msg)? logger,
+ ChangedStructureNotifier? changedStructureNotifier}) {
transformMixins.transformLibraries(
this, coreTypes, hierarchy, libraries, referenceFromIndex);
logger?.call("Transformed mixin applications");
@@ -165,7 +161,7 @@
} else {
// Transform @FfiNative(..) functions into ffi native call functions.
transformFfiNative.transformLibraries(
- component, libraries, referenceFromIndex);
+ component, libraries, diagnosticReporter, referenceFromIndex);
logger?.call("Transformed ffi natives");
// TODO(jensj/dacoharkes): We can probably limit the transformations to
// libraries that transitivley depend on dart:ffi.
@@ -183,7 +179,7 @@
}
// TODO(kmillikin): Make this run on a per-method basis.
- bool productMode = environmentDefines["dart.vm.product"] == "true";
+ bool productMode = environmentDefines!["dart.vm.product"] == "true";
transformAsync.transformLibraries(
new TypeEnvironment(coreTypes, hierarchy), libraries,
productMode: productMode);
@@ -203,9 +199,9 @@
CoreTypes coreTypes,
ClassHierarchy hierarchy,
Procedure procedure,
- Map<String, String> environmentDefines,
- {void logger(String msg)}) {
- bool productMode = environmentDefines["dart.vm.product"] == "true";
+ Map<String, String>? environmentDefines,
+ {void Function(String msg)? logger}) {
+ bool productMode = environmentDefines!["dart.vm.product"] == "true";
transformAsync.transformProcedure(
new TypeEnvironment(coreTypes, hierarchy), procedure,
productMode: productMode);
@@ -450,7 +446,7 @@
}
@override
- Class concreteIntLiteralClass(CoreTypes coreTypes, int value) {
+ Class? concreteIntLiteralClass(CoreTypes coreTypes, int value) {
const int bitsPerInt32 = 32;
const int smiBits32 = bitsPerInt32 - 2;
const int smiMin32 = -(1 << smiBits32);
@@ -489,7 +485,6 @@
Map<String, String> updateEnvironmentDefines(Map<String, String> map) {
// TODO(alexmarkov): Call this from the front-end in order to have
// the same defines when compiling platform.
- assert(map != null);
map['dart.isVM'] = 'true';
// TODO(dartbug.com/36460): Derive dart.library.* definitions from platform.
for (String library in extraRequiredLibraries) {
diff --git a/pkg/vm/lib/transformations/call_site_annotator.dart b/pkg/vm/lib/transformations/call_site_annotator.dart
index 76803a9..691ba84 100644
--- a/pkg/vm/lib/transformations/call_site_annotator.dart
+++ b/pkg/vm/lib/transformations/call_site_annotator.dart
@@ -2,14 +2,11 @@
// 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.
-// @dart=2.12
-
// This transformation annotates call sites with the receiver type.
// This is done to avoid reimplementing [Expression.getStaticType] in
// C++.
// We don't annotate all call-sites, but only those where VM could benefit from
// knowing static type of the receiver.
-library vm.transformations.call_site_annotator;
import 'package:kernel/ast.dart';
import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
@@ -60,18 +57,6 @@
}
@override
- visitPropertyGet(PropertyGet node) =>
- throw 'Unexpected node ${node.runtimeType}: $node at ${node.location}';
-
- @override
- visitPropertySet(PropertySet node) =>
- throw 'Unexpected node ${node.runtimeType}: $node at ${node.location}';
-
- @override
- visitMethodInvocation(MethodInvocation node) =>
- throw 'Unexpected node ${node.runtimeType}: $node at ${node.location}';
-
- @override
visitInstanceSet(InstanceSet node) {
super.visitInstanceSet(node);
diff --git a/pkg/vm/lib/transformations/deferred_loading.dart b/pkg/vm/lib/transformations/deferred_loading.dart
index 03bb9c2..b7dd321 100644
--- a/pkg/vm/lib/transformations/deferred_loading.dart
+++ b/pkg/vm/lib/transformations/deferred_loading.dart
@@ -9,15 +9,15 @@
import '../metadata/loading_units.dart';
class _LoadingUnitBuilder {
- int id;
+ late int id;
final _LibraryVertex root;
final List<Library> members = <Library>[];
final List<_LoadingUnitBuilder> children = <_LoadingUnitBuilder>[];
_LoadingUnitBuilder(this.root);
- _LoadingUnitBuilder get parent => root.dominator?.loadingUnit;
- int get parentId => parent == null ? 0 : parent.id;
+ _LoadingUnitBuilder? get parent => root.dominator?.loadingUnit;
+ int get parentId => parent == null ? 0 : parent!.id;
LoadingUnit asLoadingUnit() {
return new LoadingUnit(
@@ -31,7 +31,7 @@
class _LibraryVertex extends Vertex<_LibraryVertex> {
final Library library;
bool isLoadingRoot = true;
- _LoadingUnitBuilder loadingUnit;
+ _LoadingUnitBuilder? loadingUnit;
_LibraryVertex(this.library);
String toString() => "_LibraryVertex(${library.importUri})";
@@ -45,11 +45,11 @@
}
for (final vertex in map.values) {
for (final dep in vertex.library.dependencies) {
- final target = map[dep.targetLibrary];
+ final target = map[dep.targetLibrary]!;
vertex.successors.add(target);
}
}
- final root = map[component.mainMethod.parent as Library];
+ final root = map[component.mainMethod!.enclosingLibrary]!;
// Fake imports from root library to every core library so they end up in
// the same loading unit attributed to the user's root library.
@@ -71,7 +71,7 @@
if (dep.isDeferred) {
continue;
}
- var importee = map[dep.targetLibrary];
+ var importee = map[dep.targetLibrary]!;
if (importer.isDominatedBy(importee)) {
continue;
}
@@ -80,7 +80,7 @@
}
assert(root.isLoadingRoot);
- var loadingUnits = <_LoadingUnitBuilder>[];
+ final List<_LoadingUnitBuilder> loadingUnits = <_LoadingUnitBuilder>[];
for (var vertex in map.values) {
if (vertex.isLoadingRoot) {
var unit = new _LoadingUnitBuilder(vertex);
@@ -99,11 +99,11 @@
if (dom == null) {
continue; // Unreachable library.
}
- while (dom.loadingUnit == null) {
+ while (dom!.loadingUnit == null) {
dom = dom.dominator;
}
vertex.loadingUnit = dom.loadingUnit;
- vertex.loadingUnit.members.add(vertex.library);
+ vertex.loadingUnit!.members.add(vertex.library);
}
// 4. Sort loading units so parents are before children. Normally this order
@@ -117,7 +117,7 @@
}
var index = 0;
loadingUnits.clear();
- loadingUnits.add(root.loadingUnit);
+ loadingUnits.add(root.loadingUnit!);
while (index < loadingUnits.length) {
var unit = loadingUnits[index];
unit.id = ++index;
diff --git a/pkg/vm/lib/transformations/devirtualization.dart b/pkg/vm/lib/transformations/devirtualization.dart
index 38de80f..7d82594 100644
--- a/pkg/vm/lib/transformations/devirtualization.dart
+++ b/pkg/vm/lib/transformations/devirtualization.dart
@@ -16,7 +16,8 @@
Component transformComponent(CoreTypes coreTypes, Component component) {
void ignoreAmbiguousSupertypes(Class cls, Supertype a, Supertype b) {}
ClosedWorldClassHierarchy hierarchy = new ClassHierarchy(component, coreTypes,
- onAmbiguousSupertypes: ignoreAmbiguousSupertypes);
+ onAmbiguousSupertypes: ignoreAmbiguousSupertypes)
+ as ClosedWorldClassHierarchy;
final hierarchySubtypes = hierarchy.computeSubtypesInformation();
new CHADevirtualization(coreTypes, component, hierarchy, hierarchySubtypes)
.visitComponent(component);
@@ -32,14 +33,14 @@
static const _trace = const bool.fromEnvironment('trace.devirtualization');
final DirectCallMetadataRepository _metadata;
- Set<Name> _objectMemberNames;
+ final Set<Name> _objectMemberNames;
Devirtualization(
CoreTypes coreTypes, Component component, ClassHierarchy hierarchy)
- : _metadata = new DirectCallMetadataRepository() {
- _objectMemberNames = new Set<Name>.from(hierarchy
- .getInterfaceMembers(coreTypes.objectClass)
- .map((Member m) => m.name));
+ : _metadata = new DirectCallMetadataRepository(),
+ _objectMemberNames = new Set<Name>.from(hierarchy
+ .getInterfaceMembers(coreTypes.objectClass)
+ .map((Member m) => m.name)) {
component.addMetadataRepository(_metadata);
}
@@ -49,7 +50,7 @@
(member is Field) || ((member is Procedure) && member.isGetter);
bool isLegalTargetForMethodInvocation(Member target, Arguments arguments) {
- final FunctionNode func = target.function;
+ final FunctionNode func = target.function!;
final positionalArgs = arguments.positional.length;
if ((positionalArgs < func.requiredParameterCount) ||
@@ -82,10 +83,10 @@
directCall.checkReceiverForNull &&
_objectMemberNames.contains(directCall.target.name);
- DirectCallMetadata getDirectCall(TreeNode node, Member interfaceTarget,
+ DirectCallMetadata? getDirectCall(TreeNode node, Member? interfaceTarget,
{bool setter = false});
- makeDirectCall(TreeNode node, Member target, DirectCallMetadata directCall) {
+ makeDirectCall(TreeNode node, Member? target, DirectCallMetadata directCall) {
if (_trace) {
print("[devirt] Resolving ${target} to ${directCall.target}"
" at ${node.location}");
@@ -102,12 +103,12 @@
}
void _handleMethodInvocation(
- TreeNode node, Member target, Arguments arguments) {
+ TreeNode node, Member? target, Arguments arguments) {
if (target != null && !isMethod(target)) {
return;
}
- final DirectCallMetadata directCall = getDirectCall(node, target);
+ final DirectCallMetadata? directCall = getDirectCall(node, target);
// TODO(alexmarkov): Convert _isLegalTargetForMethodInvocation()
// check into an assertion once front-end implements all override checks.
@@ -136,18 +137,18 @@
super.visitEqualsCall(node);
final target = node.interfaceTarget;
- final DirectCallMetadata directCall = getDirectCall(node, target);
+ final DirectCallMetadata? directCall = getDirectCall(node, target);
if (directCall != null && !directCall.checkReceiverForNull) {
makeDirectCall(node, target, directCall);
}
}
- void _handlePropertyGet(TreeNode node, Member target) {
+ void _handlePropertyGet(TreeNode node, Member? target) {
if (target != null && !isFieldOrGetter(target)) {
return;
}
- final DirectCallMetadata directCall = getDirectCall(node, target);
+ final DirectCallMetadata? directCall = getDirectCall(node, target);
if ((directCall != null) &&
isFieldOrGetter(directCall.target) &&
@@ -168,8 +169,8 @@
_handlePropertyGet(node, null);
}
- void _handlePropertySet(TreeNode node, Member target) {
- final DirectCallMetadata directCall =
+ void _handlePropertySet(TreeNode node, Member? target) {
+ final DirectCallMetadata? directCall =
getDirectCall(node, target, setter: true);
if (directCall != null) {
makeDirectCall(node, target, directCall);
@@ -198,12 +199,12 @@
: super(coreTypes, component, hierarchy);
@override
- DirectCallMetadata getDirectCall(TreeNode node, Member interfaceTarget,
+ DirectCallMetadata? getDirectCall(TreeNode node, Member? interfaceTarget,
{bool setter = false}) {
if (interfaceTarget == null) {
return null;
}
- Member singleTarget = _hierarchySubtype
+ Member? singleTarget = _hierarchySubtype
.getSingleTargetForInterfaceInvocation(interfaceTarget, setter: setter);
if (singleTarget == null) {
return null;
diff --git a/pkg/vm/lib/transformations/ffi.dart b/pkg/vm/lib/transformations/ffi.dart
index bc29a1a..88edf51 100644
--- a/pkg/vm/lib/transformations/ffi.dart
+++ b/pkg/vm/lib/transformations/ffi.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart=2.12
-
// This file contains logic which is shared between the ffi_definition and
// ffi_use_site transformers.
@@ -292,7 +290,9 @@
/// Classes corresponding to [NativeType], indexed by [NativeType].
final List<Class> nativeTypesClasses;
- Library? currentLibrary;
+ Library? _currentLibrary;
+ Library get currentLibrary => _currentLibrary!;
+
IndexedLibrary? currentLibraryIndex;
FfiTransformer(this.index, this.coreTypes, this.hierarchy,
@@ -459,11 +459,11 @@
@override
TreeNode visitLibrary(Library node) {
- assert(currentLibrary == null);
- currentLibrary = node;
+ assert(_currentLibrary == null);
+ _currentLibrary = node;
currentLibraryIndex = referenceFromIndex?.lookupLibrary(node);
final result = super.visitLibrary(node);
- currentLibrary = null;
+ _currentLibrary = null;
return result;
}
diff --git a/pkg/vm/lib/transformations/ffi_definitions.dart b/pkg/vm/lib/transformations/ffi_definitions.dart
index e84e660..2238251 100644
--- a/pkg/vm/lib/transformations/ffi_definitions.dart
+++ b/pkg/vm/lib/transformations/ffi_definitions.dart
@@ -2,8 +2,6 @@
// 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.
-library vm.transformations.ffi_definitions;
-
import 'dart:math' as math;
import 'package:front_end/src/api_unstable/vm.dart'
@@ -69,8 +67,8 @@
ClassHierarchy hierarchy,
List<Library> libraries,
DiagnosticReporter diagnosticReporter,
- ReferenceFromIndex referenceFromIndex,
- ChangedStructureNotifier changedStructureNotifier) {
+ ReferenceFromIndex? referenceFromIndex,
+ ChangedStructureNotifier? changedStructureNotifier) {
final LibraryIndex index = LibraryIndex(component,
const ["dart:core", "dart:ffi", "dart:_internal", "dart:typed_data"]);
if (!index.containsLibrary("dart:ffi")) {
@@ -94,7 +92,7 @@
CompoundDependencyGraph(this.map);
Iterable<T> get vertices => map.keys;
- Iterable<T> neighborsOf(T vertex) => map[vertex];
+ Iterable<T> neighborsOf(T vertex) => map[vertex]!;
}
/// Checks and elaborates the dart:ffi compounds and their fields.
@@ -107,16 +105,14 @@
Set<Class> transformCompoundsInvalid = {};
Map<Class, NativeTypeCfe> compoundCache = {};
- ChangedStructureNotifier changedStructureNotifier;
-
- IndexedLibrary currentLibraryIndex;
+ ChangedStructureNotifier? changedStructureNotifier;
_FfiDefinitionTransformer(
this.index,
CoreTypes coreTypes,
ClassHierarchy hierarchy,
DiagnosticReporter diagnosticReporter,
- ReferenceFromIndex referenceFromIndex,
+ ReferenceFromIndex? referenceFromIndex,
this.changedStructureNotifier)
: super(index, coreTypes, hierarchy, diagnosticReporter,
referenceFromIndex) {}
@@ -183,7 +179,7 @@
report = true;
}
if (component.length == 1) {
- if (dependencyGraph.map[component.single].contains(component.single)) {
+ if (dependencyGraph.map[component.single]!.contains(component.single)) {
// Direct cycle.
report = true;
}
@@ -191,7 +187,7 @@
if (report) {
component.forEach((Class e) {
diagnosticReporter.report(
- templateFfiFieldCyclic.withArguments(e.superclass.name, e.name,
+ templateFfiFieldCyclic.withArguments(e.superclass!.name, e.name,
component.map((e) => e.name).toList()),
e.fileOffset,
e.name.length,
@@ -231,12 +227,6 @@
}
@override
- visitLibrary(Library node) {
- currentLibraryIndex = referenceFromIndex?.lookupLibrary(node);
- return super.visitLibrary(node);
- }
-
- @override
visitExtension(Extension node) {
// The extension and it's members are only metadata.
return node;
@@ -260,9 +250,12 @@
final packing = _checkCompoundClass(node);
- final indexedClass = currentLibraryIndex?.lookupIndexedClass(node.name);
+ final IndexedClass? indexedClass =
+ currentLibraryIndex?.lookupIndexedClass(node.name);
_checkConstructors(node, indexedClass);
- indexedCompoundClasses[node] = indexedClass;
+ if (indexedClass != null) {
+ indexedCompoundClasses[node] = indexedClass;
+ }
final fieldsValid = _checkFieldAnnotations(node, packing);
if (fieldsValid) {
@@ -276,14 +269,14 @@
}
/// Returns packing if any.
- int _checkCompoundClass(Class node) {
+ int? _checkCompoundClass(Class node) {
if (node.typeParameters.length > 0) {
diagnosticReporter.report(
templateFfiStructGeneric.withArguments(
- node.superclass.name, node.name),
+ node.superclass!.name, node.name),
node.fileOffset,
1,
- node.location.file);
+ node.location!.file);
}
if (node.superclass != structClass && node.superclass != unionClass) {
@@ -299,7 +292,7 @@
templateFfiPackedAnnotation.withArguments(node.name),
node.fileOffset,
node.name.length,
- node.location.file);
+ node.location!.file);
}
if (packingAnnotations.isNotEmpty) {
final packing = packingAnnotations.first;
@@ -309,7 +302,7 @@
packing == 8 ||
packing == 16)) {
diagnosticReporter.report(messageFfiPackedAnnotationAlignment,
- node.fileOffset, node.name.length, node.location.file);
+ node.fileOffset, node.name.length, node.location!.file);
}
return packing;
}
@@ -352,14 +345,14 @@
if (member is Field) {
return member.type;
}
- final Procedure p = member;
+ final p = member as Procedure;
if (p.isGetter) {
return p.function.returnType;
}
return p.function.positionalParameters.single.type;
}
- bool _checkFieldAnnotations(Class node, int packing) {
+ bool _checkFieldAnnotations(Class node, int? packing) {
bool success = true;
final membersWithAnnotations =
_compoundFieldMembers(node, includeSetters: false);
@@ -443,9 +436,9 @@
success = false;
} else {
final DartType nativeType = InterfaceType(
- nativeTypesClasses[_getFieldType(nativeTypeAnnos.first).index],
+ nativeTypesClasses[_getFieldType(nativeTypeAnnos.first)!.index],
Nullability.legacy);
- final DartType shouldBeDartType = convertNativeTypeToDartType(
+ final DartType? shouldBeDartType = convertNativeTypeToDartType(
nativeType,
allowCompounds: true,
allowHandle: false);
@@ -453,11 +446,11 @@
!env.isSubtypeOf(type, shouldBeDartType,
SubtypeCheckMode.ignoringNullabilities)) {
diagnosticReporter.report(
- templateFfiTypeMismatch.withArguments(type, shouldBeDartType,
+ templateFfiTypeMismatch.withArguments(type, shouldBeDartType!,
nativeType, node.enclosingLibrary.isNonNullableByDefault),
f.fileOffset,
1,
- f.location.file);
+ f.location!.file);
// This class is invalid, but continue reporting other errors on it.
success = false;
}
@@ -466,7 +459,7 @@
return success;
}
- void _checkPacking(Class outerClass, int outerClassPacking, Class fieldClass,
+ void _checkPacking(Class outerClass, int? outerClassPacking, Class fieldClass,
Member errorNode) {
if (outerClassPacking == null) {
// Outer struct has no packing, nesting anything is fine.
@@ -495,7 +488,7 @@
}
}
- void _checkConstructors(Class node, IndexedClass indexedClass) {
+ void _checkConstructors(Class node, IndexedClass? indexedClass) {
final toRemove = <Initializer>[];
// Constructors cannot have initializers because initializers refer to
@@ -508,13 +501,13 @@
templateFfiFieldInitializer.withArguments(i.field.name.text),
i.fileOffset,
1,
- i.location.file);
+ i.location!.file);
}
}
}
// Remove initializers referring to fields to prevent cascading errors.
for (final Initializer i in toRemove) {
- final Constructor c = i.parent;
+ final c = i.parent as Constructor;
c.initializers.remove(i);
}
@@ -563,7 +556,7 @@
final dartType = _compoundMemberType(m);
// Nullable.
- NativeTypeCfe type;
+ NativeTypeCfe? type;
if (isArrayType(dartType)) {
final sizeAnnotations = _getArraySizeAnnotations(m).toList();
if (sizeAnnotations.length == 1) {
@@ -582,7 +575,7 @@
final nativeTypeAnnos = _getNativeTypeAnnotations(m).toList();
if (nativeTypeAnnos.length == 1) {
final clazz = nativeTypeAnnos.first;
- final nativeType = _getFieldType(clazz);
+ final nativeType = _getFieldType(clazz)!;
type = PrimitiveNativeTypeCfe(nativeType, clazz);
}
}
@@ -633,17 +626,18 @@
///
/// Returns the total size of the compound (for all ABIs).
void _replaceFields(
- Class node, IndexedClass indexedClass, CompoundData compoundData) {
+ Class node, IndexedClass? indexedClass, CompoundData compoundData) {
final compoundType = compoundData.compoundType as CompoundNativeTypeCfe;
final compoundLayout = compoundType.layout;
_annoteCompoundWithFields(node, compoundType.members, compoundData.packing);
if (compoundType.members.isEmpty) {
diagnosticReporter.report(
- templateFfiEmptyStruct.withArguments(node.superclass.name, node.name),
+ templateFfiEmptyStruct.withArguments(
+ node.superclass!.name, node.name),
node.fileOffset,
node.name.length,
- node.location.file);
+ node.location!.file);
}
final unalignedAccess = compoundData.packing != null;
@@ -651,9 +645,9 @@
int i = 0;
for (final compoundField in compoundData.compoundFields) {
NativeTypeCfe type = compoundField.type;
- Field field = compoundField.field;
- Procedure getter = compoundField.getter;
- Procedure setter = compoundField.setter;
+ Field? field = compoundField.field;
+ Procedure? getter = compoundField.getter;
+ Procedure? setter = compoundField.setter;
final fieldOffsets = compoundLayout
.map((Abi abi, CompoundLayout v) => MapEntry(abi, v.offsets[i]));
@@ -691,7 +685,7 @@
static const vmFfiStructFields = "vm:ffi:struct-fields";
// return value is nullable.
- InstanceConstant _compoundAnnotatedFields(Class node) {
+ InstanceConstant? _compoundAnnotatedFields(Class node) {
for (final annotation in node.annotations) {
if (annotation is ConstantExpression) {
final constant = annotation.constant;
@@ -699,7 +693,8 @@
constant.classNode == pragmaClass &&
constant.fieldValues[pragmaName.getterReference] ==
StringConstant(vmFfiStructFields)) {
- return constant.fieldValues[pragmaOptions.getterReference];
+ return constant.fieldValues[pragmaOptions.getterReference]
+ as InstanceConstant?;
}
}
}
@@ -724,20 +719,22 @@
/// Must only be called if all the depencies are already in the cache.
CompoundNativeTypeCfe _compoundAnnotatedNativeTypeCfe(Class compoundClass) {
- final layoutConstant = _compoundAnnotatedFields(compoundClass);
+ final layoutConstant = _compoundAnnotatedFields(compoundClass)!;
final fieldTypes = layoutConstant
.fieldValues[ffiStructLayoutTypesField.getterReference] as ListConstant;
final members = <NativeTypeCfe>[];
for (final fieldType in fieldTypes.entries) {
if (fieldType is TypeLiteralConstant) {
final dartType = fieldType.type;
- members.add(NativeTypeCfe(this, dartType));
+ members
+ .add(NativeTypeCfe(this, dartType, compoundCache: compoundCache));
} else if (fieldType is InstanceConstant) {
final singleElementConstant = fieldType
.fieldValues[ffiInlineArrayElementTypeField.getterReference]
as TypeLiteralConstant;
- final singleElementType =
- NativeTypeCfe(this, singleElementConstant.type);
+ final singleElementType = NativeTypeCfe(
+ this, singleElementConstant.type,
+ compoundCache: compoundCache);
final arrayLengthConstant =
fieldType.fieldValues[ffiInlineArrayLengthField.getterReference]
as IntConstant;
@@ -759,7 +756,7 @@
// packing is `int?`.
void _annoteCompoundWithFields(
- Class node, List<NativeTypeCfe> types, int packing) {
+ Class node, List<NativeTypeCfe> types, int? packing) {
List<Constant> constants =
types.map((t) => t.generateConstant(this)).toList();
@@ -778,7 +775,7 @@
}
void _generateMethodsForField(Class node, Field field, NativeTypeCfe type,
- Map<Abi, int> offsets, bool unalignedAccess, IndexedClass indexedClass) {
+ Map<Abi, int> offsets, bool unalignedAccess, IndexedClass? indexedClass) {
// TODO(johnniwinther): Avoid passing [indexedClass]. When compiling
// incrementally, [field] should already carry the references from
// [indexedClass].
@@ -798,7 +795,7 @@
node.addProcedure(getter);
if (!field.isFinal) {
- Reference setterReference =
+ Reference? setterReference =
indexedClass?.lookupSetterReference(field.name) ??
field.setterReference;
assert(setterReference == field.setterReference,
@@ -828,8 +825,8 @@
///
/// If sizes are not supplied still emits a field so that the use site
/// transformer can still rewrite to it.
- void _addSizeOfField(Class compound, IndexedClass indexedClass,
- [Map<Abi, int> sizes = null]) {
+ void _addSizeOfField(Class compound, IndexedClass? indexedClass,
+ [Map<Abi, int>? sizes = null]) {
if (sizes == null) {
sizes = Map.fromEntries(Abi.values.map((abi) => MapEntry(abi, 0)));
}
@@ -846,8 +843,8 @@
isStatic: true)
..fileOffset = compound.fileOffset
..isNonNullableByDefault = true
- ..addAnnotation(ConstantExpression(InstanceConstant(pragmaClass.reference,
- /*type_arguments=*/ [], {
+ ..addAnnotation(ConstantExpression(
+ InstanceConstant(pragmaClass.reference, /*type_arguments=*/ [], {
pragmaName.getterReference: StringConstant("vm:prefer-inline"),
pragmaOptions.getterReference: NullConstant(),
})));
@@ -855,7 +852,7 @@
compound.addProcedure(getter);
}
- NativeType _getFieldType(Class c) {
+ NativeType? _getFieldType(Class c) {
final fieldType = getType(c);
if (fieldType == NativeType.kVoid) {
@@ -924,10 +921,7 @@
class CompoundData {
final List<CompoundField> compoundFields;
-
- // Nullable.
- final int packing;
-
+ final int? packing;
final NativeTypeCfe compoundType;
CompoundData(this.compoundFields, this.packing, this.compoundType);
@@ -935,15 +929,9 @@
class CompoundField {
final NativeTypeCfe type;
-
- // Nullable.
- final Field field;
-
- // Nullable.
- final Procedure getter;
-
- // Nullable.
- final Procedure setter;
+ final Field? field;
+ final Procedure? getter;
+ final Procedure? setter;
CompoundField(this.type, this.field, this.getter, this.setter);
}
@@ -970,11 +958,11 @@
/// intimately to AST nodes such as [Class].
abstract class NativeTypeCfe {
factory NativeTypeCfe(FfiTransformer transformer, DartType dartType,
- {List<int> arrayDimensions,
+ {List<int>? arrayDimensions,
Map<Class, NativeTypeCfe> compoundCache = const {}}) {
if (transformer.isPrimitiveType(dartType)) {
final clazz = (dartType as InterfaceType).classNode;
- final nativeType = transformer.getType(clazz);
+ final nativeType = transformer.getType(clazz)!;
return PrimitiveNativeTypeCfe(nativeType, clazz);
}
if (transformer.isPointerType(dartType)) {
@@ -983,7 +971,7 @@
if (transformer.isCompoundSubtype(dartType)) {
final clazz = (dartType as InterfaceType).classNode;
if (compoundCache.containsKey(clazz)) {
- return compoundCache[clazz];
+ return compoundCache[clazz]!;
} else {
throw "Class '$clazz' not found in compoundCache.";
}
@@ -1090,8 +1078,8 @@
}
@override
- Map<Abi, int> get alignment => Map.fromEntries(Abi.values.map(
- (abi) => MapEntry(abi, nonSizeAlignment[abi][nativeType] ?? size[abi])));
+ Map<Abi, int> get alignment => Map.fromEntries(Abi.values.map((abi) =>
+ MapEntry(abi, nonSizeAlignment[abi]![nativeType] ?? size[abi]!)));
@override
Constant generateConstant(FfiTransformer transformer) =>
@@ -1103,8 +1091,8 @@
bool isUnaligned(Map<Abi, int> offsets) {
final alignments = alignment;
for (final abi in offsets.keys) {
- final offset = offsets[abi];
- final alignment = alignments[abi];
+ final offset = offsets[abi]!;
+ final alignment = alignments[abi]!;
if (offset % alignment != 0) {
return true;
}
@@ -1127,7 +1115,7 @@
ReturnStatement(StaticInvocation(
(unalignedAccess && isFloat
? transformer.loadUnalignedMethods
- : transformer.loadMethods)[nativeType],
+ : transformer.loadMethods)[nativeType]!,
Arguments([
transformer.getCompoundTypedDataBaseField(
ThisExpression(), fileOffset),
@@ -1151,7 +1139,7 @@
ReturnStatement(StaticInvocation(
(unalignedAccess && isFloat
? transformer.storeUnalignedMethods
- : transformer.storeMethods)[nativeType],
+ : transformer.storeMethods)[nativeType]!,
Arguments([
transformer.getCompoundTypedDataBaseField(
ThisExpression(), fileOffset),
@@ -1172,7 +1160,7 @@
Constant generateConstant(FfiTransformer transformer) => TypeLiteralConstant(
InterfaceType(transformer.pointerClass, Nullability.nonNullable, [
InterfaceType(
- transformer.pointerClass.superclass, Nullability.nonNullable)
+ transformer.pointerClass.superclass!, Nullability.nonNullable)
]));
/// Sample output for `Pointer<Int8> get x =>`:
@@ -1191,7 +1179,7 @@
transformer.fromAddressInternal,
Arguments([
StaticInvocation(
- transformer.loadMethods[NativeType.kIntptr],
+ transformer.loadMethods[NativeType.kIntptr]!,
Arguments([
transformer.getCompoundTypedDataBaseField(
ThisExpression(), fileOffset),
@@ -1217,7 +1205,7 @@
VariableDeclaration argument,
FfiTransformer transformer) =>
ReturnStatement(StaticInvocation(
- transformer.storeMethods[NativeType.kIntptr],
+ transformer.storeMethods[NativeType.kIntptr]!,
Arguments([
transformer.getCompoundTypedDataBaseField(
ThisExpression(), fileOffset),
@@ -1308,10 +1296,10 @@
class StructNativeTypeCfe extends CompoundNativeTypeCfe {
// Nullable int.
- final int packing;
+ final int? packing;
factory StructNativeTypeCfe(Class clazz, List<NativeTypeCfe> members,
- {int packing}) {
+ {int? packing}) {
final layout = Map.fromEntries(Abi.values
.map((abi) => MapEntry(abi, _calculateLayout(members, packing, abi))));
return StructNativeTypeCfe._(clazz, members, packing, layout);
@@ -1324,13 +1312,13 @@
// Keep consistent with runtime/vm/compiler/ffi/native_type.cc
// NativeStructType::FromNativeTypes.
static CompoundLayout _calculateLayout(
- List<NativeTypeCfe> types, int packing, Abi abi) {
+ List<NativeTypeCfe> types, int? packing, Abi abi) {
int offset = 0;
final offsets = <int>[];
int structAlignment = 1;
for (int i = 0; i < types.length; i++) {
- final int size = types[i].size[abi];
- int alignment = types[i].alignment[abi];
+ final int size = types[i].size[abi]!;
+ int alignment = types[i].alignment[abi]!;
if (packing != null && packing < alignment) {
alignment = packing;
}
@@ -1363,8 +1351,8 @@
int unionSize = 1;
int unionAlignment = 1;
for (int i = 0; i < types.length; i++) {
- final int size = types[i].size[abi];
- int alignment = types[i].alignment[abi];
+ final int size = types[i].size[abi]!;
+ int alignment = types[i].alignment[abi]!;
unionSize = math.max(unionSize, size);
unionAlignment = math.max(unionAlignment, alignment);
}
diff --git a/pkg/vm/lib/transformations/ffi_native.dart b/pkg/vm/lib/transformations/ffi_native.dart
index f3fdb03..e666652 100644
--- a/pkg/vm/lib/transformations/ffi_native.dart
+++ b/pkg/vm/lib/transformations/ffi_native.dart
@@ -2,23 +2,28 @@
// 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.
-// @dart=2.12
-
import 'package:kernel/ast.dart';
import 'package:kernel/library_index.dart' show LibraryIndex;
import 'package:kernel/reference_from_index.dart'
show IndexedLibrary, ReferenceFromIndex;
+import 'package:kernel/target/targets.dart' show DiagnosticReporter;
+import 'package:front_end/src/api_unstable/vm.dart'
+ show messageFfiNativeAnnotationMustAnnotateStatic;
/// Transform @FfiNative annotated functions into FFI native function pointer
/// functions.
-void transformLibraries(Component component, List<Library> libraries,
- ReferenceFromIndex referenceFromIndex) {
+void transformLibraries(
+ Component component,
+ List<Library> libraries,
+ DiagnosticReporter diagnosticReporter,
+ ReferenceFromIndex? referenceFromIndex) {
final index = LibraryIndex(component, ['dart:ffi']);
// Skip if dart:ffi isn't loaded (e.g. during incremental compile).
if (index.tryGetClass('dart:ffi', 'FfiNative') == null) {
return;
}
- final transformer = FfiNativeTransformer(index, referenceFromIndex);
+ final transformer =
+ FfiNativeTransformer(index, diagnosticReporter, referenceFromIndex);
libraries.forEach(transformer.visitLibrary);
}
@@ -26,19 +31,24 @@
Library? currentLibrary;
IndexedLibrary? currentLibraryIndex;
+ final DiagnosticReporter diagnosticReporter;
final ReferenceFromIndex? referenceFromIndex;
final Class ffiNativeClass;
final Class nativeFunctionClass;
final Field ffiNativeNameField;
+ final Field ffiNativeIsLeafField;
final Field resolverField;
final Procedure asFunctionProcedure;
final Procedure fromAddressInternal;
- FfiNativeTransformer(LibraryIndex index, this.referenceFromIndex)
+ FfiNativeTransformer(
+ LibraryIndex index, this.diagnosticReporter, this.referenceFromIndex)
: ffiNativeClass = index.getClass('dart:ffi', 'FfiNative'),
nativeFunctionClass = index.getClass('dart:ffi', 'NativeFunction'),
ffiNativeNameField =
index.getField('dart:ffi', 'FfiNative', 'nativeName'),
+ ffiNativeIsLeafField =
+ index.getField('dart:ffi', 'FfiNative', 'isLeaf'),
resolverField = index.getTopLevelField('dart:ffi', '_ffi_resolver'),
asFunctionProcedure = index.getProcedure(
'dart:ffi', 'NativeFunctionPointer', 'asFunction'),
@@ -50,10 +60,9 @@
assert(currentLibrary == null);
currentLibrary = node;
currentLibraryIndex = referenceFromIndex?.lookupLibrary(node);
- // We only transform top-level, external procedures:
- transformList(node.procedures, node);
+ final result = super.visitLibrary(node);
currentLibrary = null;
- return node;
+ return result;
}
InstanceConstant? _tryGetFfiNativeAnnotation(Member node) {
@@ -71,21 +80,23 @@
}
// Transform:
- // @FfiNative<Double Function(Double)>('Math_sqrt')
- // external double _sqrt(double x);
+ // @FfiNative<Double Function(Double)>('Math_sqrt', isLeaf:true)
+ // external double _square_root(double x);
//
// Into:
- // final _@FfiNative_Math_sqrt =
+ // final _@FfiNative__square_root =
// Pointer<NativeFunction<Double Function(Double)>>
// .fromAddress(_ffi_resolver('dart:math', 'Math_sqrt'))
- // .asFunction<double Function(double)>();
- // double _sqrt(double x) => _@FfiNative_Math_sqrt(x);
+ // .asFunction<double Function(double)>(isLeaf:true);
+ // double _square_root(double x) => _@FfiNative__square_root(x);
Statement transformFfiNative(
Procedure node, InstanceConstant annotationConst) {
assert(currentLibrary != null);
final params = node.function.positionalParameters;
final functionName = annotationConst
.fieldValues[ffiNativeNameField.getterReference] as StringConstant;
+ final isLeaf = annotationConst
+ .fieldValues[ffiNativeIsLeafField.getterReference] as BoolConstant;
// double Function(double)
final DartType dartType =
@@ -115,26 +126,30 @@
Arguments([resolverInvocation], types: [nativeInterfaceType]));
// NativeFunctionPointer.asFunction
- // <Double Function(Double), double Function(double)>(...)
- final asFunctionInvocation = StaticInvocation(asFunctionProcedure,
- Arguments([fromAddressInvocation], types: [nativeType, dartType]));
+ // <Double Function(Double), double Function(double)>(..., isLeaf:true)
+ final asFunctionInvocation = StaticInvocation(
+ asFunctionProcedure,
+ Arguments([fromAddressInvocation],
+ types: [nativeType, dartType],
+ named: [NamedExpression("isLeaf", BoolLiteral(isLeaf.value))]));
- // final _@FfiNative_Math_sqrt = ...
- final fieldName = Name('_@FfiNative_${functionName.value}', currentLibrary);
+ // final _@FfiNative__square_root = ...
+ final fieldName = Name('_@FfiNative_${node.name.text}', currentLibrary);
final funcPtrField = Field.immutable(fieldName,
type: dartType,
initializer: asFunctionInvocation,
isStatic: true,
isFinal: true,
fileUri: currentLibrary!.fileUri,
- getterReference: currentLibraryIndex?.lookupGetterReference(fieldName));
+ getterReference: currentLibraryIndex?.lookupGetterReference(fieldName))
+ ..fileOffset = node.fileOffset;
currentLibrary!.addField(funcPtrField);
- // _@FfiNative_Math_sqrt(x)
+ // _@FfiNative__square_root(x)
final callFuncPtrInvocation = FunctionInvocation(
FunctionAccessKind.FunctionType,
StaticGet(funcPtrField),
- Arguments(params.map((p) => VariableGet(p)).toList()),
+ Arguments(params.map<Expression>((p) => VariableGet(p)).toList()),
functionType: dartType as FunctionType);
return ReturnStatement(callFuncPtrInvocation);
@@ -144,7 +159,7 @@
visitProcedure(Procedure node) {
// Only transform functions that are external and have FfiNative annotation:
// @FfiNative<Double Function(Double)>('Math_sqrt')
- // external double _sqrt(double x);
+ // external double _square_root(double x);
if (!node.isExternal) {
return node;
}
@@ -153,6 +168,11 @@
return node;
}
+ if (!node.isStatic) {
+ diagnosticReporter.report(messageFfiNativeAnnotationMustAnnotateStatic,
+ node.fileOffset, 1, node.location!.file);
+ }
+
node.isExternal = false;
node.function.body = transformFfiNative(node, ffiNativeAnnotation)
..parent = node.function;
diff --git a/pkg/vm/lib/transformations/ffi_use_sites.dart b/pkg/vm/lib/transformations/ffi_use_sites.dart
index 4600fde..49281ed 100644
--- a/pkg/vm/lib/transformations/ffi_use_sites.dart
+++ b/pkg/vm/lib/transformations/ffi_use_sites.dart
@@ -2,8 +2,6 @@
// 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.
-library vm.transformations.ffi_use_sites;
-
import 'package:front_end/src/api_unstable/vm.dart'
show
messageFfiExceptionalReturnNull,
@@ -44,7 +42,7 @@
ClassHierarchy hierarchy,
List<Library> libraries,
DiagnosticReporter diagnosticReporter,
- ReferenceFromIndex referenceFromIndex) {
+ ReferenceFromIndex? referenceFromIndex) {
final index = new LibraryIndex(
component, ["dart:ffi", "dart:_internal", "dart:typed_data"]);
if (!index.containsLibrary("dart:ffi")) {
@@ -64,7 +62,7 @@
/// Checks and replaces calls to dart:ffi compound fields and methods.
class _FfiUseSiteTransformer extends FfiTransformer {
- StaticTypeContext _staticTypeContext;
+ StaticTypeContext? _staticTypeContext;
bool get isFfiLibrary => currentLibrary == ffiLibrary;
@@ -77,7 +75,7 @@
CoreTypes coreTypes,
ClassHierarchy hierarchy,
DiagnosticReporter diagnosticReporter,
- ReferenceFromIndex referenceFromIndex)
+ ReferenceFromIndex? referenceFromIndex)
: super(index, coreTypes, hierarchy, diagnosticReporter,
referenceFromIndex) {}
@@ -174,7 +172,7 @@
_ensureNativeTypeValid(nativeType, node, allowCompounds: true);
if (nativeType is InterfaceType) {
- Expression inlineSizeOf = _inlineSizeOf(nativeType);
+ Expression? inlineSizeOf = _inlineSizeOf(nativeType);
if (inlineSizeOf != null) {
return inlineSizeOf;
}
@@ -204,7 +202,7 @@
return replacement;
} else if (target == asFunctionMethod) {
final dartType = node.arguments.types[1];
- final DartType nativeType = InterfaceType(
+ final InterfaceType nativeType = InterfaceType(
nativeFunctionClass, Nullability.legacy, [node.arguments.types[0]]);
_ensureNativeTypeValid(nativeType, node);
@@ -212,10 +210,9 @@
_ensureIsLeafIsConst(node);
_ensureLeafCallDoesNotUseHandles(nativeType, node);
- final DartType nativeSignature =
- (nativeType as InterfaceType).typeArguments[0];
+ final DartType nativeSignature = nativeType.typeArguments[0];
- bool isLeaf = _getIsLeafBoolean(node);
+ bool? isLeaf = _getIsLeafBoolean(node);
if (isLeaf == null) {
isLeaf = false;
}
@@ -241,7 +238,7 @@
final DartType nativeType = InterfaceType(
nativeFunctionClass, Nullability.legacy, [node.arguments.types[0]]);
final Expression func = node.arguments.positional[0];
- final DartType dartType = func.getStaticType(_staticTypeContext);
+ final DartType dartType = func.getStaticType(_staticTypeContext!);
_ensureIsStaticFunction(func);
@@ -255,7 +252,7 @@
((node.arguments.types[0] as FunctionType).returnType
as InterfaceType)
.classNode;
- final NativeType expectedReturn = getType(expectedReturnClass);
+ final NativeType? expectedReturn = getType(expectedReturnClass);
if (expectedReturn == NativeType.kVoid ||
expectedReturn == NativeType.kPointer ||
@@ -307,7 +304,7 @@
}
final DartType returnType =
- exceptionalReturn.getStaticType(_staticTypeContext);
+ exceptionalReturn.getStaticType(_staticTypeContext!);
if (!env.isSubtypeOf(returnType, funcType.returnType,
SubtypeCheckMode.ignoringNullabilities)) {
@@ -337,7 +334,7 @@
// Inline the body to get rid of a generic invocation of sizeOf.
// TODO(http://dartbug.com/39964): Add `allignmentOf<T>()` call.
- Expression sizeInBytes = _inlineSizeOf(nativeType);
+ Expression? sizeInBytes = _inlineSizeOf(nativeType as InterfaceType);
if (sizeInBytes != null) {
if (node.arguments.positional.length == 2) {
sizeInBytes = multiply(node.arguments.positional[1], sizeInBytes);
@@ -399,9 +396,9 @@
.distinct()
.fold(nestedExpression, _invokeCompoundConstructor);
- Expression _inlineSizeOf(InterfaceType nativeType) {
+ Expression? _inlineSizeOf(InterfaceType nativeType) {
final Class nativeClass = nativeType.classNode;
- final NativeType nt = getType(nativeClass);
+ final NativeType? nt = getType(nativeClass);
if (nt == null) {
// User-defined compounds.
final Procedure sizeOfGetter = nativeClass.procedures
@@ -455,7 +452,7 @@
.substituteType(lookupFunctionType.withoutTypeParameters)
as FunctionType);
- bool isLeaf = _getIsLeafBoolean(node);
+ bool? isLeaf = _getIsLeafBoolean(node);
if (isLeaf == null) {
isLeaf = false;
}
@@ -516,7 +513,7 @@
pointer,
offsetByMethod.name,
Arguments([
- multiply(node.arguments.positional[1], _inlineSizeOf(dartType))
+ multiply(node.arguments.positional[1], _inlineSizeOf(dartType)!)
]),
interfaceTarget: offsetByMethod,
functionType:
@@ -534,8 +531,8 @@
final typedDataBasePrime = typedDataBaseOffset(
getArrayTypedDataBaseField(NullCheck(node.arguments.positional[0])),
- multiply(node.arguments.positional[1], _inlineSizeOf(dartType)),
- _inlineSizeOf(dartType),
+ multiply(node.arguments.positional[1], _inlineSizeOf(dartType)!),
+ _inlineSizeOf(dartType)!,
dartType,
node.fileOffset);
@@ -598,7 +595,7 @@
type: coreTypes.intNonNullableRawType)
..fileOffset = node.fileOffset;
final singleElementSizeVar = VariableDeclaration("#singleElementSize",
- initializer: _inlineSizeOf(elementType),
+ initializer: _inlineSizeOf(elementType as InterfaceType),
type: coreTypes.intNonNullableRawType)
..fileOffset = node.fileOffset;
final elementSizeVar = VariableDeclaration("#elementSize",
@@ -682,12 +679,12 @@
try {
if (target == elementAtMethod) {
final DartType pointerType =
- node.receiver.getStaticType(_staticTypeContext);
- final DartType nativeType = _pointerTypeGetTypeArg(pointerType);
+ node.receiver.getStaticType(_staticTypeContext!);
+ final DartType nativeType = _pointerTypeGetTypeArg(pointerType)!;
_ensureNativeTypeValid(nativeType, node, allowCompounds: true);
- Expression inlineSizeOf = _inlineSizeOf(nativeType);
+ Expression? inlineSizeOf = _inlineSizeOf(nativeType as InterfaceType);
if (inlineSizeOf != null) {
// Generates `receiver.offsetBy(inlineSizeOfExpression)`.
return InstanceInvocation(
@@ -712,7 +709,7 @@
return node;
}
- DartType _pointerTypeGetTypeArg(DartType pointerType) {
+ DartType? _pointerTypeGetTypeArg(DartType pointerType) {
return pointerType is InterfaceType ? pointerType.typeArguments[0] : null;
}
@@ -722,7 +719,7 @@
final DartType correspondingDartType = convertNativeTypeToDartType(
nativeType,
allowCompounds: true,
- allowHandle: allowHandle);
+ allowHandle: allowHandle)!;
if (dartType == correspondingDartType) return;
if (env.isSubtypeOf(correspondingDartType, dartType,
SubtypeCheckMode.ignoringNullabilities)) {
@@ -785,7 +782,7 @@
/// Returns the class that should not be implemented or extended.
///
/// If the superclass is not sealed, returns `null`.
- Class _extendsOrImplementsSealedClass(Class klass) {
+ Class? _extendsOrImplementsSealedClass(Class klass) {
// Classes in dart:ffi themselves can extend FFI classes.
if (klass == arrayClass ||
klass == arraySizeClass ||
@@ -822,7 +819,7 @@
}
void _ensureNotExtendsOrImplementsSealedClass(Class klass) {
- final Class extended = _extendsOrImplementsSealedClass(klass);
+ final Class? extended = _extendsOrImplementsSealedClass(klass);
if (extended != null) {
diagnosticReporter.report(
templateFfiExtendsOrImplementsSealedClass
@@ -838,7 +835,7 @@
// - `true` if leaf
// - `false` if not leaf
// - `null` if the expression is not valid (e.g. non-const bool, null)
- bool _getIsLeafBoolean(StaticInvocation node) {
+ bool? _getIsLeafBoolean(StaticInvocation node) {
for (final named in node.arguments.named) {
if (named.name == 'isLeaf') {
final expr = named.value;
@@ -891,8 +888,8 @@
}
}
// Check if any of the argument types are Handle.
- for (InterfaceType param in functionType.positionalParameters) {
- if (param.classNode == handleClass) {
+ for (DartType param in functionType.positionalParameters) {
+ if ((param as InterfaceType).classNode == handleClass) {
diagnosticReporter.report(messageFfiLeafCallMustNotTakeHandle,
node.fileOffset, 1, node.location?.file);
}
diff --git a/pkg/vm/lib/transformations/late_var_init_transformer.dart b/pkg/vm/lib/transformations/late_var_init_transformer.dart
index 7d245f1..48fd416 100644
--- a/pkg/vm/lib/transformations/late_var_init_transformer.dart
+++ b/pkg/vm/lib/transformations/late_var_init_transformer.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart=2.12
-
import 'package:kernel/ast.dart';
/// Wraps the initializers of late local variables in closures.
diff --git a/pkg/vm/lib/transformations/list_literals_lowering.dart b/pkg/vm/lib/transformations/list_literals_lowering.dart
index e6b5e13..1acb42f 100644
--- a/pkg/vm/lib/transformations/list_literals_lowering.dart
+++ b/pkg/vm/lib/transformations/list_literals_lowering.dart
@@ -22,23 +22,24 @@
final Procedure _defaultFactory;
// Specialized _GrowableList._literalN(e1, ..., eN) factories.
- final List<Procedure> _specializedFactories =
- List<Procedure>.filled(numSpecializedFactories, null);
+ final List<Procedure?> _specializedFactories =
+ List<Procedure?>.filled(numSpecializedFactories, null);
ListLiteralsLowering(this.coreTypes)
: _defaultFactory =
- coreTypes.index.getMember('dart:core', '_GrowableList', '');
+ coreTypes.index.getProcedure('dart:core', '_GrowableList', '');
Procedure getSpecializedFactory(int length) =>
(_specializedFactories[length - 1] ??= coreTypes.index
- .getMember('dart:core', '_GrowableList', '_literal$length'));
+ .getProcedure('dart:core', '_GrowableList', '_literal$length'));
Expression transformListLiteral(ListLiteral node) {
if (node.isConst) {
throw 'Unexpected constant ListLiteral node'
' (such nodes should be converted to ConstantExpression): $node';
}
- if (node.parent is Field && isRedirectingFactoryField(node.parent)) {
+ final parent = node.parent;
+ if (parent is Field && isRedirectingFactoryField(parent)) {
// Do not transform list literals which are used to represent
// redirecting factories.
return node;
diff --git a/pkg/vm/lib/transformations/lowering.dart b/pkg/vm/lib/transformations/lowering.dart
index 4b320ad..d776f33 100644
--- a/pkg/vm/lib/transformations/lowering.dart
+++ b/pkg/vm/lib/transformations/lowering.dart
@@ -37,8 +37,8 @@
final FactorySpecializer factorySpecializer;
final ListLiteralsLowering listLiteralsLowering;
- Member _currentMember;
- StaticTypeContext _cachedStaticTypeContext;
+ Member? _currentMember;
+ StaticTypeContext? _cachedStaticTypeContext;
_Lowering(CoreTypes coreTypes, ClassHierarchy hierarchy, this.nullSafety)
: env = TypeEnvironment(coreTypes, hierarchy),
@@ -47,7 +47,7 @@
listLiteralsLowering = ListLiteralsLowering(coreTypes);
StaticTypeContext get _staticTypeContext =>
- _cachedStaticTypeContext ??= StaticTypeContext(_currentMember, env);
+ _cachedStaticTypeContext ??= StaticTypeContext(_currentMember!, env);
@override
defaultMember(Member node) {
diff --git a/pkg/vm/lib/transformations/mixin_deduplication.dart b/pkg/vm/lib/transformations/mixin_deduplication.dart
index ba65266..61f008b 100644
--- a/pkg/vm/lib/transformations/mixin_deduplication.dart
+++ b/pkg/vm/lib/transformations/mixin_deduplication.dart
@@ -2,10 +2,6 @@
// 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.
-// @dart=2.12
-
-library vm.transformations.mixin_deduplication;
-
import 'package:kernel/ast.dart';
/// De-duplication of identical mixin applications.
diff --git a/pkg/vm/lib/transformations/no_dynamic_invocations_annotator.dart b/pkg/vm/lib/transformations/no_dynamic_invocations_annotator.dart
index 5e9600e..75b566f 100644
--- a/pkg/vm/lib/transformations/no_dynamic_invocations_annotator.dart
+++ b/pkg/vm/lib/transformations/no_dynamic_invocations_annotator.dart
@@ -46,7 +46,6 @@
case Action.invoke:
return '${target}';
}
- return '?';
}
}
diff --git a/pkg/vm/lib/transformations/obfuscation_prohibitions_annotator.dart b/pkg/vm/lib/transformations/obfuscation_prohibitions_annotator.dart
index 98592ef..b4eeab7 100644
--- a/pkg/vm/lib/transformations/obfuscation_prohibitions_annotator.dart
+++ b/pkg/vm/lib/transformations/obfuscation_prohibitions_annotator.dart
@@ -28,7 +28,7 @@
void _addIfEntryPoint(
List<Expression> annotations, String name, TreeNode node) {
for (var ann in annotations) {
- ParsedPragma pragma = parser.parsePragma(ann);
+ ParsedPragma? pragma = parser.parsePragma(ann);
if (pragma is ParsedEntryPointPragma) {
metadata.protectedNames.add(name);
if (node is Field) {
diff --git a/pkg/vm/lib/transformations/pragma.dart b/pkg/vm/lib/transformations/pragma.dart
index cde363a..dfac713 100644
--- a/pkg/vm/lib/transformations/pragma.dart
+++ b/pkg/vm/lib/transformations/pragma.dart
@@ -2,8 +2,6 @@
// 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.
-library vm.transformations.pragma;
-
import 'package:kernel/ast.dart';
import 'package:kernel/core_types.dart' show CoreTypes;
@@ -54,7 +52,7 @@
abstract class PragmaAnnotationParser {
/// May return 'null' if the annotation does not represent a recognized
/// @pragma.
- ParsedPragma parsePragma(Expression annotation);
+ ParsedPragma? parsePragma(Expression annotation);
}
class ConstantPragmaAnnotationParser extends PragmaAnnotationParser {
@@ -62,8 +60,8 @@
ConstantPragmaAnnotationParser(this.coreTypes);
- ParsedPragma parsePragma(Expression annotation) {
- InstanceConstant pragmaConstant;
+ ParsedPragma? parsePragma(Expression annotation) {
+ InstanceConstant? pragmaConstant;
if (annotation is ConstantExpression) {
Constant constant = annotation.constant;
if (constant is InstanceConstant) {
@@ -79,7 +77,7 @@
if (pragmaConstant == null) return null;
String pragmaName;
- Constant name =
+ Constant? name =
pragmaConstant.fieldValues[coreTypes.pragmaName.getterReference];
if (name is StringConstant) {
pragmaName = name.value;
@@ -88,12 +86,11 @@
}
Constant options =
- pragmaConstant.fieldValues[coreTypes.pragmaOptions.getterReference];
- assert(options != null);
+ pragmaConstant.fieldValues[coreTypes.pragmaOptions.getterReference]!;
switch (pragmaName) {
case kEntryPointPragmaName:
- PragmaEntryPointType type;
+ PragmaEntryPointType? type;
if (options is NullConstant) {
type = PragmaEntryPointType.Default;
} else if (options is BoolConstant && options.value == true) {
@@ -113,7 +110,6 @@
}
return type != null ? new ParsedEntryPointPragma(type) : null;
case kExactResultTypePragmaName:
- if (options == null) return null;
if (options is TypeLiteralConstant) {
return new ParsedResultTypeByTypePragma(options.type, false);
} else if (options is StringConstant) {
@@ -132,7 +128,7 @@
case kNonNullableResultType:
return new ParsedNonNullableResultType();
case kRecognizedPragmaName:
- PragmaRecognizedType type;
+ PragmaRecognizedType? type;
if (options is StringConstant) {
if (options.value == "asm-intrinsic") {
type = PragmaRecognizedType.AsmIntrinsic;
diff --git a/pkg/vm/lib/transformations/specializer/factory_specializer.dart b/pkg/vm/lib/transformations/specializer/factory_specializer.dart
index 7475638..b86c3e6 100644
--- a/pkg/vm/lib/transformations/specializer/factory_specializer.dart
+++ b/pkg/vm/lib/transformations/specializer/factory_specializer.dart
@@ -2,10 +2,6 @@
// 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.
-// @dart=2.12
-
-library vm.transformations.specializer.factory_specializer;
-
import 'package:kernel/kernel.dart';
import 'package:kernel/core_types.dart';
import 'package:vm/transformations/specializer/list_factory_specializer.dart';
diff --git a/pkg/vm/lib/transformations/specializer/list_factory_specializer.dart b/pkg/vm/lib/transformations/specializer/list_factory_specializer.dart
index 248c192..1a3f10f 100644
--- a/pkg/vm/lib/transformations/specializer/list_factory_specializer.dart
+++ b/pkg/vm/lib/transformations/specializer/list_factory_specializer.dart
@@ -2,10 +2,6 @@
// 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.
-// @dart=2.12
-
-library vm.transformations.specializer.list_factory_specializer;
-
import 'package:kernel/ast.dart';
import 'package:kernel/core_types.dart' show CoreTypes;
import 'package:vm/transformations/specializer/factory_specializer.dart';
diff --git a/pkg/vm/lib/transformations/specializer/map_factory_specializer.dart b/pkg/vm/lib/transformations/specializer/map_factory_specializer.dart
index 8a01984..55f9d52 100644
--- a/pkg/vm/lib/transformations/specializer/map_factory_specializer.dart
+++ b/pkg/vm/lib/transformations/specializer/map_factory_specializer.dart
@@ -2,10 +2,6 @@
// 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.
-// @dart=2.12
-
-library vm.transformations.specializer.map_factory_specializer;
-
import 'package:kernel/ast.dart';
import 'package:kernel/core_types.dart';
import 'dart:core';
diff --git a/pkg/vm/lib/transformations/specializer/set_factory_specializer.dart b/pkg/vm/lib/transformations/specializer/set_factory_specializer.dart
index a508435..2479e3d 100644
--- a/pkg/vm/lib/transformations/specializer/set_factory_specializer.dart
+++ b/pkg/vm/lib/transformations/specializer/set_factory_specializer.dart
@@ -2,10 +2,6 @@
// 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.
-// @dart=2.12
-
-library vm.transformations.specializer.set_factory_specializer;
-
import 'package:kernel/ast.dart';
import 'package:kernel/core_types.dart' show CoreTypes;
diff --git a/pkg/vm/lib/transformations/to_string_transformer.dart b/pkg/vm/lib/transformations/to_string_transformer.dart
index 10e7575..0cd1b5f 100644
--- a/pkg/vm/lib/transformations/to_string_transformer.dart
+++ b/pkg/vm/lib/transformations/to_string_transformer.dart
@@ -13,7 +13,7 @@
/// `super.toString()`.
class ToStringVisitor extends RecursiveVisitor {
/// The [packageUris] must not be null.
- ToStringVisitor(this._packageUris) : assert(_packageUris != null);
+ ToStringVisitor(this._packageUris);
/// A set of package URIs to apply this transformer to, e.g. 'dart:ui' and
/// 'package:flutter/foundation.dart'.
@@ -42,7 +42,7 @@
if (className == 'pragma' && libraryUri == 'dart:core') {
for (var fieldRef in constant.fieldValues.keys) {
if (fieldRef.asField.name.text == 'name') {
- Constant name = constant.fieldValues[fieldRef];
+ Constant? name = constant.fieldValues[fieldRef];
return name is StringConstant &&
name.value == 'flutter:keep-to-string';
}
@@ -57,13 +57,12 @@
void visitProcedure(Procedure node) {
if (node.name.text == 'toString' &&
node.enclosingClass != null &&
- node.enclosingLibrary != null &&
!node.isStatic &&
!node.isAbstract &&
- !node.enclosingClass.isEnum &&
+ !node.enclosingClass!.isEnum &&
_isInTargetPackage(node) &&
!_hasKeepAnnotation(node)) {
- node.function.body.replaceWith(
+ node.function.body!.replaceWith(
ReturnStatement(
SuperMethodInvocation(
node.name,
diff --git a/pkg/vm/lib/transformations/type_flow/analysis.dart b/pkg/vm/lib/transformations/type_flow/analysis.dart
index 502fe14..75eff47 100644
--- a/pkg/vm/lib/transformations/type_flow/analysis.dart
+++ b/pkg/vm/lib/transformations/type_flow/analysis.dart
@@ -3,7 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
/// Global type flow analysis.
-library kernel.transformations.analysis;
import 'dart:collection';
import 'dart:core' hide Type;
@@ -49,24 +48,28 @@
/// Maintains set of dependent invocations.
class _DependencyTracker {
- Set<_Invocation> _dependentInvocations;
+ Set<_Invocation>? _dependentInvocations;
void addDependentInvocation(_Invocation invocation) {
if (!identical(invocation, this)) {
- _dependentInvocations ??= new Set<_Invocation>();
- _dependentInvocations.add(invocation);
+ var dependentInvocations = _dependentInvocations;
+ if (dependentInvocations == null) {
+ _dependentInvocations = dependentInvocations = Set<_Invocation>();
+ }
+ dependentInvocations.add(invocation);
}
}
void invalidateDependentInvocations(_WorkList workList) {
- if (_dependentInvocations != null) {
+ final dependentInvocations = _dependentInvocations;
+ if (dependentInvocations != null) {
if (kPrintTrace) {
tracePrint(' - CHANGED: $this');
- for (var di in _dependentInvocations) {
+ for (var di in dependentInvocations) {
tracePrint(' - invalidating $di');
}
}
- _dependentInvocations.forEach(workList.invalidateInvocation);
+ dependentInvocations.forEach(workList.invalidateInvocation);
}
}
}
@@ -81,12 +84,12 @@
final Selector selector;
final Args<Type> args;
- Type result;
+ Type? result;
/// Result of the invocation calculated before invocation was invalidated.
/// Used to check if the re-analysis of the invocation yields the same
/// result or not (to avoid invalidation of callers if result hasn't changed).
- Type invalidatedResult;
+ Type? invalidatedResult;
/// Number of times result of this invocation was invalidated.
int invalidationCounter = 0;
@@ -106,7 +109,7 @@
/// Returns result of this invocation if its available without
/// further analysis, or `null` if it's not available.
/// Used for recursive calls while this invocation is being processed.
- Type get resultForRecursiveInvocation => result;
+ Type? get resultForRecursiveInvocation => result;
/// Use [type] as a current computed result of this invocation.
/// If this invocation was invalidated, and the invalidated result is
@@ -114,7 +117,6 @@
/// Result type may be saturated if this invocation was invalidated
/// too many times.
void setResult(TypeFlowAnalysis typeFlowAnalysis, Type type) {
- assert(type != null);
result = type;
if (invalidatedResult != null) {
@@ -130,8 +132,8 @@
// the analysis, result is saturated after invocation is invalidated
// at least [_Invocation.invalidationLimit] times.
if (invalidationCounter > _Invocation.invalidationLimit) {
- result =
- result.union(invalidatedResult, typeFlowAnalysis.hierarchyCache);
+ result = result!
+ .union(invalidatedResult!, typeFlowAnalysis.hierarchyCache);
}
}
invalidatedResult = null;
@@ -190,11 +192,12 @@
// they could fail bounds checks.
//
// TODO(sjindel): Use [TypeCheck] to avoid bounds checks.
- if (selector.member.function != null) {
- typeChecksNeeded = selector.member.function.typeParameters
- .any((t) => t.isGenericCovariantImpl);
+ final function = selector.member.function;
+ if (function != null) {
+ typeChecksNeeded =
+ function.typeParameters.any((t) => t.isGenericCovariantImpl);
} else {
- Field field = selector.member;
+ Field field = selector.member as Field;
if (selector.callKind == CallKind.PropertySet) {
// TODO(dartbug.com/40615): Use TFA results to improve this criterion.
typeChecksNeeded = field.isGenericCovariantImpl;
@@ -275,13 +278,10 @@
fieldValue.isInitialized = true;
return const EmptyType();
}
-
- // Make dartanalyzer happy.
- throw 'Unexpected call kind ${selector.callKind}';
}
Type _processFunction(TypeFlowAnalysis typeFlowAnalysis) {
- final Member member = selector.member;
+ final Member member = selector.member!;
if (selector.memberAgreesToCallKind(member)) {
if (_argumentsValid()) {
final summary = typeFlowAnalysis.getSummary(member);
@@ -324,13 +324,12 @@
}
bool _argumentsValid() {
- final function = selector.member.function;
- assert(function != null);
-
+ final member = selector.member!;
+ final function = member.function!;
final int positionalArguments = args.positionalCount;
- final int firstParamIndex = numTypeParams(selector.member) +
- (hasReceiverArg(selector.member) ? 1 : 0);
+ final int firstParamIndex =
+ numTypeParams(member) + (hasReceiverArg(member) ? 1 : 0);
final int requiredParameters =
firstParamIndex + function.requiredParameterCount;
if (positionalArguments < requiredParameters) {
@@ -359,9 +358,9 @@
class _DispatchableInvocation extends _Invocation {
bool _isPolymorphic = false;
- Set<Call> _callSites; // Populated only if not polymorphic.
- Member _monomorphicTarget;
- _DirectInvocation _monomorphicDirectInvocation;
+ Set<Call>? _callSites; // Populated only if not polymorphic.
+ Member? _monomorphicTarget;
+ _DirectInvocation? _monomorphicDirectInvocation;
@override
set typeChecksNeeded(bool value) {
@@ -432,7 +431,8 @@
if (!_isPolymorphic) {
assert(target == _monomorphicTarget);
- _monomorphicDirectInvocation = directInvocation;
+ _monomorphicDirectInvocation =
+ directInvocation as _DirectInvocation;
}
type = typeFlowAnalysis.workList.processInvocation(directInvocation);
@@ -484,13 +484,13 @@
final bool isNullableReceiver = receiver is NullableType;
if (isNullableReceiver) {
- receiver = (receiver as NullableType).baseType;
+ receiver = receiver.baseType;
assert(receiver is! NullableType);
}
if (selector is InterfaceSelector) {
final staticReceiverType = new ConeType(typeFlowAnalysis.hierarchyCache
- .getTFClass(selector.member.enclosingClass));
+ .getTFClass(selector.member!.enclosingClass!));
receiver = receiver.intersection(
staticReceiverType, typeFlowAnalysis.hierarchyCache);
assert(receiver is! NullableType);
@@ -505,7 +505,7 @@
// invocation to the receiver class. A new allocated class discovered
// in the receiver cone will invalidate this invocation.
receiver = typeFlowAnalysis.hierarchyCache
- .specializeTypeCone((receiver as ConeType).cls, allowWideCone: false);
+ .specializeTypeCone(receiver.cls, allowWideCone: false);
}
assert(targets.isEmpty);
@@ -533,7 +533,7 @@
Class nullClass =
typeFlowAnalysis.environment.coreTypes.deprecatedNullClass;
- Member target = typeFlowAnalysis.hierarchyCache.hierarchy
+ Member? target = typeFlowAnalysis.hierarchyCache.hierarchy
.getDispatchTarget(nullClass, selector.name, setter: selector.isSetter);
if (target != null) {
@@ -550,7 +550,7 @@
TypeFlowAnalysis typeFlowAnalysis) {
final TFClass cls = receiver.cls;
- Member target =
+ Member? target =
(cls as _TFClassImpl).getDispatchTarget(selector, typeFlowAnalysis);
if (target != null) {
@@ -645,8 +645,9 @@
if (_isPolymorphic) {
callSite.setPolymorphic();
} else {
- if (_monomorphicTarget != null) {
- callSite.addTarget(_monomorphicTarget);
+ final monomorphicTarget = _monomorphicTarget;
+ if (monomorphicTarget != null) {
+ callSite.addTarget(monomorphicTarget);
}
}
@@ -658,18 +659,20 @@
/// Notify call sites monitoring this invocation about changes in
/// polymorphism of this invocation.
void _notifyCallSites() {
- if (_callSites != null) {
- _callSites.forEach(_notifyCallSite);
+ final callSites = _callSites;
+ if (callSites != null) {
+ callSites.forEach(_notifyCallSite);
}
}
@override
- Type get resultForRecursiveInvocation {
+ Type? get resultForRecursiveInvocation {
if (result != null) {
return result;
}
- if (_monomorphicDirectInvocation != null) {
- return _monomorphicDirectInvocation.resultForRecursiveInvocation;
+ final monomorphicDirectInvocation = _monomorphicDirectInvocation;
+ if (monomorphicDirectInvocation != null) {
+ return monomorphicDirectInvocation.resultForRecursiveInvocation;
}
return null;
}
@@ -681,30 +684,30 @@
/// 1) Add 1..N concrete types ordered by classId OR add 1 arbitrary type.
/// 2) Make type nullable.
class _ReceiverTypeBuilder {
- Type _type;
- List<ConcreteType> _list;
+ Type? _type;
+ List<ConcreteType>? _list;
bool _nullable = false;
/// Appends a ConcreteType. May be called multiple times.
/// Should not be used in conjunction with [addType].
void addConcreteType(ConcreteType type) {
- if (_list == null) {
- if (_type == null) {
+ final list = _list;
+ if (list == null) {
+ final Type? t = _type;
+ if (t == null) {
_type = type;
return;
}
+ final ct = t as ConcreteType;
- assert(_type is ConcreteType);
- assert(_type != type);
-
- _list = <ConcreteType>[];
- _list.add(_type);
-
+ assert(ct != type);
+ assert(ct.cls.id < type.cls.id);
+ _list = <ConcreteType>[ct, type];
_type = null;
+ } else {
+ assert(list.last.cls.id < type.cls.id);
+ list.add(type);
}
-
- assert(_list.last.cls.id < type.cls.id);
- _list.add(type);
}
/// Appends an arbitrary Type. May be called only once.
@@ -721,12 +724,13 @@
/// Returns union of added types.
Type toType() {
- Type t = _type;
+ Type? t = _type;
if (t == null) {
- if (_list == null) {
+ final list = _list;
+ if (list == null) {
t = const EmptyType();
} else {
- t = new SetType(_list);
+ t = SetType(list);
}
} else {
assert(_list == null);
@@ -751,7 +755,7 @@
static const int maxInvocationsPerSelector = 5000;
int count = 0;
- _Invocation approximation;
+ _Invocation? approximation;
}
/// Maintains ([Selector], [Args]) => [_Invocation] cache.
@@ -769,7 +773,7 @@
_Invocation invocation = (selector is DirectSelector)
? new _DirectInvocation(selector, args)
: new _DispatchableInvocation(selector, args);
- _Invocation result = _invocations.lookup(invocation);
+ _Invocation? result = _invocations.lookup(invocation);
if (result != null) {
return result;
}
@@ -782,14 +786,16 @@
final sa = (_approximations[selector] ??= new _SelectorApproximation());
if (sa.count >= _SelectorApproximation.maxInvocationsPerSelector) {
- if (sa.approximation == null) {
+ _Invocation? approximation = sa.approximation;
+ if (approximation == null) {
final rawArgs =
_typeFlowAnalysis.summaryCollector.rawArguments(selector);
- sa.approximation = new _DispatchableInvocation(selector, rawArgs);
+ sa.approximation =
+ approximation = _DispatchableInvocation(selector, rawArgs);
Statistics.approximateInvocationsCreated++;
}
Statistics.approximateInvocationsUsed++;
- return sa.approximation;
+ return approximation;
}
++sa.count;
@@ -807,8 +813,8 @@
class _FieldValue extends _DependencyTracker {
final Field field;
final Type staticType;
- final Summary typeGuardSummary;
- Type value;
+ final Summary? typeGuardSummary;
+ Type value = const EmptyType();
/// Flag indicating if field initializer was executed.
bool isInitialized = false;
@@ -823,8 +829,6 @@
: staticType = typesBuilder.fromStaticType(field.type, true) {
if (field.initializer == null && _isDefaultValueOfFieldObservable()) {
value = new Type.nullable(const EmptyType());
- } else {
- value = const EmptyType();
}
}
@@ -837,8 +841,7 @@
return true;
}
- final enclosingClass = field.enclosingClass;
- assert(enclosingClass != null);
+ final enclosingClass = field.enclosingClass!;
// Default value is not observable if every generative constructor
// is redirecting or initializes the field.
@@ -854,10 +857,11 @@
});
}
- void ensureInitialized(TypeFlowAnalysis typeFlowAnalysis, Type receiverType) {
+ void ensureInitialized(
+ TypeFlowAnalysis typeFlowAnalysis, Type? receiverType) {
if (field.initializer != null) {
assert(field.isStatic == (receiverType == null));
- final args = !field.isStatic ? <Type>[receiverType] : const <Type>[];
+ final args = !field.isStatic ? <Type>[receiverType!] : const <Type>[];
final initializerInvocation = typeFlowAnalysis._invocationsCache
.getInvocation(
new DirectSelector(field, callKind: CallKind.FieldInitializer),
@@ -868,17 +872,18 @@
}
}
- Type getValue(TypeFlowAnalysis typeFlowAnalysis, Type receiverType) {
+ Type getValue(TypeFlowAnalysis typeFlowAnalysis, Type? receiverType) {
ensureInitialized(typeFlowAnalysis, receiverType);
addDependentInvocation(typeFlowAnalysis.currentInvocation);
+ final typeGuardSummary = this.typeGuardSummary;
return (typeGuardSummary != null)
- ? typeGuardSummary.apply(Args([receiverType, value]),
+ ? typeGuardSummary.apply(Args([receiverType!, value]),
typeFlowAnalysis.hierarchyCache, typeFlowAnalysis)
: value;
}
void setValue(
- Type newValue, TypeFlowAnalysis typeFlowAnalysis, Type receiverType) {
+ Type newValue, TypeFlowAnalysis typeFlowAnalysis, Type? receiverType) {
// Make sure type cones are specialized before putting them into field
// value, in order to ensure that dependency is established between
// cone's base type and corresponding field setter.
@@ -905,10 +910,11 @@
//
final hierarchy = typeFlowAnalysis.hierarchyCache;
// TODO(sjindel/tfa): Perform narrowing inside 'TypeCheck'.
+ final typeGuardSummary = this.typeGuardSummary;
final narrowedNewValue = typeGuardSummary != null
? typeGuardSummary
- .apply(
- new Args([receiverType, newValue]), hierarchy, typeFlowAnalysis)
+ .apply(new Args([receiverType!, newValue]), hierarchy,
+ typeFlowAnalysis)
.intersection(staticType, hierarchy)
: newValue.specialize(hierarchy).intersection(staticType, hierarchy);
Type newType =
@@ -950,28 +956,26 @@
/// Flag indicating if this class has a noSuchMethod() method not inherited
/// from Object.
/// Lazy initialized by ClassHierarchyCache.hasNonTrivialNoSuchMethod().
- bool hasNonTrivialNoSuchMethod;
+ bool? hasNonTrivialNoSuchMethod;
_TFClassImpl(int id, Class classNode, this.supertypes)
: super(id, classNode) {
supertypes.add(this);
}
- ConcreteType _concreteType;
- ConcreteType get concreteType =>
- _concreteType ??= new ConcreteType(this, null);
+ late final ConcreteType concreteType = ConcreteType(this, null);
- Type _specializedConeType;
+ Type? _specializedConeType;
Type get specializedConeType =>
_specializedConeType ??= _calculateConeTypeSpecialization();
bool get hasWideCone =>
_allocatedSubtypes.length > maxAllocatedTypesInSetSpecializations;
- WideConeType _wideConeType;
+ late final WideConeType _wideConeType = WideConeType(this);
WideConeType get wideConeType {
assert(hasWideCone);
- return _wideConeType ??= new WideConeType(this);
+ return _wideConeType;
}
Type _calculateConeTypeSpecialization() {
@@ -997,14 +1001,16 @@
_specializedConeType = null; // Reset cached specialization.
}
- Member getDispatchTarget(
+ Member? getDispatchTarget(
Selector selector, TypeFlowAnalysis typeFlowAnalysis) {
- Member target = _dispatchTargets[selector];
+ Member? target = _dispatchTargets[selector];
if (target == null) {
target = typeFlowAnalysis.hierarchyCache.hierarchy.getDispatchTarget(
classNode, selector.name,
setter: selector.isSetter);
- _dispatchTargets[selector] = target;
+ if (target != null) {
+ _dispatchTargets[selector] = target;
+ }
}
return target;
}
@@ -1019,10 +1025,11 @@
final cachedFlattenedTypeArgs = <Class, List<DartType>>{};
final cachedFlattenedTypeArgsForNonGeneric = <Class, List<Type>>{};
- RuntimeTypeTranslatorImpl closedTypeTranslator;
+ late final RuntimeTypeTranslatorImpl closedTypeTranslator;
- GenericInterfacesInfoImpl(this.hierarchy) {
- closedTypeTranslator = RuntimeTypeTranslatorImpl.forClosedTypes(this);
+ GenericInterfacesInfoImpl(CoreTypes coreTypes, this.hierarchy) {
+ closedTypeTranslator =
+ RuntimeTypeTranslatorImpl.forClosedTypes(coreTypes, this);
}
List<DartType> flattenedTypeArgumentsFor(Class klass, {bool useCache: true}) {
@@ -1047,7 +1054,7 @@
if (klass == iface) return 0;
final pair = new SubtypePair(klass, iface);
- int offset = supertypeOffsetsCache[pair];
+ int? offset = supertypeOffsetsCache[pair];
if (offset != null) return offset;
@@ -1062,16 +1069,16 @@
}
List<Type> flattenedTypeArgumentsForNonGeneric(Class klass) {
- List<Type> result = cachedFlattenedTypeArgsForNonGeneric[klass];
+ List<Type>? result = cachedFlattenedTypeArgsForNonGeneric[klass];
if (result != null) return result;
List<DartType> flattenedTypeArgs =
flattenedTypeArgumentsFor(klass, useCache: false);
- result = new List<Type>.filled(flattenedTypeArgs.length, null);
- for (int i = 0; i < flattenedTypeArgs.length; ++i) {
- final translated = closedTypeTranslator.translate(flattenedTypeArgs[i]);
+ result = <Type>[];
+ for (DartType arg in flattenedTypeArgs) {
+ final translated = closedTypeTranslator.translate(arg);
assert(translated is RuntimeType || translated is UnknownType);
- result[i] = translated;
+ result.add(translated as Type);
}
cachedFlattenedTypeArgsForNonGeneric[klass] = result;
return result;
@@ -1106,10 +1113,8 @@
_ClassHierarchyCache(this._typeFlowAnalysis, this.hierarchy,
this.genericInterfacesInfo, this.environment, bool nullSafety)
: objectNoSuchMethod = hierarchy.getDispatchTarget(
- environment.coreTypes.objectClass, noSuchMethodName),
- super(environment.coreTypes, nullSafety) {
- assert(objectNoSuchMethod != null);
- }
+ environment.coreTypes.objectClass, noSuchMethodName)!,
+ super(environment.coreTypes, nullSafety);
@override
_TFClassImpl getTFClass(Class c) {
@@ -1196,10 +1201,13 @@
bool hasNonTrivialNoSuchMethod(TFClass c) {
final classImpl = c as _TFClassImpl;
- classImpl.hasNonTrivialNoSuchMethod ??=
- (hierarchy.getDispatchTarget(c.classNode, noSuchMethodName) !=
- objectNoSuchMethod);
- return classImpl.hasNonTrivialNoSuchMethod;
+ bool? value = classImpl.hasNonTrivialNoSuchMethod;
+ if (value == null) {
+ classImpl.hasNonTrivialNoSuchMethod = value =
+ (hierarchy.getDispatchTarget(c.classNode, noSuchMethodName) !=
+ objectNoSuchMethod);
+ }
+ return value;
}
_DynamicTargetSet getDynamicTargetSet(DynamicSelector selector) {
@@ -1292,10 +1300,11 @@
}
bool invalidateProtobufFields() {
- if (_typeFlowAnalysis.protobufHandler == null) {
+ final protobufHandler = _typeFlowAnalysis.protobufHandler;
+ if (protobufHandler == null) {
return false;
}
- final fields = _typeFlowAnalysis.protobufHandler.getInvalidatedFields();
+ final fields = protobufHandler.getInvalidatedFields();
if (fields.isEmpty) {
return false;
}
@@ -1303,7 +1312,7 @@
for (var field in fields) {
assert(field.isStatic);
// Reset summary in order to rebuild it.
- _typeFlowAnalysis._summaries[field] = null;
+ _typeFlowAnalysis._summaries.remove(field);
// Invalidate (and enqueue) field initializer invocation.
final initializerInvocation = _typeFlowAnalysis._invocationsCache
.getInvocation(
@@ -1326,10 +1335,11 @@
}
Type processInvocation(_Invocation invocation) {
- if (invocation.result != null) {
+ Type? result = invocation.result;
+ if (result != null) {
// Already processed.
Statistics.usedCachedResultsOfInvocations++;
- return invocation.result;
+ return result;
}
// Test if tracing is enabled to avoid expensive message formatting.
@@ -1372,18 +1382,18 @@
-1);
}
processing.remove(invocation);
- return invocation.invalidatedResult;
+ return invocation.invalidatedResult!;
}
callStack.add(invocation);
pending.remove(invocation);
- Type result = invocation.process(_typeFlowAnalysis);
+ result = invocation.process(_typeFlowAnalysis);
invocation.setResult(_typeFlowAnalysis, result);
// setResult may saturate result to ensure convergence.
- result = invocation.result;
+ result = invocation.result!;
// Invocation is still pending - it was invalidated while being processed.
// Move result to invalidatedResult.
@@ -1432,12 +1442,12 @@
final TypeEnvironment environment;
final LibraryIndex libraryIndex;
final PragmaAnnotationParser annotationMatcher;
- final ProtobufHandler protobufHandler;
- NativeCodeOracle nativeCodeOracle;
- _ClassHierarchyCache hierarchyCache;
- SummaryCollector summaryCollector;
- _InvocationsCache _invocationsCache;
- _WorkList workList;
+ final ProtobufHandler? protobufHandler;
+ late NativeCodeOracle nativeCodeOracle;
+ late _ClassHierarchyCache hierarchyCache;
+ late SummaryCollector summaryCollector;
+ late _InvocationsCache _invocationsCache;
+ late _WorkList workList;
GenericInterfacesInfo _genericInterfacesInfo;
final Map<Member, Summary> _summaries = <Member, Summary>{};
@@ -1457,7 +1467,7 @@
this.environment,
this.libraryIndex,
this.protobufHandler,
- PragmaAnnotationParser matcher)
+ PragmaAnnotationParser? matcher)
: annotationMatcher =
matcher ?? new ConstantPragmaAnnotationParser(coreTypes) {
nativeCodeOracle = new NativeCodeOracle(libraryIndex, annotationMatcher);
@@ -1486,9 +1496,9 @@
}
_FieldValue getFieldValue(Field field) {
- _FieldValue fieldValue = _fieldValues[field];
+ _FieldValue? fieldValue = _fieldValues[field];
if (fieldValue == null) {
- Summary typeGuardSummary = null;
+ Summary? typeGuardSummary = null;
if (field.isGenericCovariantImpl) {
typeGuardSummary = summaryCollector.createSummary(field,
fieldSummaryType: FieldSummaryType.kFieldGuard);
@@ -1546,22 +1556,24 @@
bool isClassAllocated(Class c) => hierarchyCache.allocatedClasses.contains(c);
- Call callSite(TreeNode node) => summaryCollector.callSites[node];
+ Call? callSite(TreeNode node) => summaryCollector.callSites[node];
- TypeCheck explicitCast(AsExpression cast) =>
+ TypeCheck? explicitCast(AsExpression cast) =>
summaryCollector.explicitCasts[cast];
- NarrowNotNull nullTest(TreeNode node) => summaryCollector.nullTests[node];
+ TypeCheck? isTest(IsExpression node) => summaryCollector.isTests[node];
- Type fieldType(Field field) => _fieldValues[field]?.value;
+ NarrowNotNull? nullTest(TreeNode node) => summaryCollector.nullTests[node];
- Args<Type> argumentTypes(Member member) => _summaries[member]?.argumentTypes;
+ Type? fieldType(Field field) => _fieldValues[field]?.value;
- Type argumentType(Member member, VariableDeclaration memberParam) {
+ Args<Type>? argumentTypes(Member member) => _summaries[member]?.argumentTypes;
+
+ Type? argumentType(Member member, VariableDeclaration memberParam) {
return _summaries[member]?.argumentType(member, memberParam);
}
- List<VariableDeclaration> uncheckedParameters(Member member) =>
+ List<VariableDeclaration>? uncheckedParameters(Member member) =>
_summaries[member]?.uncheckedParameters;
bool isTearOffTaken(Member member) => _tearOffTaken.contains(member);
@@ -1595,7 +1607,7 @@
/// ---- Implementation of [CallHandler] interface. ----
@override
- Type applyCall(Call callSite, Selector selector, Args<Type> args,
+ Type applyCall(Call? callSite, Selector selector, Args<Type> args,
{bool isResultUsed: true, bool processImmediately: true}) {
_Invocation invocation = _invocationsCache.getInvocation(selector, args);
@@ -1625,7 +1637,7 @@
workList.enqueueInvocation(invocation);
}
- return null;
+ return const EmptyType();
}
}
@@ -1676,7 +1688,7 @@
}
@override
- void recordTearOff(Procedure target) {
+ void recordTearOff(Member target) {
_tearOffTaken.add(target);
}
}
diff --git a/pkg/vm/lib/transformations/type_flow/calls.dart b/pkg/vm/lib/transformations/type_flow/calls.dart
index 6fa64e8..dd16279d 100644
--- a/pkg/vm/lib/transformations/type_flow/calls.dart
+++ b/pkg/vm/lib/transformations/type_flow/calls.dart
@@ -3,7 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
/// Declares classes which describe a call: selectors and arguments.
-library vm.transformations.type_flow.calls;
import 'dart:core' hide Type;
@@ -28,10 +27,10 @@
Selector(this.callKind);
/// Interface or concrete target, may be null.
- Member get member;
+ Member? get member;
/// Selector name.
- Name get name => member.name;
+ Name get name => member!.name;
bool get isSetter => (callKind == CallKind.PropertySet);
@@ -44,6 +43,7 @@
/// Static approximation of Dart return type.
DartType get staticReturnType {
+ final member = this.member;
if (member == null) {
return const DynamicType();
}
@@ -59,7 +59,6 @@
case CallKind.SetFieldInConstructor:
return const NeverType.nonNullable();
}
- return null;
}
bool memberAgreesToCallKind(Member member) {
@@ -77,7 +76,6 @@
case CallKind.SetFieldInConstructor:
return member is Field;
}
- return false;
}
String get _callKindPrefix {
@@ -92,7 +90,6 @@
case CallKind.FieldInitializer:
return 'init ';
}
- return '';
}
}
@@ -167,7 +164,7 @@
DynamicSelector(CallKind callKind, this.name) : super(callKind);
@override
- Member get member => null;
+ Member? get member => null;
@override
int get hashCode => (super.hashCode ^ name.hashCode + 37) & kHashMask;
@@ -187,7 +184,8 @@
final List<T> values;
final List<String> names;
- int _hashCode;
+ @override
+ late final int hashCode = _computeHashCode();
Args(this.values, {this.names = const <String>[]}) {
assert(isSorted(names));
@@ -204,9 +202,6 @@
T get receiver => values[0];
- @override
- int get hashCode => _hashCode ??= _computeHashCode();
-
int _computeHashCode() {
int hash = 1231;
for (var v in values) {
diff --git a/pkg/vm/lib/transformations/type_flow/native_code.dart b/pkg/vm/lib/transformations/type_flow/native_code.dart
index e24408b..0611379 100644
--- a/pkg/vm/lib/transformations/type_flow/native_code.dart
+++ b/pkg/vm/lib/transformations/type_flow/native_code.dart
@@ -3,7 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
/// Handling of native code and entry points.
-library vm.transformations.type_flow.native_code;
import 'dart:core' hide Type;
@@ -33,24 +32,21 @@
/// Record the fact that given member is called from this.
void recordMemberCalledViaThis(Member target);
- /// Record the fact that given method is torn off.
- void recordTearOff(Procedure target) {}
+ /// Record the fact that given member is torn off.
+ void recordTearOff(Member target) {}
}
class PragmaEntryPointsVisitor extends RecursiveVisitor {
final EntryPointsListener entryPoints;
final NativeCodeOracle nativeCodeOracle;
final PragmaAnnotationParser matcher;
- Class currentClass = null;
PragmaEntryPointsVisitor(
- this.entryPoints, this.nativeCodeOracle, this.matcher) {
- assert(matcher != null);
- }
+ this.entryPoints, this.nativeCodeOracle, this.matcher);
- PragmaEntryPointType _annotationsDefineRoot(List<Expression> annotations) {
+ PragmaEntryPointType? _annotationsDefineRoot(List<Expression> annotations) {
for (var annotation in annotations) {
- ParsedPragma pragma = matcher.parsePragma(annotation);
+ ParsedPragma? pragma = matcher.parsePragma(annotation);
if (pragma == null) continue;
if (pragma is ParsedEntryPointPragma) return pragma.type;
}
@@ -70,7 +66,6 @@
}
nativeCodeOracle.addClassReferencedFromNativeCode(klass);
}
- currentClass = klass;
klass.visitChildren(this);
}
@@ -79,15 +74,14 @@
var type = _annotationsDefineRoot(proc.annotations);
if (type == null) return;
- if (proc.isRedirectingFactoryConstructor) {
+ if (proc.isRedirectingFactory) {
if (type != PragmaEntryPointType.CallOnly &&
type != PragmaEntryPointType.Default) {
throw "Error: factory $proc doesn't have a setter or getter";
}
Member target = proc;
- while (target is Procedure && target.isRedirectingFactoryConstructor) {
- target = getRedirectingFactoryBody(target).target;
- assert(target != null);
+ while (target is Procedure && target.isRedirectingFactory) {
+ target = getRedirectingFactoryBody(target)!.target!;
assert(
(target is Procedure && target.isFactory) || target is Constructor);
}
@@ -150,7 +144,7 @@
}
entryPoints
.addRawCall(new DirectSelector(ctor, callKind: CallKind.Method));
- entryPoints.addAllocatedClass(currentClass);
+ entryPoints.addAllocatedClass(ctor.enclosingClass);
nativeCodeOracle.setMemberReferencedFromNativeCode(ctor);
}
}
@@ -199,9 +193,7 @@
final Set<Class> _classesReferencedFromNativeCode = new Set<Class>();
final PragmaAnnotationParser _matcher;
- NativeCodeOracle(this._libraryIndex, this._matcher) {
- assert(_matcher != null);
- }
+ NativeCodeOracle(this._libraryIndex, this._matcher);
void addClassReferencedFromNativeCode(Class klass) {
_classesReferencedFromNativeCode.add(klass);
@@ -217,9 +209,9 @@
bool isMemberReferencedFromNativeCode(Member member) =>
_membersReferencedFromNativeCode.contains(member);
- PragmaRecognizedType recognizedType(Member member) {
+ PragmaRecognizedType? recognizedType(Member member) {
for (var annotation in member.annotations) {
- ParsedPragma pragma = _matcher.parsePragma(annotation);
+ ParsedPragma? pragma = _matcher.parsePragma(annotation);
if (pragma is ParsedRecognized) {
return pragma.type;
}
@@ -227,15 +219,16 @@
return null;
}
- bool isRecognized(Member member, [List<PragmaRecognizedType> expectedTypes]) {
- PragmaRecognizedType type = recognizedType(member);
+ bool isRecognized(Member member,
+ [List<PragmaRecognizedType>? expectedTypes]) {
+ PragmaRecognizedType? type = recognizedType(member);
return type != null &&
(expectedTypes == null || expectedTypes.contains(type));
}
bool hasDisableUnboxedParameters(Member member) {
for (var annotation in member.annotations) {
- ParsedPragma pragma = _matcher.parsePragma(annotation);
+ ParsedPragma? pragma = _matcher.parsePragma(annotation);
if (pragma is ParsedDisableUnboxedParameters) {
if (member.enclosingLibrary.importUri.scheme != "dart") {
throw "ERROR: Cannot use @pragma(vm:disable-unboxed-parameters) outside core libraries.";
@@ -253,11 +246,11 @@
EntryPointsListener entryPointsListener,
TypesBuilder typesBuilder,
RuntimeTypeTranslator translator) {
- TypeExpr returnType = null;
- bool nullable = null;
+ TypeExpr? returnType = null;
+ bool? nullable = null;
for (var annotation in member.annotations) {
- ParsedPragma pragma = _matcher.parsePragma(annotation);
+ ParsedPragma? pragma = _matcher.parsePragma(annotation);
if (pragma == null) continue;
if (pragma is ParsedResultTypeByTypePragma ||
pragma is ParsedResultTypeByPathPragma ||
@@ -276,8 +269,8 @@
returnType = entryPointsListener.addAllocatedClass(type.classNode);
if (pragma.resultTypeUsesPassedTypeArguments) {
returnType = translator.instantiateConcreteType(
- returnType,
- member.function.typeParameters
+ returnType as ConcreteType,
+ member.function!.typeParameters
.map((t) => TypeParameterType(
t, TypeParameterType.computeNullabilityFromBound(t)))
.toList());
@@ -312,7 +305,7 @@
return returnType;
} else {
return typesBuilder.fromStaticType(
- member.function.returnType, nullable ?? true);
+ member.function!.returnType, nullable ?? true);
}
}
}
diff --git a/pkg/vm/lib/transformations/type_flow/protobuf_handler.dart b/pkg/vm/lib/transformations/type_flow/protobuf_handler.dart
index 5bd8db7..c0175a4 100644
--- a/pkg/vm/lib/transformations/type_flow/protobuf_handler.dart
+++ b/pkg/vm/lib/transformations/type_flow/protobuf_handler.dart
@@ -45,14 +45,14 @@
final Procedure _builderInfoAddMethod;
// Type of BuilderInfo.add<Null>().
- FunctionType _typeOfBuilderInfoAddOfNull;
+ late FunctionType _typeOfBuilderInfoAddOfNull;
final _messageClasses = <Class, _MessageClass>{};
final _invalidatedClasses = <_MessageClass>{};
/// Creates [ProtobufHandler] instance for [component].
/// Returns null if protobuf library is not used.
- static ProtobufHandler forComponent(
+ static ProtobufHandler? forComponent(
Component component, CoreTypes coreTypes) {
final libraryIndex = LibraryIndex(component, [protobufLibraryUri]);
if (!libraryIndex.containsLibrary(protobufLibraryUri)) {
@@ -66,12 +66,12 @@
libraryIndex.getClass(protobufLibraryUri, 'GeneratedMessage'),
_tagNumberClass =
libraryIndex.getClass(protobufLibraryUri, 'TagNumber'),
- _tagNumberField = libraryIndex.getMember(
- protobufLibraryUri, 'TagNumber', 'tagNumber'),
+ _tagNumberField =
+ libraryIndex.getField(protobufLibraryUri, 'TagNumber', 'tagNumber'),
_builderInfoClass =
libraryIndex.getClass(protobufLibraryUri, 'BuilderInfo'),
- _builderInfoAddMethod =
- libraryIndex.getMember(protobufLibraryUri, 'BuilderInfo', 'add') {
+ _builderInfoAddMethod = libraryIndex.getProcedure(
+ protobufLibraryUri, 'BuilderInfo', 'add') {
final functionType = _builderInfoAddMethod.getterType as FunctionType;
_typeOfBuilderInfoAddOfNull = Substitution.fromPairs(
functionType.typeParameters, const <DartType>[NullType()])
@@ -128,8 +128,9 @@
List<Field> getInvalidatedFields() {
final fields = <Field>[];
for (var cls in _invalidatedClasses) {
- if (cls._metadataField != null) {
- fields.add(cls._metadataField);
+ final field = cls._metadataField;
+ if (field != null) {
+ fields.add(field);
}
}
_invalidatedClasses.clear();
@@ -141,14 +142,15 @@
++Statistics.protobufMetadataInitializersUpdated;
Statistics.protobufMetadataFieldsPruned -= cls.numberOfFieldsPruned;
- final field = cls._metadataField;
- if (cls._originalInitializer == null) {
- cls._originalInitializer = field.initializer;
+ final field = cls._metadataField!;
+ Expression? originalInitializer = cls._originalInitializer;
+ if (originalInitializer == null) {
+ cls._originalInitializer = originalInitializer = field.initializer!;
}
final cloner = CloneVisitorNotMembers();
- field.initializer = cloner.clone(cls._originalInitializer)..parent = field;
+ field.initializer = cloner.clone(originalInitializer)..parent = field;
final transformer = _MetadataTransformer(this, cls);
- field.initializer.accept(transformer);
+ field.initializer!.accept(transformer);
_invalidatedClasses.remove(cls);
cls.numberOfFieldsPruned = transformer.numberOfFieldsPruned;
@@ -166,8 +168,8 @@
}
class _MessageClass {
- Field _metadataField;
- Expression _originalInitializer;
+ Field? _metadataField;
+ Expression? _originalInitializer;
final _usedTags = <int>{};
int numberOfFieldsPruned = 0;
}
diff --git a/pkg/vm/lib/transformations/type_flow/signature_shaking.dart b/pkg/vm/lib/transformations/type_flow/signature_shaking.dart
index 2d16a7b..5ae2e16 100644
--- a/pkg/vm/lib/transformations/type_flow/signature_shaking.dart
+++ b/pkg/vm/lib/transformations/type_flow/signature_shaking.dart
@@ -55,7 +55,7 @@
SignatureShaker(this.typeFlowAnalysis, this.tableSelectorAssigner);
- _ProcedureInfo _infoForMember(Member member) {
+ _ProcedureInfo? _infoForMember(Member member) {
if (!(member is Procedure &&
(member.kind == ProcedureKind.Method ||
member.kind == ProcedureKind.Factory) ||
@@ -87,7 +87,7 @@
}
while (worklist.isNotEmpty) {
_ParameterInfo param = worklist.removeLast();
- for (_ParameterInfo dependencyParam in param.useDependencies) {
+ for (_ParameterInfo dependencyParam in param.useDependencies!) {
if (!dependencyParam.isRead) {
dependencyParam.isRead = true;
if (dependencyParam.useDependencies != null) {
@@ -139,7 +139,7 @@
return positional.any((param) =>
param.canBeEliminated ||
(param.isAlwaysPassed &&
- param.index >= function.requiredParameterCount)) ||
+ param.index! >= function.requiredParameterCount)) ||
named.values
.any((param) => param.canBeEliminated || param.isAlwaysPassed);
}
@@ -147,7 +147,7 @@
class _ParameterInfo {
final _ProcedureInfo info;
- final int index;
+ final int? index;
int passCount = 0;
bool isRead = false;
@@ -158,7 +158,7 @@
/// List of parameter variables which were passed as arguments via this
/// parameter. When this parameter is considered used, all [useDependencies]
/// parameters should be transitively marked as read.
- List<_ParameterInfo> useDependencies = null;
+ List<_ParameterInfo>? useDependencies = null;
_ParameterInfo(this.info, this.index);
@@ -175,7 +175,7 @@
void observeParameter(
Member member, VariableDeclaration param, SignatureShaker shaker) {
- final Type type = shaker.typeFlowAnalysis.argumentType(member, param);
+ final Type? type = shaker.typeFlowAnalysis.argumentType(member, param);
// A parameter is considered constant if the TFA has inferred it to have a
// constant value in every implementation. The constant value inferred does
@@ -212,19 +212,19 @@
_Collect(this.shaker);
void enterFunction(Member member) {
- final _ProcedureInfo info = shaker._infoForMember(member);
+ final _ProcedureInfo? info = shaker._infoForMember(member);
if (info == null) return;
localParameters.clear();
useDependencies.clear();
- final FunctionNode fun = member.function;
+ final FunctionNode fun = member.function!;
for (int i = 0; i < fun.positionalParameters.length; i++) {
final VariableDeclaration param = fun.positionalParameters[i];
localParameters[param] = info.ensurePositional(i)
..observeParameter(member, param, shaker);
}
for (VariableDeclaration param in fun.namedParameters) {
- localParameters[param] = info.ensureNamed(param.name)
+ localParameters[param] = info.ensureNamed(param.name!)
..observeParameter(member, param, shaker);
}
@@ -268,19 +268,22 @@
void addUseDependency(Expression arg, _ParameterInfo param) {
if (arg is VariableGet) {
- _ParameterInfo localParam = localParameters[arg.variable];
+ _ParameterInfo? localParam = localParameters[arg.variable];
if (localParam != null && !localParam.isUsed) {
// This is a parameter passed as an argument. Mark it as a use
// dependency.
- param.useDependencies ??= [];
- param.useDependencies.add(localParam);
+ var paramUseDependencies = param.useDependencies;
+ if (paramUseDependencies == null) {
+ param.useDependencies = paramUseDependencies = [];
+ }
+ paramUseDependencies.add(localParam);
useDependencies.add(arg);
}
}
}
void collectCall(Member member, Arguments args) {
- final _ProcedureInfo info = shaker._infoForMember(member);
+ final _ProcedureInfo? info = shaker._infoForMember(member);
if (info == null) return;
for (int i = 0; i < args.positional.length; i++) {
@@ -304,7 +307,10 @@
@override
void visitSuperMethodInvocation(SuperMethodInvocation node) {
- collectCall(node.interfaceTarget, node.arguments);
+ final interfaceTarget = node.interfaceTarget;
+ if (interfaceTarget != null) {
+ collectCall(interfaceTarget, node.arguments);
+ }
super.visitSuperMethodInvocation(node);
}
@@ -336,7 +342,7 @@
class _Transform extends RecursiveVisitor {
final SignatureShaker shaker;
- StaticTypeContext typeContext;
+ late StaticTypeContext typeContext;
final Map<VariableDeclaration, Constant> eliminatedParams = {};
final Set<VariableDeclaration> unusedParams = {};
final List<LocalInitializer> addedInitializers = [];
@@ -347,16 +353,15 @@
Member member, _ParameterInfo param, VariableDeclaration variable) {
Constant value;
if (param.isConstant) {
- Type type = shaker.typeFlowAnalysis.argumentType(member, variable);
+ Type type = shaker.typeFlowAnalysis.argumentType(member, variable)!;
if (type is ConcreteType) {
- assert(type.constant != null);
- value = type.constant;
+ value = type.constant!;
} else {
assert(type is NullableType && type.baseType is EmptyType);
value = NullConstant();
}
} else {
- value = (variable.initializer as ConstantExpression)?.constant ??
+ value = (variable.initializer as ConstantExpression?)?.constant ??
NullConstant();
}
eliminatedParams[variable] = value;
@@ -368,10 +373,10 @@
eliminatedParams.clear();
unusedParams.clear();
- final _ProcedureInfo info = shaker._infoForMember(member);
+ final _ProcedureInfo? info = shaker._infoForMember(member);
if (info == null || !info.eligible || info.callCount == 0) return;
- final FunctionNode function = member.function;
+ final FunctionNode function = member.function!;
if (!info.transformNeeded(function)) return;
@@ -402,9 +407,9 @@
// as required positional parameters, alphabetically by name.
final List<VariableDeclaration> sortedNamed = function.namedParameters
.toList()
- ..sort((var1, var2) => var1.name.compareTo(var2.name));
+ ..sort((var1, var2) => var1.name!.compareTo(var2.name!));
for (VariableDeclaration variable in sortedNamed) {
- final _ParameterInfo param = info.named[variable.name];
+ final _ParameterInfo param = info.named[variable.name!]!;
if (param.isAlwaysPassed) {
if (param.isUsed) {
if (param.canBeEliminated) {
@@ -449,7 +454,7 @@
// 4. All named parameters that are not always passed and can't be
// eliminated, as named parameters in alphabetical order.
for (VariableDeclaration variable in sortedNamed) {
- final _ParameterInfo param = info.named[variable.name];
+ final _ParameterInfo param = info.named[variable.name!]!;
if (!param.isAlwaysPassed) {
if (param.isUsed) {
if (param.canBeEliminated) {
@@ -473,7 +478,7 @@
@override
void visitVariableGet(VariableGet node) {
- Constant constantValue = eliminatedParams[node.variable];
+ Constant? constantValue = eliminatedParams[node.variable];
if (constantValue != null) {
node.replaceWith(ConstantExpression(constantValue));
}
@@ -509,7 +514,7 @@
void Function(Expression, _ParameterInfo) fun) {
for (int i = args.named.length - 1; i >= 0; i--) {
final NamedExpression namedExp = args.named[i];
- fun(namedExp.value, info.named[namedExp.name]);
+ fun(namedExp.value, info.named[namedExp.name]!);
}
for (int i = args.positional.length - 1; i >= 0; i--) {
fun(args.positional[i], info.positional[i]);
@@ -517,8 +522,8 @@
}
void transformCall(
- Member target, TreeNode call, Expression receiver, Arguments args) {
- final _ProcedureInfo info = shaker._infoForMember(target);
+ Member target, TreeNode call, Expression? receiver, Arguments args) {
+ final _ProcedureInfo? info = shaker._infoForMember(target);
if (info == null || !info.eligible) return;
bool transformNeeded = false;
@@ -542,7 +547,7 @@
Map<Expression, VariableDeclaration> hoisted = {};
if (hoistingNeeded) {
if (call is Initializer) {
- final Constructor constructor = call.parent;
+ final Constructor constructor = call.parent as Constructor;
forEachArgumentRev(args, info, (Expression arg, _ParameterInfo param) {
if (mayHaveOrSeeSideEffects(arg) && !isUnusedParam(arg)) {
VariableDeclaration argVar = VariableDeclaration(null,
@@ -555,8 +560,8 @@
}
});
} else {
- final TreeNode parent = call.parent;
- Expression current = call;
+ final TreeNode parent = call.parent!;
+ Expression current = call as Expression;
forEachArgumentRev(args, info, (Expression arg, _ParameterInfo param) {
if (mayHaveOrSeeSideEffects(arg) && !isUnusedParam(arg)) {
VariableDeclaration argVar = VariableDeclaration(null,
@@ -604,7 +609,7 @@
final List<NamedExpression> sortedNamed = args.named.toList()
..sort((var1, var2) => var1.name.compareTo(var2.name));
for (NamedExpression arg in sortedNamed) {
- final _ParameterInfo param = info.named[arg.name];
+ final _ParameterInfo param = info.named[arg.name]!;
if (param.isAlwaysPassed && !param.canBeEliminated) {
positional.add(getMaybeHoistedArg(arg.value));
}
@@ -623,7 +628,7 @@
// eliminated, as named parameters in alphabetical order.
// (Arguments are kept in original order.)
for (NamedExpression arg in args.named) {
- final _ParameterInfo param = info.named[arg.name];
+ final _ParameterInfo param = info.named[arg.name]!;
if (!param.isAlwaysPassed && !param.canBeEliminated) {
arg.value = getMaybeHoistedArg(arg.value)..parent = arg;
named.add(arg);
@@ -642,7 +647,10 @@
@override
void visitSuperMethodInvocation(SuperMethodInvocation node) {
super.visitSuperMethodInvocation(node);
- transformCall(node.interfaceTarget, node, null, node.arguments);
+ final interfaceTarget = node.interfaceTarget;
+ if (interfaceTarget != null) {
+ transformCall(interfaceTarget, node, null, node.arguments);
+ }
}
@override
diff --git a/pkg/vm/lib/transformations/type_flow/summary.dart b/pkg/vm/lib/transformations/type_flow/summary.dart
index b8033f9..fb18cec 100644
--- a/pkg/vm/lib/transformations/type_flow/summary.dart
+++ b/pkg/vm/lib/transformations/type_flow/summary.dart
@@ -3,7 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
/// Type flow summary of a member, function or initializer.
-library vm.transformations.type_flow.summary;
import 'dart:core' hide Type;
@@ -16,22 +15,19 @@
abstract class CallHandler {
Type applyCall(Call callSite, Selector selector, Args<Type> args,
- {bool isResultUsed});
+ {required bool isResultUsed});
void typeCheckTriggered();
+ void addAllocatedClass(Class c);
}
/// Base class for all statements in a summary.
abstract class Statement extends TypeExpr {
/// Index of this statement in the [Summary].
int index = -1;
- Summary summary;
+ late Summary summary;
@override
- Type getComputedType(List<Type> types) {
- final type = types[index];
- assert(type != null);
- return type;
- }
+ Type getComputedType(List<Type?> types) => types[index]!;
String get label => "t$index";
@@ -45,7 +41,7 @@
void accept(StatementVisitor visitor);
/// Execute this statement and compute its resulting type.
- Type apply(List<Type> computedTypes, TypeHierarchy typeHierarchy,
+ Type apply(List<Type?> computedTypes, TypeHierarchy typeHierarchy,
CallHandler callHandler);
}
@@ -71,9 +67,9 @@
// [staticType] is null if no narrowing should be performed. This happens for
// type parameters and for parameters whose type is narrowed by a [TypeCheck]
// statement.
- final Type staticTypeForNarrowing;
+ final Type? staticTypeForNarrowing;
- Type defaultValue;
+ Type? defaultValue;
Type _argumentType = const EmptyType();
Parameter(this.name, this.staticTypeForNarrowing);
@@ -94,7 +90,7 @@
}
@override
- Type apply(List<Type> computedTypes, TypeHierarchy typeHierarchy,
+ Type apply(List<Type?> computedTypes, TypeHierarchy typeHierarchy,
CallHandler callHandler) =>
throw 'Unable to apply _Parameter';
@@ -107,7 +103,7 @@
}
Type _observeNotPassed(TypeHierarchy typeHierarchy) {
- final Type argType = defaultValue.specialize(typeHierarchy);
+ final Type argType = defaultValue!.specialize(typeHierarchy);
_observeArgumentType(argType, typeHierarchy);
return argType;
}
@@ -127,7 +123,7 @@
String dump() => "$label = _Narrow ($arg to $type)";
@override
- Type apply(List<Type> computedTypes, TypeHierarchy typeHierarchy,
+ Type apply(List<Type?> computedTypes, TypeHierarchy typeHierarchy,
CallHandler callHandler) =>
arg.getComputedType(computedTypes).intersection(type, typeHierarchy);
}
@@ -144,11 +140,11 @@
// Shared NarrowNotNull instances which are used when the outcome is
// known at summary creation time.
- static final NarrowNotNull alwaysNotNull = NarrowNotNull(null)
+ static final NarrowNotNull alwaysNotNull = NarrowNotNull(const EmptyType())
.._flags = canBeNotNullFlag;
- static final NarrowNotNull alwaysNull = NarrowNotNull(null)
+ static final NarrowNotNull alwaysNull = NarrowNotNull(const EmptyType())
.._flags = canBeNullFlag;
- static final NarrowNotNull unknown = NarrowNotNull(null)
+ static final NarrowNotNull unknown = NarrowNotNull(const EmptyType())
.._flags = canBeNullFlag | canBeNotNullFlag;
bool get isAlwaysNull => (_flags & canBeNotNullFlag) == 0;
@@ -170,14 +166,14 @@
}
@override
- Type apply(List<Type> computedTypes, TypeHierarchy typeHierarchy,
+ Type apply(List<Type?> computedTypes, TypeHierarchy typeHierarchy,
CallHandler callHandler) =>
handleArgument(arg.getComputedType(computedTypes));
}
/// Joins values from multiple sources. Its type is a union of [values].
class Join extends Statement {
- final String _name;
+ final String? _name;
final DartType staticType;
final List<TypeExpr> values = <TypeExpr>[]; // TODO(alexmarkov): Set
@@ -194,15 +190,14 @@
" (${values.join(", ")})";
@override
- Type apply(List<Type> computedTypes, TypeHierarchy typeHierarchy,
+ Type apply(List<Type?> computedTypes, TypeHierarchy typeHierarchy,
CallHandler callHandler) {
- Type type = null;
- assert(values.isNotEmpty);
+ Type? type = null;
for (var value in values) {
final valueType = value.getComputedType(computedTypes);
type = type != null ? type.union(valueType, typeHierarchy) : valueType;
}
- return type;
+ return type!;
}
}
@@ -219,7 +214,7 @@
String dump() => "$label = _Use ($arg)";
@override
- Type apply(List<Type> computedTypes, TypeHierarchy typeHierarchy,
+ Type apply(List<Type?> computedTypes, TypeHierarchy typeHierarchy,
CallHandler callHandler) =>
throw 'Use statements should be removed during summary normalization';
}
@@ -228,14 +223,18 @@
class Call extends Statement {
final Selector selector;
final Args<TypeExpr> args;
- final Type staticResultType;
+ final Type? staticResultType;
- Call(this.selector, this.args, this.staticResultType) {
+ Call(this.selector, this.args, this.staticResultType,
+ bool isInstanceCreation) {
// TODO(sjindel/tfa): Support inferring unchecked entry-points for dynamic
// and direct calls as well.
if (selector is DynamicSelector || selector is DirectSelector) {
setUseCheckedEntry();
}
+ if (isInstanceCreation) {
+ setInstanceCreation();
+ }
}
@override
@@ -245,9 +244,10 @@
String dump() => "$label${isResultUsed ? '*' : ''} = _Call $selector $args";
@override
- Type apply(List<Type> computedTypes, TypeHierarchy typeHierarchy,
+ Type apply(List<Type?> computedTypes, TypeHierarchy typeHierarchy,
CallHandler callHandler) {
- final List<Type> argTypes = new List<Type>.filled(args.values.length, null);
+ final List<Type> argTypes =
+ new List<Type>.filled(args.values.length, const EmptyType());
for (int i = 0; i < args.values.length; i++) {
final Type type = args.values[i].getComputedType(computedTypes);
if (type == const EmptyType()) {
@@ -260,12 +260,19 @@
if (selector is! DirectSelector) {
_observeReceiverType(argTypes[0], typeHierarchy);
}
- final Stopwatch timer = kPrintTimings ? (new Stopwatch()..start()) : null;
+ if (isInstanceCreation) {
+ callHandler
+ .addAllocatedClass((argTypes[0] as ConcreteType).cls.classNode);
+ }
+ final Stopwatch? timer = kPrintTimings ? (new Stopwatch()..start()) : null;
Type result = callHandler.applyCall(
this, selector, new Args<Type>(argTypes, names: args.names),
isResultUsed: isResultUsed);
- summary.calleeTime += kPrintTimings ? timer.elapsedMicroseconds : 0;
- if (isResultUsed) {
+ summary.calleeTime += kPrintTimings ? timer!.elapsedMicroseconds : 0;
+ if (isInstanceCreation) {
+ result = argTypes[0];
+ } else if (isResultUsed) {
+ final staticResultType = this.staticResultType;
if (staticResultType != null) {
result = result.intersection(staticResultType, typeHierarchy);
}
@@ -287,10 +294,11 @@
static const int kReachable = (1 << 4);
static const int kUseCheckedEntry = (1 << 5);
static const int kReceiverMayBeInt = (1 << 6);
+ static const int kInstanceCreation = (1 << 7);
- Member _monomorphicTarget;
+ Member? _monomorphicTarget;
- Member get monomorphicTarget => _monomorphicTarget;
+ Member? get monomorphicTarget => _monomorphicTarget;
bool get isMonomorphic => (_flags & kMonomorphic) != 0;
@@ -306,6 +314,8 @@
bool get useCheckedEntry => (_flags & kUseCheckedEntry) != 0;
+ bool get isInstanceCreation => (_flags & kInstanceCreation) != 0;
+
Type get resultType => _resultType;
void setUseCheckedEntry() {
@@ -320,6 +330,10 @@
_flags |= kReachable;
}
+ void setInstanceCreation() {
+ _flags |= kInstanceCreation;
+ }
+
void setPolymorphic() {
_flags = (_flags & ~kMonomorphic) | kPolymorphic;
_monomorphicTarget = null;
@@ -376,18 +390,19 @@
"/$paramIndex]${nullability.suffix})";
@override
- Type apply(List<Type> computedTypes, TypeHierarchy typeHierarchy,
+ Type apply(List<Type?> computedTypes, TypeHierarchy typeHierarchy,
CallHandler callHandler) {
Type argType = arg.getComputedType(computedTypes);
- Type extractedType;
+ Type? extractedType;
void extractType(ConcreteType c) {
- if (c.typeArgs == null) {
+ final typeArgs = c.typeArgs;
+ if (typeArgs == null) {
extractedType = const UnknownType();
} else {
final interfaceOffset = typeHierarchy.genericInterfaceOffsetFor(
c.cls.classNode, referenceClass);
- final typeArg = c.typeArgs[interfaceOffset + paramIndex];
+ final typeArg = typeArgs[interfaceOffset + paramIndex];
Type extracted = typeArg;
if (typeArg is RuntimeType) {
final argNullability = typeArg.nullability;
@@ -452,16 +467,15 @@
}
@override
- Type apply(List<Type> computedTypes, TypeHierarchy typeHierarchy,
+ Type apply(List<Type?> computedTypes, TypeHierarchy typeHierarchy,
CallHandler callHandler) {
bool hasRuntimeType = false;
- final types = new List<Type>.filled(flattenedTypeArgs.length, null);
- for (int i = 0; i < types.length; ++i) {
+ final types = List<Type>.generate(flattenedTypeArgs.length, (int i) {
final computed = flattenedTypeArgs[i].getComputedType(computedTypes);
assert(computed is RuntimeType || computed is UnknownType);
if (computed is RuntimeType) hasRuntimeType = true;
- types[i] = computed;
- }
+ return computed;
+ });
return new ConcreteType(cls, hasRuntimeType ? types : null);
}
}
@@ -485,14 +499,13 @@
"${nullability.suffix})";
@override
- Type apply(List<Type> computedTypes, TypeHierarchy typeHierarchy,
+ Type apply(List<Type?> computedTypes, TypeHierarchy typeHierarchy,
CallHandler callHandler) {
- final types = new List<RuntimeType>.filled(flattenedTypeArgs.length, null);
- for (int i = 0; i < types.length; ++i) {
- final computed = flattenedTypeArgs[i].getComputedType(computedTypes);
- assert(computed is RuntimeType || computed is UnknownType);
+ final types = <RuntimeType>[];
+ for (TypeExpr arg in flattenedTypeArgs) {
+ final computed = arg.getComputedType(computedTypes);
if (computed is UnknownType) return const UnknownType();
- types[i] = computed;
+ types.add(computed as RuntimeType);
}
DartType dartType;
if (klass == typeHierarchy.coreTypes.deprecatedFutureOrClass) {
@@ -518,22 +531,22 @@
final TreeNode node;
final Type staticType;
+ final SubtypeTestKind kind;
// 'isTestedOnlyOnCheckedEntryPoint' is whether or not this parameter's type-check will
// occur on the "checked" entrypoint in the VM but will be skipped on
// "unchecked" entrypoint.
bool isTestedOnlyOnCheckedEntryPoint;
- VariableDeclaration get parameter =>
- node is VariableDeclaration ? node : null;
+ bool get isParameterCheck => node is VariableDeclaration;
+ VariableDeclaration get parameterVariable => node as VariableDeclaration;
- bool canAlwaysSkip = true;
+ bool alwaysPass = true;
+ bool alwaysFail = true;
- TypeCheck(this.arg, this.type, this.node, this.staticType) {
- assert(node != null);
- isTestedOnlyOnCheckedEntryPoint =
- parameter != null && !parameter.isCovariant;
- }
+ TypeCheck(this.arg, this.type, this.node, this.staticType, this.kind)
+ : isTestedOnlyOnCheckedEntryPoint =
+ node is VariableDeclaration && !node.isCovariant;
@override
void accept(StatementVisitor visitor) => visitor.visitTypeCheck(this);
@@ -546,21 +559,21 @@
}
@override
- Type apply(List<Type> computedTypes, TypeHierarchy typeHierarchy,
+ Type apply(List<Type?> computedTypes, TypeHierarchy typeHierarchy,
CallHandler callHandler) {
Type argType = arg.getComputedType(computedTypes);
Type checkType = type.getComputedType(computedTypes);
// TODO(sjindel/tfa): Narrow the result if possible.
assert(checkType is UnknownType || checkType is RuntimeType);
- bool canSkip = true; // Can this check be skipped on this invocation.
+ bool pass = true; // Can this check be skipped on this invocation.
if (checkType is UnknownType) {
// If we don't know what the RHS of the check is going to be, we can't
// guarantee that it will pass.
- canSkip = false;
+ pass = false;
} else if (checkType is RuntimeType) {
- canSkip = argType.isSubtypeOfRuntimeType(typeHierarchy, checkType);
+ pass = argType.isSubtypeOfRuntimeType(typeHierarchy, checkType, kind);
argType = argType.intersection(
typeHierarchy.fromStaticType(checkType.representedTypeRaw, true),
typeHierarchy);
@@ -571,8 +584,8 @@
// If this check might be skipped on an
// unchecked entry-point, we need to signal that the call-site must be
// checked.
- if (!canSkip) {
- canAlwaysSkip = false;
+ if (!pass) {
+ alwaysPass = false;
if (isTestedOnlyOnCheckedEntryPoint) {
callHandler.typeCheckTriggered();
}
@@ -581,7 +594,13 @@
}
}
- argType = argType.intersection(staticType, typeHierarchy);
+ argType = argType
+ .intersection(staticType, typeHierarchy)
+ .specialize(typeHierarchy);
+
+ if (argType is! EmptyType) {
+ alwaysFail = false;
+ }
return argType;
}
@@ -596,11 +615,11 @@
int requiredParameterCount;
List<Statement> _statements = <Statement>[];
- TypeExpr result = null;
- Type resultType = EmptyType();
+ TypeExpr result = const EmptyType();
+ Type resultType = const EmptyType();
// Analysis time of callees. Populated only if kPrintTimings.
- int calleeTime;
+ int calleeTime = 0;
Summary(this.name,
{this.parameterCount: 0,
@@ -630,7 +649,7 @@
/// Apply this summary to the given arguments and return the resulting type.
Type apply(Args<Type> arguments, TypeHierarchy typeHierarchy,
CallHandler callHandler) {
- final Stopwatch timer = kPrintTimings ? (new Stopwatch()..start()) : null;
+ final Stopwatch? timer = kPrintTimings ? (new Stopwatch()..start()) : null;
final int oldCalleeTime = calleeTime;
calleeTime = 0;
final args = arguments.values;
@@ -649,7 +668,7 @@
//
// The first `parameterCount` statements are Parameters.
- List<Type> types = new List<Type>.filled(_statements.length, null);
+ List<Type?> types = new List<Type?>.filled(_statements.length, null);
for (int i = 0; i < positionalArgCount; i++) {
final Parameter param = _statements[i] as Parameter;
@@ -659,9 +678,9 @@
}
final argType = args[i].specialize(typeHierarchy);
param._observeArgumentType(argType, typeHierarchy);
- if (param.staticTypeForNarrowing != null) {
- types[i] =
- argType.intersection(param.staticTypeForNarrowing, typeHierarchy);
+ final staticTypeForNarrowing = param.staticTypeForNarrowing;
+ if (staticTypeForNarrowing != null) {
+ types[i] = argType.intersection(staticTypeForNarrowing, typeHierarchy);
} else {
// TODO(sjindel/tfa): Narrowing is performed inside a [TypeCheck] later.
types[i] = args[i];
@@ -682,9 +701,10 @@
args[positionalArgCount + argIndex].specialize(typeHierarchy);
argIndex++;
param._observeArgumentType(argType, typeHierarchy);
- if (param.staticTypeForNarrowing != null) {
+ final staticTypeForNarrowing = param.staticTypeForNarrowing;
+ if (staticTypeForNarrowing != null) {
types[i] =
- argType.intersection(param.staticTypeForNarrowing, typeHierarchy);
+ argType.intersection(staticTypeForNarrowing, typeHierarchy);
} else {
types[i] = argType;
}
@@ -713,7 +733,7 @@
resultType = resultType.union(computedType, typeHierarchy);
if (kPrintTimings) {
- final dirtyTime = timer.elapsedMicroseconds;
+ final dirtyTime = timer!.elapsedMicroseconds;
final pureTime = dirtyTime < calleeTime ? 0 : (dirtyTime - calleeTime);
Statistics.numSummaryApplications.add(name);
Statistics.dirtySummaryAnalysisTime.add(name, dirtyTime);
@@ -725,9 +745,9 @@
}
Args<Type> get argumentTypes {
- final argTypes = new List<Type>.filled(parameterCount, null);
- final argNames = new List<String>.filled(
- parameterCount - positionalParameterCount, null);
+ final argTypes = new List<Type>.filled(parameterCount, const EmptyType());
+ final argNames =
+ new List<String>.filled(parameterCount - positionalParameterCount, '');
for (int i = 0; i < parameterCount; i++) {
Parameter param = _statements[i] as Parameter;
argTypes[i] = param.argumentType;
@@ -741,7 +761,7 @@
Type argumentType(Member member, VariableDeclaration memberParam) {
final int firstParamIndex =
numTypeParams(member) + (hasReceiverArg(member) ? 1 : 0);
- final positional = member.function.positionalParameters;
+ final positional = member.function!.positionalParameters;
for (int i = 0; i < positional.length; i++) {
if (positional[i] == memberParam) {
final Parameter param = _statements[firstParamIndex + i] as Parameter;
@@ -762,9 +782,9 @@
final params = <VariableDeclaration>[];
for (Statement statement in _statements) {
if (statement is TypeCheck &&
- statement.canAlwaysSkip &&
- statement.parameter != null) {
- params.add(statement.parameter);
+ statement.alwaysPass &&
+ statement.isParameterCheck) {
+ params.add(statement.parameterVariable);
}
}
return params;
@@ -780,17 +800,17 @@
(hasReceiverArg(member) ? 1 : 0) + numTypeParams(member);
final Map<String, Parameter> paramsByName = {};
for (int i = implicit; i < parameterCount; i++) {
- final Parameter param = statements[i];
+ final Parameter param = statements[i] as Parameter;
paramsByName[param.name] = param;
}
- FunctionNode function = member.function;
+ FunctionNode function = member.function!;
statements.length = implicit;
for (VariableDeclaration param in function.positionalParameters) {
- statements.add(paramsByName[param.name]);
+ statements.add(paramsByName[param.name]!);
}
positionalParameterCount = statements.length;
for (VariableDeclaration param in function.namedParameters) {
- statements.add(paramsByName[param.name]);
+ statements.add(paramsByName[param.name]!);
}
parameterCount = statements.length;
requiredParameterCount = implicit + function.requiredParameterCount;
diff --git a/pkg/vm/lib/transformations/type_flow/summary_collector.dart b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
index fac8e00..9905fcc 100644
--- a/pkg/vm/lib/transformations/type_flow/summary_collector.dart
+++ b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
@@ -3,7 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
/// Creation of type flow summaries out of kernel AST.
-library vm.transformations.type_flow.summary_collector;
import 'dart:core' hide Type;
@@ -12,6 +11,7 @@
import 'package:kernel/ast.dart' as ast show Statement, StatementVisitor;
import 'package:kernel/class_hierarchy.dart'
show ClassHierarchy, ClosedWorldClassHierarchy;
+import 'package:kernel/core_types.dart' show CoreTypes;
import 'package:kernel/type_environment.dart'
show StaticTypeContext, SubtypeCheckMode, TypeEnvironment;
import 'package:kernel/type_algebra.dart' show Substitution;
@@ -127,8 +127,13 @@
// This pattern may appear after approximations during summary
// normalization (so it's not enough to handle it in _makeNarrow).
final arg = st.arg;
- if (arg is Type && st.type == const AnyType()) {
- return (arg is NullableType) ? arg.baseType : arg;
+ if (st.type is AnyType) {
+ if (arg is Type) {
+ return (arg is NullableType) ? arg.baseType : arg;
+ }
+ if (arg is Call && arg.isInstanceCreation) {
+ return arg;
+ }
}
}
@@ -232,7 +237,7 @@
// function and checks if control can fall through them or not.
bool controlCanFallThrough(FunctionNode function) {
- return function.body.accept(this);
+ return function.body!.accept(this);
}
@override
@@ -278,11 +283,11 @@
bool visitContinueSwitchStatement(ContinueSwitchStatement node) => false;
@override
- bool visitIfStatement(IfStatement node) =>
- node.then == null ||
- node.otherwise == null ||
- node.then.accept(this) ||
- node.otherwise.accept(this);
+ bool visitIfStatement(IfStatement node) {
+ final otherwise = node.otherwise;
+ if (otherwise == null) return true;
+ return node.then.accept(this) || otherwise.accept(this);
+ }
@override
bool visitReturnStatement(ReturnStatement node) => false;
@@ -316,7 +321,7 @@
final List<VariableDeclaration> varDeclarations = <VariableDeclaration>[];
/// Set of captured variables.
- Set<VariableDeclaration> captured;
+ Set<VariableDeclaration>? captured;
/// Set of variables which were modified for each loop, switch statement
/// and try block statement. Doesn't include captured variables and
@@ -327,10 +332,10 @@
int numVariablesAtFunctionEntry = 0;
/// Active loops, switch statements and try blocks.
- List<ast.Statement> activeStatements;
+ List<ast.Statement>? activeStatements;
/// Number of variables at entry of active statements.
- List<int> numVariablesAtActiveStatements;
+ List<int>? numVariablesAtActiveStatements;
_VariablesInfoCollector(Member member) {
member.accept(this);
@@ -338,8 +343,10 @@
int get numVariables => varDeclarations.length;
- bool isCaptured(VariableDeclaration variable) =>
- captured != null && captured.contains(variable);
+ bool isCaptured(VariableDeclaration variable) {
+ final captured = this.captured;
+ return captured != null && captured.contains(variable);
+ }
Set<int> getModifiedVariables(ast.Statement st) {
return modifiedSets[st] ?? const <int>{};
@@ -380,14 +387,15 @@
}
void _useVariable(VariableDeclaration variable, bool isVarAssignment) {
- final index = varIndex[variable];
+ final index = varIndex[variable]!;
if (_isDeclaredBefore(index, numVariablesAtFunctionEntry)) {
_captureVariable(variable);
return;
}
+ final activeStatements = this.activeStatements;
if (isVarAssignment && activeStatements != null) {
for (int i = activeStatements.length - 1; i >= 0; --i) {
- if (_isDeclaredBefore(index, numVariablesAtActiveStatements[i])) {
+ if (_isDeclaredBefore(index, numVariablesAtActiveStatements![i])) {
final st = activeStatements[i];
(modifiedSets[st] ??= <int>{}).add(index);
} else {
@@ -403,8 +411,8 @@
}
void _endCollectingModifiedVariables() {
- activeStatements.removeLast();
- numVariablesAtActiveStatements.removeLast();
+ activeStatements!.removeLast();
+ numVariablesAtActiveStatements!.removeLast();
}
@override
@@ -450,7 +458,7 @@
@override
visitTryCatch(TryCatch node) {
_startCollectingModifiedVariables(node);
- node.body?.accept(this);
+ node.body.accept(this);
_endCollectingModifiedVariables();
visitList(node.catches, this);
}
@@ -458,9 +466,9 @@
@override
visitTryFinally(TryFinally node) {
_startCollectingModifiedVariables(node);
- node.body?.accept(this);
+ node.body.accept(this);
_endCollectingModifiedVariables();
- node.finalizer?.accept(this);
+ node.finalizer.accept(this);
}
@override
@@ -482,7 +490,7 @@
visitList(node.variables, this);
_startCollectingModifiedVariables(node);
node.condition?.accept(this);
- node.body?.accept(this);
+ node.body.accept(this);
visitList(node.updates, this);
_endCollectingModifiedVariables();
}
@@ -514,7 +522,7 @@
enum FieldSummaryType { kFieldGuard, kInitializer }
/// Create a type flow summary for a member from the kernel AST.
-class SummaryCollector extends RecursiveResultVisitor<TypeExpr> {
+class SummaryCollector extends RecursiveResultVisitor<TypeExpr?> {
final Target target;
final TypeEnvironment _environment;
final ClosedWorldClassHierarchy _hierarchy;
@@ -522,23 +530,24 @@
final TypesBuilder _typesBuilder;
final NativeCodeOracle _nativeCodeOracle;
final GenericInterfacesInfo _genericInterfacesInfo;
- final ProtobufHandler _protobufHandler;
+ final ProtobufHandler? _protobufHandler;
final Map<TreeNode, Call> callSites = <TreeNode, Call>{};
final Map<AsExpression, TypeCheck> explicitCasts =
<AsExpression, TypeCheck>{};
+ final Map<IsExpression, TypeCheck> isTests = <IsExpression, TypeCheck>{};
final Map<TreeNode, NarrowNotNull> nullTests = <TreeNode, NarrowNotNull>{};
final _FallthroughDetector _fallthroughDetector = new _FallthroughDetector();
final Set<Name> _nullMethodsAndGetters = <Name>{};
final Set<Name> _nullSetters = <Name>{};
- Summary _summary;
- _VariablesInfoCollector _variablesInfo;
+ Summary _summary = Summary('<unused>');
+ late _VariablesInfoCollector _variablesInfo;
// Current value of each variable. May contain null if variable is not
// declared yet, or EmptyType if current location is unreachable
// (e.g. after return or throw).
- List<TypeExpr> _variableValues;
+ List<TypeExpr?> _variableValues = const <TypeExpr?>[];
// Contains Joins which accumulate all values of certain variables.
// Used only when all variable values should be merged regardless of control
@@ -550,30 +559,30 @@
// If _variableCells[i] != null, then all values are accumulated in the
// _variableCells[i]. _variableValues[i] does not change and remains equal
// to _variableCells[i].
- List<Join> _variableCells;
+ List<Join?> _variableCells = const <Join?>[];
// Counts number of Joins inserted for each variable. Only used to set
// readable names for such joins (foo_0, foo_1 etc.)
- List<int> _variableVersions;
+ List<int> _variableVersions = const <int>[];
// State of variables after corresponding LabeledStatement.
// Used to collect states from BreakStatements.
- Map<LabeledStatement, List<TypeExpr>> _variableValuesAfterLabeledStatements;
+ Map<LabeledStatement, List<TypeExpr?>>? _variableValuesAfterLabeledStatements;
// Joins corresponding to variables on entry to switch cases.
// Used to propagate state from ContinueSwitchStatement to a target case.
- Map<SwitchCase, List<Join>> _joinsAtSwitchCases;
+ Map<SwitchCase, List<Join?>>? _joinsAtSwitchCases;
// Join which accumulates all return values.
- Join _returnValue;
+ Join? _returnValue;
- Parameter _receiver;
- ConstantAllocationCollector constantAllocationCollector;
- RuntimeTypeTranslatorImpl _translator;
- StaticTypeContext _staticTypeContext;
+ Parameter? _receiver;
+ late ConstantAllocationCollector constantAllocationCollector;
+ late RuntimeTypeTranslatorImpl _translator;
+ StaticTypeContext? _staticTypeContext;
// Currently only used for factory constructors.
- Map<TypeParameter, TypeExpr> _fnTypeVariables;
+ Map<TypeParameter, TypeExpr>? _fnTypeVariables;
SummaryCollector(
this.target,
@@ -584,7 +593,6 @@
this._nativeCodeOracle,
this._genericInterfacesInfo,
this._protobufHandler) {
- assert(_genericInterfacesInfo != null);
constantAllocationCollector = new ConstantAllocationCollector(this);
_nullMethodsAndGetters.addAll(getSelectors(
_hierarchy, _environment.coreTypes.deprecatedNullClass,
@@ -600,15 +608,15 @@
"${member}${fieldSummaryType == FieldSummaryType.kFieldGuard ? " (guard)" : ""}";
debugPrint("===== $summaryName =====");
assert(!member.isAbstract);
- assert(!(member is Procedure && member.isRedirectingFactoryConstructor));
+ assert(!(member is Procedure && member.isRedirectingFactory));
_protobufHandler?.beforeSummaryCreation(member);
_staticTypeContext = new StaticTypeContext(member, _environment);
_variablesInfo = new _VariablesInfoCollector(member);
_variableValues =
- new List<TypeExpr>.filled(_variablesInfo.numVariables, null);
- _variableCells = new List<Join>.filled(_variablesInfo.numVariables, null);
+ new List<TypeExpr?>.filled(_variablesInfo.numVariables, null);
+ _variableCells = new List<Join?>.filled(_variablesInfo.numVariables, null);
_variableVersions = new List<int>.filled(_variablesInfo.numVariables, 0);
_variableValuesAfterLabeledStatements = null;
_joinsAtSwitchCases = null;
@@ -625,25 +633,24 @@
parameterCount: numArgs, positionalParameterCount: numArgs);
// TODO(alexmarkov): subclass cone
_receiver = _declareParameter("this",
- _environment.coreTypes.legacyRawType(member.enclosingClass), null,
+ _environment.coreTypes.legacyRawType(member.enclosingClass!), null,
isReceiver: true);
} else {
_summary = new Summary(summaryName);
}
- _translator = new RuntimeTypeTranslatorImpl(
- this, _summary, _receiver, null, _genericInterfacesInfo);
+ _translator = new RuntimeTypeTranslatorImpl(_environment.coreTypes,
+ _summary, _receiver, null, _genericInterfacesInfo);
if (fieldSummaryType == FieldSummaryType.kInitializer) {
- assert(member.initializer != null);
- _summary.result = _visit(member.initializer);
+ _summary.result = _visit(member.initializer!);
} else {
final Parameter valueParam =
_declareParameter("value", member.type, null);
_summary.result = _typeCheck(valueParam, member.type, member);
}
} else {
- FunctionNode function = member.function;
+ final FunctionNode function = member.function!;
final numTypeParameters = numTypeParams(member);
final firstParamIndex = (hasReceiver ? 1 : 0) + numTypeParameters;
@@ -658,43 +665,42 @@
firstParamIndex + function.requiredParameterCount);
if (numTypeParameters > 0) {
- _fnTypeVariables = <TypeParameter, TypeExpr>{};
- for (int i = 0; i < numTypeParameters; ++i) {
- _fnTypeVariables[function.typeParameters[i]] =
- _declareParameter(function.typeParameters[i].name, null, null);
- }
+ _fnTypeVariables = <TypeParameter, TypeExpr>{
+ for (TypeParameter tp in function.typeParameters)
+ tp: _declareParameter(tp.name!, null, null)
+ };
}
if (hasReceiver) {
// TODO(alexmarkov): subclass cone
_receiver = _declareParameter("this",
- _environment.coreTypes.legacyRawType(member.enclosingClass), null,
+ _environment.coreTypes.legacyRawType(member.enclosingClass!), null,
isReceiver: true);
}
- _translator = new RuntimeTypeTranslatorImpl(
- this, _summary, _receiver, _fnTypeVariables, _genericInterfacesInfo);
+ _translator = new RuntimeTypeTranslatorImpl(_environment.coreTypes,
+ _summary, _receiver, _fnTypeVariables, _genericInterfacesInfo);
// Handle forwarding stubs. We need to check types against the types of
// the forwarding stub's target, [member.concreteForwardingStubTarget].
- FunctionNode useTypesFrom = member.function;
- if (member is Procedure &&
- member.isForwardingStub &&
- member.concreteForwardingStubTarget != null) {
+ FunctionNode useTypesFrom = function;
+ if (member is Procedure && member.isForwardingStub) {
final target = member.concreteForwardingStubTarget;
- if (target is Field) {
- useTypesFrom = FunctionNode(null, positionalParameters: [
- VariableDeclaration("value", type: target.type)
- ]);
- } else {
- useTypesFrom = member.concreteForwardingStubTarget.function;
+ if (target != null) {
+ if (target is Field) {
+ useTypesFrom = FunctionNode(null, positionalParameters: [
+ VariableDeclaration("value", type: target.type)
+ ]);
+ } else {
+ useTypesFrom = target.function!;
+ }
}
}
for (int i = 0; i < function.positionalParameters.length; ++i) {
final decl = function.positionalParameters[i];
_declareParameter(
- decl.name,
+ decl.name!,
_useTypeCheckForParameter(decl)
? null
: useTypesFrom.positionalParameters[i].type,
@@ -703,7 +709,7 @@
for (int i = 0; i < function.namedParameters.length; ++i) {
final decl = function.namedParameters[i];
_declareParameter(
- decl.name,
+ decl.name!,
_useTypeCheckForParameter(decl)
? null
: useTypesFrom.namedParameters[i].type,
@@ -732,7 +738,7 @@
assert(count == _summary.parameterCount);
_returnValue = new Join("%result", function.returnType);
- _summary.add(_returnValue);
+ _summary.add(_returnValue!);
if (member is Constructor) {
// Make sure instance field initializers are visited.
@@ -742,7 +748,7 @@
new DirectSelector(f, callKind: CallKind.FieldInitializer));
}
}
- member.initializers.forEach(_visit);
+ member.initializers.forEach(_visitWithoutResult);
}
if (function.body == null) {
@@ -752,15 +758,15 @@
// Runtime type could be more precise than static type, so
// calculate intersection.
final typeCheck = _typeCheck(type, function.returnType, function);
- _returnValue.values.add(typeCheck);
+ _returnValue!.values.add(typeCheck);
} else {
- _returnValue.values.add(type);
+ _returnValue!.values.add(type);
}
} else {
- _visit(function.body);
+ _visitWithoutResult(function.body!);
if (_fallthroughDetector.controlCanFallThrough(function)) {
- _returnValue.values.add(_nullType);
+ _returnValue!.values.add(_nullType);
}
}
@@ -768,15 +774,15 @@
// In addition to what is returned from the function body,
// operator == performs implicit comparison with null
// and returns bool.
- _returnValue.values.add(_boolType);
+ _returnValue!.values.add(_boolType);
}
- _summary.result = _returnValue;
+ _summary.result = _returnValue!;
}
member.annotations.forEach(_visit);
- member.enclosingClass?.annotations?.forEach(_visit);
- member.enclosingLibrary?.annotations?.forEach(_visit);
+ member.enclosingClass?.annotations.forEach(_visit);
+ member.enclosingLibrary.annotations.forEach(_visit);
_staticTypeContext = null;
@@ -800,9 +806,7 @@
}
Args<Type> rawArguments(Selector selector) {
- final member = selector.member;
- assert(member != null);
-
+ final member = selector.member!;
final List<Type> args = <Type>[];
final List<String> names = <String>[];
@@ -814,15 +818,14 @@
if (hasReceiverArg(member)) {
assert(member.enclosingClass != null);
final receiver =
- new ConeType(_typesBuilder.getTFClass(member.enclosingClass));
+ new ConeType(_typesBuilder.getTFClass(member.enclosingClass!));
args.add(receiver);
}
switch (selector.callKind) {
case CallKind.Method:
if (member is! Field) {
- final function = member.function;
- assert(function != null);
+ final function = member.function!;
final int paramCount = function.positionalParameters.length +
function.namedParameters.length;
@@ -832,7 +835,7 @@
if (function.namedParameters.isNotEmpty) {
for (var param in function.namedParameters) {
- names.add(param.name);
+ names.add(param.name!);
}
// TODO(dartbug.com/32292): make sure parameters are sorted in
// kernel AST and remove this sorting.
@@ -856,11 +859,15 @@
return new Args<Type>(args, names: names);
}
- TypeExpr _visit(TreeNode node) => node.accept(this);
+ TypeExpr _visit(Expression node) => node.accept(this)!;
- Args<TypeExpr> _visitArguments(TypeExpr receiver, Arguments arguments,
+ void _visitWithoutResult(TreeNode node) {
+ node.accept(this);
+ }
+
+ Args<TypeExpr> _visitArguments(TypeExpr? receiver, Arguments arguments,
{bool passTypeArguments: false}) {
- final args = <TypeExpr>[];
+ final List<TypeExpr> args = <TypeExpr>[];
if (passTypeArguments) {
for (var type in arguments.types) {
args.add(_translator.translate(type));
@@ -882,7 +889,7 @@
}
names.sort();
for (var name in names) {
- args.add(map[name]);
+ args.add(map[name]!);
}
return new Args<TypeExpr>(args, names: names);
} else {
@@ -891,9 +898,9 @@
}
Parameter _declareParameter(
- String name, DartType type, Expression initializer,
+ String name, DartType? type, Expression? initializer,
{bool isReceiver: false}) {
- Type staticType;
+ Type? staticType;
if (type != null) {
staticType = _typesBuilder.fromStaticType(type, !isReceiver);
}
@@ -908,7 +915,7 @@
} else if (initializer is BasicLiteral ||
initializer is SymbolLiteral ||
initializer is TypeLiteral) {
- param.defaultValue = _visit(initializer);
+ param.defaultValue = _visit(initializer) as Type;
} else {
throw 'Unexpected parameter $name default value ${initializer.runtimeType} $initializer';
}
@@ -922,8 +929,7 @@
}
void _declareVariable(VariableDeclaration decl, TypeExpr initialValue) {
- final int varIndex = _variablesInfo.varIndex[decl];
- assert(varIndex != null);
+ final int varIndex = _variablesInfo.varIndex[decl]!;
assert(_variablesInfo.varDeclarations[varIndex] == decl);
assert(_variableValues[varIndex] == null);
if (_variablesInfo.isCaptured(decl)) {
@@ -936,8 +942,8 @@
}
void _writeVariable(VariableDeclaration variable, TypeExpr value) {
- final int varIndex = _variablesInfo.varIndex[variable];
- final Join join = _variableCells[varIndex];
+ final int varIndex = _variablesInfo.varIndex[variable]!;
+ final Join? join = _variableCells[varIndex];
if (join != null) {
join.values.add(value);
} else {
@@ -945,11 +951,12 @@
}
}
- List<TypeExpr> _cloneVariableValues(List<TypeExpr> values) =>
- new List<TypeExpr>.from(values);
+ List<TypeExpr?> _cloneVariableValues(List<TypeExpr?> values) =>
+ new List<TypeExpr?>.from(values);
- List<TypeExpr> _makeEmptyVariableValues() {
- final values = new List<TypeExpr>.filled(_variablesInfo.numVariables, null);
+ List<TypeExpr?> _makeEmptyVariableValues() {
+ final values =
+ new List<TypeExpr?>.filled(_variablesInfo.numVariables, null);
for (int i = 0; i < values.length; ++i) {
if (_variableCells[i] != null) {
values[i] = _variableValues[i];
@@ -970,11 +977,11 @@
return join;
}
- void _mergeVariableValues(List<TypeExpr> dst, List<TypeExpr> src) {
+ void _mergeVariableValues(List<TypeExpr?> dst, List<TypeExpr?> src) {
assert(dst.length == src.length);
for (int i = 0; i < dst.length; ++i) {
- final TypeExpr dstValue = dst[i];
- final TypeExpr srcValue = src[i];
+ final TypeExpr? dstValue = dst[i];
+ final TypeExpr? srcValue = src[i];
if (identical(dstValue, srcValue)) {
continue;
}
@@ -989,21 +996,21 @@
} else if (srcValue is Join && srcValue.values.contains(dstValue)) {
dst[i] = srcValue;
} else {
- final Join join = _makeJoin(i, dst[i]);
- join.values.add(src[i]);
+ final Join join = _makeJoin(i, dstValue);
+ join.values.add(srcValue);
dst[i] = join;
}
}
}
- void _copyVariableValues(List<TypeExpr> dst, List<TypeExpr> src) {
+ void _copyVariableValues(List<TypeExpr?> dst, List<TypeExpr?> src) {
assert(dst.length == src.length);
for (int i = 0; i < dst.length; ++i) {
dst[i] = src[i];
}
}
- bool _isIdenticalState(List<TypeExpr> state1, List<TypeExpr> state2) {
+ bool _isIdenticalState(List<TypeExpr?> state1, List<TypeExpr?> state2) {
assert(state1.length == state2.length);
for (int i = 0; i < state1.length; ++i) {
if (!identical(state1[i], state2[i])) {
@@ -1013,14 +1020,14 @@
return true;
}
- List<Join> _insertJoinsForModifiedVariables(TreeNode node, bool isTry) {
- final List<Join> joins =
- new List<Join>.filled(_variablesInfo.numVariables, null);
+ List<Join?> _insertJoinsForModifiedVariables(ast.Statement node, bool isTry) {
+ final List<Join?> joins =
+ new List<Join?>.filled(_variablesInfo.numVariables, null);
for (var i in _variablesInfo.getModifiedVariables(node)) {
if (_variableCells[i] != null) {
assert(_variableCells[i] == _variableValues[i]);
} else {
- final join = _makeJoin(i, _variableValues[i]);
+ final join = _makeJoin(i, _variableValues[i]!);
joins[i] = join;
_variableValues[i] = join;
if (isTry) {
@@ -1036,7 +1043,7 @@
/// Stops accumulating values in [joins] by removing them from
/// _variableCells.
- void _restoreVariableCellsAfterTry(List<Join> joins) {
+ void _restoreVariableCellsAfterTry(List<Join?> joins) {
for (int i = 0; i < joins.length; ++i) {
if (joins[i] != null) {
assert(_variableCells[i] == joins[i]);
@@ -1045,37 +1052,43 @@
}
}
- void _mergeVariableValuesToJoins(List<TypeExpr> values, List<Join> joins) {
+ void _mergeVariableValuesToJoins(List<TypeExpr?> values, List<Join?> joins) {
for (int i = 0; i < joins.length; ++i) {
final join = joins[i];
final value = values[i];
if (join != null &&
!identical(join, value) &&
!identical(join.values.first, value)) {
- join.values.add(value);
+ join.values.add(value!);
}
}
}
- TypeCheck _typeCheck(TypeExpr value, DartType type, TreeNode node) {
+ TypeCheck _typeCheck(TypeExpr value, DartType type, TreeNode node,
+ [SubtypeTestKind kind = SubtypeTestKind.Subtype]) {
final TypeExpr runtimeType = _translator.translate(type);
- final typeCheck = new TypeCheck(
- value, runtimeType, node, _typesBuilder.fromStaticType(type, true));
+ final bool canBeNull = (kind == SubtypeTestKind.IsTest)
+ ? _canBeNullAfterSuccessfulIsCheck(type)
+ : true;
+ final typeCheck = new TypeCheck(value, runtimeType, node,
+ _typesBuilder.fromStaticType(type, canBeNull), kind);
_summary.add(typeCheck);
return typeCheck;
}
// TODO(alexmarkov): Avoid declaring variables with static types.
void _declareVariableWithStaticType(VariableDeclaration decl) {
- if (decl.initializer != null) {
- _visit(decl.initializer);
+ final initializer = decl.initializer;
+ if (initializer != null) {
+ _visit(initializer);
}
_declareVariable(decl, _typesBuilder.fromStaticType(decl.type, true));
}
- Call _makeCall(TreeNode node, Selector selector, Args<TypeExpr> args) {
- Type staticResultType = null;
- Member target;
+ Call _makeCall(TreeNode node, Selector selector, Args<TypeExpr> args,
+ {bool isInstanceCreation = false}) {
+ Type? staticResultType = null;
+ Member? target;
if (selector is DirectSelector) {
target = selector.member;
} else if (selector is InterfaceSelector) {
@@ -1086,11 +1099,9 @@
node is Expression) {
staticResultType = _staticType(node);
}
- Call call = new Call(selector, args, staticResultType);
+ Call call = new Call(selector, args, staticResultType, isInstanceCreation);
_summary.add(call);
- if (node != null) {
- callSites[node] = call;
- }
+ callSites[node] = call;
return call;
}
@@ -1109,6 +1120,8 @@
if (type == const AnyType()) {
return (arg is NullableType) ? arg.baseType : arg;
}
+ } else if (arg is Call && arg.isInstanceCreation && type is AnyType) {
+ return arg;
}
if (type is NullableType && type.baseType == const AnyType()) {
return arg;
@@ -1118,19 +1131,17 @@
return narrow;
}
- // Narrow type of [arg] after successful 'is' test against [type].
- TypeExpr _makeNarrowAfterSuccessfulIsCheck(TypeExpr arg, DartType type) {
+ bool _canBeNullAfterSuccessfulIsCheck(DartType type) {
// 'x is type' can succeed for null if type is
// - a top type (dynamic, void, Object? or Object*)
// - nullable (including Null)
// - a type parameter (it can be instantiated with Null)
// - legacy Never
final nullability = type.nullability;
- final bool canBeNull = _environment.isTop(type) ||
+ return _environment.isTop(type) ||
nullability == Nullability.nullable ||
type is TypeParameterType ||
(type is NeverType && nullability == Nullability.legacy);
- return _makeNarrow(arg, _typesBuilder.fromStaticType(type, canBeNull));
}
TypeExpr _makeNarrowNotNull(TreeNode node, TypeExpr arg) {
@@ -1176,53 +1187,43 @@
}
DartType _staticDartType(Expression node) =>
- node.getStaticType(_staticTypeContext);
+ node.getStaticType(_staticTypeContext!);
Type _staticType(Expression node) =>
_typesBuilder.fromStaticType(_staticDartType(node), true);
- ConcreteType _cachedBoolType;
- ConcreteType get _boolType => _cachedBoolType ??=
+ late final ConcreteType _boolType =
_entryPointsListener.addAllocatedClass(_environment.coreTypes.boolClass);
- ConcreteType _cachedBoolTrue;
- ConcreteType get _boolTrue => _cachedBoolTrue ??=
- new ConcreteType(_boolType.cls, null, BoolConstant(true));
+ late final ConcreteType _boolTrue =
+ ConcreteType(_boolType.cls, null, BoolConstant(true));
- ConcreteType _cachedBoolFalse;
- ConcreteType get _boolFalse => _cachedBoolFalse ??=
- new ConcreteType(_boolType.cls, null, BoolConstant(false));
+ late final ConcreteType _boolFalse =
+ ConcreteType(_boolType.cls, null, BoolConstant(false));
- Type _cachedDoubleType;
- Type get _doubleType => _cachedDoubleType ??= new ConeType(
- _typesBuilder.getTFClass(_environment.coreTypes.doubleClass));
+ late final Type _doubleType =
+ ConeType(_typesBuilder.getTFClass(_environment.coreTypes.doubleClass));
- Type _cachedIntType;
- Type get _intType => _cachedIntType ??=
- new ConeType(_typesBuilder.getTFClass(_environment.coreTypes.intClass));
+ late final Type _intType =
+ ConeType(_typesBuilder.getTFClass(_environment.coreTypes.intClass));
- Type _cachedStringType;
- Type get _stringType => _cachedStringType ??= new ConeType(
- _typesBuilder.getTFClass(_environment.coreTypes.stringClass));
+ late final Type _stringType =
+ ConeType(_typesBuilder.getTFClass(_environment.coreTypes.stringClass));
- Type _cachedSymbolType;
- Type get _symbolType => _cachedSymbolType ??= new ConeType(
- _typesBuilder.getTFClass(_environment.coreTypes.symbolClass));
+ late final Type _symbolType =
+ ConeType(_typesBuilder.getTFClass(_environment.coreTypes.symbolClass));
- Type _cachedTypeType;
- Type get _typeType => _cachedTypeType ??=
- new ConeType(_typesBuilder.getTFClass(_environment.coreTypes.typeClass));
+ late final Type _typeType =
+ ConeType(_typesBuilder.getTFClass(_environment.coreTypes.typeClass));
- Type _cachedNullType;
- Type get _nullType =>
- _cachedNullType ??= new Type.nullable(const EmptyType());
+ late final Type _nullType = Type.nullable(const EmptyType());
- Class get _superclass => _staticTypeContext.thisType.classNode.superclass;
+ Class get _superclass => _staticTypeContext!.thisType!.classNode.superclass!;
Type _boolLiteralType(bool value) => value ? _boolTrue : _boolFalse;
- Type _intLiteralType(int value, Constant constant) {
- final Class concreteClass =
+ Type _intLiteralType(int value, Constant? constant) {
+ final Class? concreteClass =
target.concreteIntLiteralClass(_environment.coreTypes, value);
if (concreteClass != null) {
constant ??= IntConstant(value);
@@ -1234,8 +1235,8 @@
return _intType;
}
- Type _doubleLiteralType(double value, Constant constant) {
- final Class concreteClass =
+ Type _doubleLiteralType(double value, Constant? constant) {
+ final Class? concreteClass =
target.concreteDoubleLiteralClass(_environment.coreTypes, value);
if (concreteClass != null) {
constant ??= DoubleConstant(value);
@@ -1247,8 +1248,8 @@
return _doubleType;
}
- Type _stringLiteralType(String value, Constant constant) {
- final Class concreteClass =
+ Type _stringLiteralType(String value, Constant? constant) {
+ final Class? concreteClass =
target.concreteStringLiteralClass(_environment.coreTypes, value);
if (concreteClass != null) {
constant ??= StringConstant(value);
@@ -1271,7 +1272,7 @@
node.positionalParameters.forEach(_declareVariableWithStaticType);
node.namedParameters.forEach(_declareVariableWithStaticType);
- _visit(node.body);
+ _visitWithoutResult(node.body!);
_variableValues = savedVariableValues;
_returnValue = savedReturn;
@@ -1294,8 +1295,7 @@
for (Class c
in _hierarchy.computeSubtypesInformation().getSubtypesOf(cls)) {
if (!c.isAbstract) {
- final candidate = _hierarchy.getDispatchTarget(c, _equalsName);
- assert(candidate != null);
+ final candidate = _hierarchy.getDispatchTarget(c, _equalsName)!;
assert(!candidate.isAbstract);
if (candidate != _environment.coreTypes.objectEquals) {
_cachedHasOverriddenEquals[cls] = true;
@@ -1315,12 +1315,12 @@
// On exit _variableValues is null, so caller should explicitly pick
// either trueState or falseState.
void _visitCondition(
- Expression node, List<TypeExpr> trueState, List<TypeExpr> falseState) {
+ Expression node, List<TypeExpr?> trueState, List<TypeExpr?> falseState) {
assert(_isIdenticalState(_variableValues, trueState));
assert(_isIdenticalState(_variableValues, falseState));
if (node is Not) {
_visitCondition(node.operand, falseState, trueState);
- _variableValues = null;
+ _variableValues = const <TypeExpr?>[]; // Should not be used.
return;
} else if (node is LogicalExpression) {
final isOR = (node.operatorEnum == LogicalExpressionOperator.OR);
@@ -1338,7 +1338,7 @@
_visitCondition(node.right, trueState, falseStateAfterRHS);
_mergeVariableValues(falseState, falseStateAfterRHS);
}
- _variableValues = null;
+ _variableValues = const <TypeExpr?>[]; // Should not be used.
return;
} else if (node is VariableGet ||
(node is AsExpression && node.operand is VariableGet)) {
@@ -1346,12 +1346,12 @@
_addUse(_visit(node));
final variableGet =
(node is AsExpression ? node.operand : node) as VariableGet;
- final int varIndex = _variablesInfo.varIndex[variableGet.variable];
+ final int varIndex = _variablesInfo.varIndex[variableGet.variable]!;
if (_variableCells[varIndex] == null) {
trueState[varIndex] = _boolTrue;
falseState[varIndex] = _boolFalse;
}
- _variableValues = null;
+ _variableValues = const <TypeExpr?>[]; // Should not be used.
return;
} else if (node is EqualsCall && node.left is VariableGet) {
final lhs = node.left as VariableGet;
@@ -1366,11 +1366,11 @@
!_hasOverriddenEquals(lhs.variable.type))) {
// 'x == c', where x is a variable and c is a constant.
_addUse(_visit(node));
- final int varIndex = _variablesInfo.varIndex[lhs.variable];
+ final int varIndex = _variablesInfo.varIndex[lhs.variable]!;
if (_variableCells[varIndex] == null) {
trueState[varIndex] = _visit(rhs);
}
- _variableValues = null;
+ _variableValues = const <TypeExpr?>[]; // Should not be used.
return;
}
} else if (node is EqualsNull && node.expression is VariableGet) {
@@ -1380,29 +1380,30 @@
_makeCall(node, DirectSelector(_environment.coreTypes.objectEquals),
Args<TypeExpr>([expr, _nullType]));
final narrowedNotNull = _makeNarrowNotNull(node, expr);
- final int varIndex = _variablesInfo.varIndex[lhs.variable];
+ final int varIndex = _variablesInfo.varIndex[lhs.variable]!;
if (_variableCells[varIndex] == null) {
trueState[varIndex] = _nullType;
falseState[varIndex] = narrowedNotNull;
}
- _variableValues = null;
+ _variableValues = const <TypeExpr?>[]; // Should not be used.
return;
} else if (node is IsExpression && node.operand is VariableGet) {
// Handle 'x is T', where x is a variable.
final operand = node.operand as VariableGet;
- _addUse(_visit(operand));
- final int varIndex = _variablesInfo.varIndex[operand.variable];
+ final TypeCheck typeCheck =
+ _typeCheck(_visit(operand), node.type, node, SubtypeTestKind.IsTest);
+ isTests[node] = typeCheck;
+ final int varIndex = _variablesInfo.varIndex[operand.variable]!;
if (_variableCells[varIndex] == null) {
- trueState[varIndex] =
- _makeNarrowAfterSuccessfulIsCheck(_visit(operand), node.type);
+ trueState[varIndex] = typeCheck;
}
- _variableValues = null;
+ _variableValues = const <TypeExpr?>[]; // Should not be used.
return;
}
_addUse(_visit(node));
_copyVariableValues(trueState, _variableValues);
_copyVariableValues(falseState, _variableValues);
- _variableValues = null;
+ _variableValues = const <TypeExpr?>[]; // Should not be used.
}
void _updateReceiverAfterCall(
@@ -1411,7 +1412,7 @@
if (receiverNode is VariableGet) {
final nullSelectors = isSetter ? _nullSetters : _nullMethodsAndGetters;
if (!nullSelectors.contains(selector)) {
- final int varIndex = _variablesInfo.varIndex[receiverNode.variable];
+ final int varIndex = _variablesInfo.varIndex[receiverNode.variable]!;
if (_variableCells[varIndex] == null) {
_variableValues[varIndex] =
_makeNarrow(receiverValue, const AnyType());
@@ -1420,9 +1421,8 @@
}
}
- Procedure _cachedUnsafeCast;
- Procedure get unsafeCast => _cachedUnsafeCast ??= _environment.coreTypes.index
- .getTopLevelMember('dart:_internal', 'unsafeCast');
+ late final Procedure unsafeCast = _environment.coreTypes.index
+ .getTopLevelProcedure('dart:_internal', 'unsafeCast');
@override
defaultTreeNode(TreeNode node) =>
@@ -1432,10 +1432,10 @@
TypeExpr visitAsExpression(AsExpression node) {
final operandNode = node.operand;
final TypeExpr operand = _visit(operandNode);
- final TypeExpr result = _typeCheck(operand, node.type, node);
+ final TypeCheck result = _typeCheck(operand, node.type, node);
explicitCasts[node] = result;
if (operandNode is VariableGet) {
- final int varIndex = _variablesInfo.varIndex[operandNode.variable];
+ final int varIndex = _variablesInfo.varIndex[operandNode.variable]!;
if (_variableCells[varIndex] == null) {
_variableValues[varIndex] = result;
}
@@ -1448,7 +1448,7 @@
final operandNode = node.operand;
final TypeExpr result = _makeNarrowNotNull(node, _visit(operandNode));
if (operandNode is VariableGet) {
- final int varIndex = _variablesInfo.varIndex[operandNode.variable];
+ final int varIndex = _variablesInfo.varIndex[operandNode.variable]!;
if (_variableCells[varIndex] == null) {
_variableValues[varIndex] = result;
}
@@ -1495,12 +1495,12 @@
@override
TypeExpr visitConstructorInvocation(ConstructorInvocation node) {
ConcreteType klass =
- _entryPointsListener.addAllocatedClass(node.constructedType.classNode);
+ _typesBuilder.getTFClass(node.constructedType.classNode).concreteType;
TypeExpr receiver =
_translator.instantiateConcreteType(klass, node.arguments.types);
final args = _visitArguments(receiver, node.arguments);
- _makeCall(node, new DirectSelector(node.target), args);
- return receiver;
+ return _makeCall(node, new DirectSelector(node.target), args,
+ isInstanceCreation: true);
}
@override
@@ -1525,26 +1525,30 @@
@override
TypeExpr visitIsExpression(IsExpression node) {
- _visit(node.operand);
+ final operandNode = node.operand;
+ final TypeExpr operand = _visit(operandNode);
+ final TypeCheck typeCheck =
+ _typeCheck(operand, node.type, node, SubtypeTestKind.IsTest);
+ isTests[node] = typeCheck;
return _boolType;
}
@override
TypeExpr visitLet(Let node) {
- _declareVariable(node.variable, _visit(node.variable.initializer));
+ _declareVariable(node.variable, _visit(node.variable.initializer!));
return _visit(node.body);
}
@override
TypeExpr visitBlockExpression(BlockExpression node) {
- _visit(node.body);
+ _visitWithoutResult(node.body);
return _visit(node.value);
}
@override
TypeExpr visitListLiteral(ListLiteral node) {
node.expressions.forEach(_visit);
- Class concreteClass =
+ Class? concreteClass =
target.concreteListLiteralClass(_environment.coreTypes);
if (concreteClass != null) {
return _translator.instantiateConcreteType(
@@ -1570,7 +1574,7 @@
_visit(entry.key);
_visit(entry.value);
}
- Class concreteClass =
+ Class? concreteClass =
target.concreteMapLiteralClass(_environment.coreTypes);
if (concreteClass != null) {
return _translator.instantiateConcreteType(
@@ -1672,7 +1676,7 @@
}
TypeExpr _handlePropertyGet(
- TreeNode node, Expression receiverNode, Member target, Name selector) {
+ TreeNode node, Expression receiverNode, Member? target, Name selector) {
var receiver = _visit(receiverNode);
var args = new Args<TypeExpr>([receiver]);
TypeExpr result;
@@ -1761,8 +1765,7 @@
@override
TypeExpr visitSuperPropertyGet(SuperPropertyGet node) {
assert(kPartialMixinResolution);
- assert(_receiver != null, "Should have receiver. Node: $node");
- final args = new Args<TypeExpr>([_receiver]);
+ final args = new Args<TypeExpr>([_receiver!]);
// Re-resolve target due to partial mixin resolution.
final target = _hierarchy.getDispatchTarget(_superclass, node.name);
if (target == null) {
@@ -1776,9 +1779,8 @@
@override
TypeExpr visitSuperPropertySet(SuperPropertySet node) {
assert(kPartialMixinResolution);
- assert(_receiver != null, "Should have receiver. Node: $node");
final value = _visit(node.value);
- final args = new Args<TypeExpr>([_receiver, value]);
+ final args = new Args<TypeExpr>([_receiver!, value]);
// Re-resolve target due to partial mixin resolution.
final target =
_hierarchy.getDispatchTarget(_superclass, node.name, setter: true);
@@ -1864,8 +1866,7 @@
@override
TypeExpr visitThisExpression(ThisExpression node) {
- assert(_receiver != null, "Should have receiver. Node: $node");
- return _receiver;
+ return _receiver!;
}
@override
@@ -1882,7 +1883,7 @@
@override
TypeExpr visitVariableGet(VariableGet node) {
- final v = _variableValues[_variablesInfo.varIndex[node.variable]];
+ final v = _variableValues[_variablesInfo.varIndex[node.variable]!];
if (v == null) {
throw 'Unable to find variable ${node.variable} at ${node.location}';
}
@@ -1907,56 +1908,60 @@
}
@override
- TypeExpr visitAssertStatement(AssertStatement node) {
+ TypeExpr? visitAssertStatement(AssertStatement node) {
if (!kRemoveAsserts) {
_addUse(_visit(node.condition));
- if (node.message != null) {
- _visit(node.message);
+ final message = node.message;
+ if (message != null) {
+ _visit(message);
}
}
return null;
}
@override
- TypeExpr visitBlock(Block node) {
- node.statements.forEach(_visit);
+ TypeExpr? visitBlock(Block node) {
+ node.statements.forEach(_visitWithoutResult);
return null;
}
@override
- TypeExpr visitAssertBlock(AssertBlock node) {
+ TypeExpr? visitAssertBlock(AssertBlock node) {
if (!kRemoveAsserts) {
- node.statements.forEach(_visit);
+ node.statements.forEach(_visitWithoutResult);
}
return null;
}
@override
- TypeExpr visitBreakStatement(BreakStatement node) {
- _variableValuesAfterLabeledStatements ??=
- <LabeledStatement, List<TypeExpr>>{};
- final state = _variableValuesAfterLabeledStatements[node.target];
+ TypeExpr? visitBreakStatement(BreakStatement node) {
+ var afterLabels = _variableValuesAfterLabeledStatements;
+ if (afterLabels == null) {
+ _variableValuesAfterLabeledStatements =
+ afterLabels = <LabeledStatement, List<TypeExpr?>>{};
+ }
+ final state = afterLabels[node.target];
if (state != null) {
_mergeVariableValues(state, _variableValues);
} else {
- _variableValuesAfterLabeledStatements[node.target] = _variableValues;
+ afterLabels[node.target] = _variableValues;
}
_variableValues = _makeEmptyVariableValues();
return null;
}
@override
- TypeExpr visitContinueSwitchStatement(ContinueSwitchStatement node) {
+ TypeExpr? visitContinueSwitchStatement(ContinueSwitchStatement node) {
_mergeVariableValuesToJoins(
- _variableValues, _joinsAtSwitchCases[node.target]);
+ _variableValues, _joinsAtSwitchCases![node.target]!);
_variableValues = _makeEmptyVariableValues();
return null;
}
@override
- TypeExpr visitDoStatement(DoStatement node) {
- final List<Join> joins = _insertJoinsForModifiedVariables(node, false);
- _visit(node.body);
+ TypeExpr? visitDoStatement(DoStatement node) {
+ final List<Join?> joins = _insertJoinsForModifiedVariables(node, false);
+ _visitWithoutResult(node.body);
final trueState = _cloneVariableValues(_variableValues);
final falseState = _cloneVariableValues(_variableValues);
_visitCondition(node.condition, trueState, falseState);
@@ -1970,39 +1975,39 @@
}
@override
- TypeExpr visitEmptyStatement(EmptyStatement node) => null;
+ TypeExpr? visitEmptyStatement(EmptyStatement node) => null;
@override
- TypeExpr visitExpressionStatement(ExpressionStatement node) {
+ TypeExpr? visitExpressionStatement(ExpressionStatement node) {
_visit(node.expression);
return null;
}
@override
- TypeExpr visitForInStatement(ForInStatement node) {
+ TypeExpr? visitForInStatement(ForInStatement node) {
_visit(node.iterable);
// TODO(alexmarkov): try to infer more precise type from 'iterable'
_declareVariableWithStaticType(node.variable);
- final List<Join> joins = _insertJoinsForModifiedVariables(node, false);
+ final List<Join?> joins = _insertJoinsForModifiedVariables(node, false);
final stateAfterLoop = _cloneVariableValues(_variableValues);
- _visit(node.body);
+ _visitWithoutResult(node.body);
_mergeVariableValuesToJoins(_variableValues, joins);
_variableValues = stateAfterLoop;
return null;
}
@override
- TypeExpr visitForStatement(ForStatement node) {
+ TypeExpr? visitForStatement(ForStatement node) {
node.variables.forEach(visitVariableDeclaration);
- final List<Join> joins = _insertJoinsForModifiedVariables(node, false);
+ final List<Join?> joins = _insertJoinsForModifiedVariables(node, false);
final trueState = _cloneVariableValues(_variableValues);
final falseState = _cloneVariableValues(_variableValues);
if (node.condition != null) {
- _visitCondition(node.condition, trueState, falseState);
+ _visitCondition(node.condition!, trueState, falseState);
}
_variableValues = trueState;
- _visit(node.body);
+ _visitWithoutResult(node.body);
node.updates.forEach(_visit);
_mergeVariableValuesToJoins(_variableValues, joins);
// Kernel represents 'break;' as a BreakStatement referring to a
@@ -2014,7 +2019,7 @@
}
@override
- TypeExpr visitFunctionDeclaration(FunctionDeclaration node) {
+ TypeExpr? visitFunctionDeclaration(FunctionDeclaration node) {
// TODO(alexmarkov): support function types.
node.variable.annotations.forEach(_visit);
_declareVariableWithStaticType(node.variable);
@@ -2023,18 +2028,18 @@
}
@override
- TypeExpr visitIfStatement(IfStatement node) {
+ TypeExpr? visitIfStatement(IfStatement node) {
final trueState = _cloneVariableValues(_variableValues);
final falseState = _cloneVariableValues(_variableValues);
_visitCondition(node.condition, trueState, falseState);
_variableValues = trueState;
- _visit(node.then);
+ _visitWithoutResult(node.then);
final stateAfter = _variableValues;
_variableValues = falseState;
if (node.otherwise != null) {
- _visit(node.otherwise);
+ _visitWithoutResult(node.otherwise!);
}
_mergeVariableValues(stateAfter, _variableValues);
@@ -2043,8 +2048,8 @@
}
@override
- TypeExpr visitLabeledStatement(LabeledStatement node) {
- _visit(node.body);
+ TypeExpr? visitLabeledStatement(LabeledStatement node) {
+ _visitWithoutResult(node.body);
final state = _variableValuesAfterLabeledStatements?.remove(node);
if (state != null) {
_mergeVariableValues(_variableValues, state);
@@ -2053,34 +2058,35 @@
}
@override
- TypeExpr visitReturnStatement(ReturnStatement node) {
- TypeExpr ret =
- (node.expression != null) ? _visit(node.expression) : _nullType;
- if (_returnValue != null) {
- _returnValue.values.add(ret);
- }
+ TypeExpr? visitReturnStatement(ReturnStatement node) {
+ final expression = node.expression;
+ TypeExpr ret = (expression != null) ? _visit(expression) : _nullType;
+ _returnValue?.values.add(ret);
_variableValues = _makeEmptyVariableValues();
return null;
}
@override
- TypeExpr visitSwitchStatement(SwitchStatement node) {
+ TypeExpr? visitSwitchStatement(SwitchStatement node) {
_visit(node.expression);
// Insert joins at each case in case there are 'continue' statements.
final stateOnEntry = _variableValues;
- final variableValuesAtCaseEntry = <SwitchCase, List<TypeExpr>>{};
- _joinsAtSwitchCases ??= <SwitchCase, List<Join>>{};
+ final variableValuesAtCaseEntry = <SwitchCase, List<TypeExpr?>>{};
+ Map<SwitchCase, List<Join?>>? joinsAtSwitchCases = _joinsAtSwitchCases;
+ if (joinsAtSwitchCases == null) {
+ _joinsAtSwitchCases = joinsAtSwitchCases = <SwitchCase, List<Join?>>{};
+ }
for (var switchCase in node.cases) {
_variableValues = _cloneVariableValues(stateOnEntry);
- _joinsAtSwitchCases[switchCase] =
+ joinsAtSwitchCases[switchCase] =
_insertJoinsForModifiedVariables(node, false);
variableValuesAtCaseEntry[switchCase] = _variableValues;
}
bool hasDefault = false;
for (var switchCase in node.cases) {
- _variableValues = variableValuesAtCaseEntry[switchCase];
+ _variableValues = variableValuesAtCaseEntry[switchCase]!;
switchCase.expressions.forEach(_visit);
- _visit(switchCase.body);
+ _visitWithoutResult(switchCase.body);
hasDefault = hasDefault || switchCase.isDefault;
}
if (!hasDefault) {
@@ -2090,21 +2096,21 @@
}
@override
- TypeExpr visitTryCatch(TryCatch node) {
+ TypeExpr? visitTryCatch(TryCatch node) {
final joins = _insertJoinsForModifiedVariables(node, true);
final stateAfterTry = _cloneVariableValues(_variableValues);
- _visit(node.body);
+ _visitWithoutResult(node.body);
_restoreVariableCellsAfterTry(joins);
- List<TypeExpr> stateAfterCatch;
+ List<TypeExpr?>? stateAfterCatch;
for (var catchClause in node.catches) {
_variableValues = _cloneVariableValues(stateAfterTry);
if (catchClause.exception != null) {
- _declareVariableWithStaticType(catchClause.exception);
+ _declareVariableWithStaticType(catchClause.exception!);
}
if (catchClause.stackTrace != null) {
- _declareVariableWithStaticType(catchClause.stackTrace);
+ _declareVariableWithStaticType(catchClause.stackTrace!);
}
- _visit(catchClause.body);
+ _visitWithoutResult(catchClause.body);
if (stateAfterCatch == null) {
stateAfterCatch = _variableValues;
} else {
@@ -2112,38 +2118,39 @@
}
}
_variableValues = stateAfterTry;
- _mergeVariableValues(_variableValues, stateAfterCatch);
+ _mergeVariableValues(_variableValues, stateAfterCatch!);
return null;
}
@override
- TypeExpr visitTryFinally(TryFinally node) {
+ TypeExpr? visitTryFinally(TryFinally node) {
final joins = _insertJoinsForModifiedVariables(node, true);
final stateAfterTry = _cloneVariableValues(_variableValues);
- _visit(node.body);
+ _visitWithoutResult(node.body);
_restoreVariableCellsAfterTry(joins);
_variableValues = stateAfterTry;
- _visit(node.finalizer);
+ _visitWithoutResult(node.finalizer);
return null;
}
@override
- TypeExpr visitVariableDeclaration(VariableDeclaration node) {
+ TypeExpr? visitVariableDeclaration(VariableDeclaration node) {
node.annotations.forEach(_visit);
+ final initializer = node.initializer;
final TypeExpr initialValue =
- node.initializer == null ? _nullType : _visit(node.initializer);
+ initializer == null ? _nullType : _visit(initializer);
_declareVariable(node, initialValue);
return null;
}
@override
- TypeExpr visitWhileStatement(WhileStatement node) {
- final List<Join> joins = _insertJoinsForModifiedVariables(node, false);
+ TypeExpr? visitWhileStatement(WhileStatement node) {
+ final List<Join?> joins = _insertJoinsForModifiedVariables(node, false);
final trueState = _cloneVariableValues(_variableValues);
final falseState = _cloneVariableValues(_variableValues);
_visitCondition(node.condition, trueState, falseState);
_variableValues = trueState;
- _visit(node.body);
+ _visitWithoutResult(node.body);
_mergeVariableValuesToJoins(_variableValues, joins);
// Kernel represents 'break;' as a BreakStatement referring to a
// LabeledStatement. We are therefore guaranteed to always have the
@@ -2154,15 +2161,15 @@
}
@override
- TypeExpr visitYieldStatement(YieldStatement node) {
+ TypeExpr? visitYieldStatement(YieldStatement node) {
_visit(node.expression);
return null;
}
@override
- TypeExpr visitFieldInitializer(FieldInitializer node) {
+ TypeExpr? visitFieldInitializer(FieldInitializer node) {
final value = _visit(node.value);
- final args = new Args<TypeExpr>([_receiver, value]);
+ final args = new Args<TypeExpr>([_receiver!, value]);
_makeCall(
node,
new DirectSelector(node.field,
@@ -2172,17 +2179,17 @@
}
@override
- TypeExpr visitRedirectingInitializer(RedirectingInitializer node) {
+ TypeExpr? visitRedirectingInitializer(RedirectingInitializer node) {
final args = _visitArguments(_receiver, node.arguments);
_makeCall(node, new DirectSelector(node.target), args);
return null;
}
@override
- TypeExpr visitSuperInitializer(SuperInitializer node) {
+ TypeExpr? visitSuperInitializer(SuperInitializer node) {
final args = _visitArguments(_receiver, node.arguments);
- Constructor target = null;
+ Constructor? target = null;
if (kPartialMixinResolution) {
// Re-resolve target due to partial mixin resolution.
for (var replacement in _superclass.constructors) {
@@ -2194,27 +2201,26 @@
} else {
target = node.target;
}
- assert(target != null);
- _makeCall(node, new DirectSelector(target), args);
+ _makeCall(node, new DirectSelector(target!), args);
return null;
}
@override
- TypeExpr visitLocalInitializer(LocalInitializer node) {
+ TypeExpr? visitLocalInitializer(LocalInitializer node) {
visitVariableDeclaration(node.variable);
return null;
}
@override
- TypeExpr visitAssertInitializer(AssertInitializer node) {
+ TypeExpr? visitAssertInitializer(AssertInitializer node) {
if (!kRemoveAsserts) {
- _visit(node.statement);
+ _visitWithoutResult(node.statement);
}
return null;
}
@override
- TypeExpr visitInvalidInitializer(InvalidInitializer node) {
+ TypeExpr? visitInvalidInitializer(InvalidInitializer node) {
return null;
}
@@ -2226,21 +2232,21 @@
class RuntimeTypeTranslatorImpl extends DartTypeVisitor<TypeExpr>
implements RuntimeTypeTranslator {
- final Summary summary;
- final Map<TypeParameter, TypeExpr> functionTypeVariables;
+ final CoreTypes coreTypes;
+ final Summary? summary;
+ final Map<TypeParameter, TypeExpr>? functionTypeVariables;
final Map<DartType, TypeExpr> typesCache = <DartType, TypeExpr>{};
- final TypeExpr receiver;
+ final TypeExpr? receiver;
final GenericInterfacesInfo genericInterfacesInfo;
- final SummaryCollector summaryCollector;
- RuntimeTypeTranslatorImpl(this.summaryCollector, this.summary, this.receiver,
+ RuntimeTypeTranslatorImpl(this.coreTypes, this.summary, this.receiver,
this.functionTypeVariables, this.genericInterfacesInfo) {}
// Create a type translator which can be used only for types with no free type
// variables.
- RuntimeTypeTranslatorImpl.forClosedTypes(this.genericInterfacesInfo)
- : summaryCollector = null,
- summary = null,
+ RuntimeTypeTranslatorImpl.forClosedTypes(
+ this.coreTypes, this.genericInterfacesInfo)
+ : summary = null,
functionTypeVariables = null,
receiver = null {}
@@ -2253,8 +2259,7 @@
final substitution = Substitution.fromPairs(klass.typeParameters, typeArgs);
final flattenedTypeArgs =
genericInterfacesInfo.flattenedTypeArgumentsFor(klass);
- final flattenedTypeExprs =
- new List<TypeExpr>.filled(flattenedTypeArgs.length, null);
+ final flattenedTypeExprs = <TypeExpr>[];
bool createConcreteType = true;
bool allUnknown = true;
@@ -2263,7 +2268,7 @@
translate(substitution.substituteType(flattenedTypeArgs[i]));
if (typeExpr is! UnknownType) allUnknown = false;
if (typeExpr is Statement) createConcreteType = false;
- flattenedTypeExprs[i] = typeExpr;
+ flattenedTypeExprs.add(typeExpr);
}
if (allUnknown) return type;
@@ -2273,7 +2278,7 @@
type.cls, new List<Type>.from(flattenedTypeExprs));
} else {
final instantiate = new CreateConcreteType(type.cls, flattenedTypeExprs);
- summary.add(instantiate);
+ summary!.add(instantiate);
return instantiate;
}
}
@@ -2323,8 +2328,7 @@
type.classNode.typeParameters, type.typeArguments);
final flattenedTypeArgs =
genericInterfacesInfo.flattenedTypeArgumentsFor(type.classNode);
- final flattenedTypeExprs =
- new List<TypeExpr>.filled(flattenedTypeArgs.length, null);
+ final flattenedTypeExprs = <TypeExpr>[];
bool createRuntimeType = true;
for (var i = 0; i < flattenedTypeArgs.length; ++i) {
@@ -2332,7 +2336,7 @@
translate(substitution.substituteType(flattenedTypeArgs[i]));
if (typeExpr == const UnknownType()) return const UnknownType();
if (typeExpr is! RuntimeType) createRuntimeType = false;
- flattenedTypeExprs[i] = typeExpr;
+ flattenedTypeExprs.add(typeExpr);
}
if (createRuntimeType) {
@@ -2342,7 +2346,7 @@
} else {
final instantiate = new CreateRuntimeType(
type.classNode, type.nullability, flattenedTypeExprs);
- summary.add(instantiate);
+ summary!.add(instantiate);
return instantiate;
}
}
@@ -2357,32 +2361,32 @@
<RuntimeType>[typeArg]);
} else {
final instantiate = new CreateRuntimeType(
- summaryCollector._environment.coreTypes.deprecatedFutureOrClass,
+ coreTypes.deprecatedFutureOrClass,
type.nullability,
<TypeExpr>[typeArg]);
- summary.add(instantiate);
+ summary!.add(instantiate);
return instantiate;
}
}
@override
visitTypeParameterType(TypeParameterType type) {
+ final functionTypeVariables = this.functionTypeVariables;
if (functionTypeVariables != null) {
final result = functionTypeVariables[type.parameter];
if (result != null) return result;
}
if (type.parameter.parent is! Class) return const UnknownType();
final interfaceClass = type.parameter.parent as Class;
- assert(receiver != null);
// Undetermined nullability is equivalent to nonNullable when
// instantiating type parameter, so convert it right away.
Nullability nullability = type.nullability;
if (nullability == Nullability.undetermined) {
nullability = Nullability.nonNullable;
}
- final extract = new Extract(receiver, interfaceClass,
+ final extract = new Extract(receiver!, interfaceClass,
interfaceClass.typeParameters.indexOf(type.parameter), nullability);
- summary.add(extract);
+ summary!.add(extract);
return extract;
}
}
@@ -2402,7 +2406,7 @@
Type _getStaticType(Constant constant) =>
summaryCollector._typesBuilder.fromStaticType(
- constant.getType(summaryCollector._staticTypeContext), false);
+ constant.getType(summaryCollector._staticTypeContext!), false);
@override
defaultConstant(Constant constant) {
@@ -2449,7 +2453,7 @@
for (final Constant entry in constant.entries) {
typeFor(entry);
}
- final Class concreteClass = summaryCollector.target
+ final Class? concreteClass = summaryCollector.target
.concreteConstListLiteralClass(summaryCollector._environment.coreTypes);
if (concreteClass != null) {
return new ConcreteType(
@@ -2475,7 +2479,16 @@
@override
Type visitStaticTearOffConstant(StaticTearOffConstant constant) {
- final Member member = constant.procedure;
+ final Procedure member = constant.target;
+ summaryCollector._entryPointsListener
+ .addRawCall(new DirectSelector(member));
+ summaryCollector._entryPointsListener.recordTearOff(member);
+ return _getStaticType(constant);
+ }
+
+ @override
+ Type visitConstructorTearOffConstant(ConstructorTearOffConstant constant) {
+ final Member member = constant.target;
summaryCollector._entryPointsListener
.addRawCall(new DirectSelector(member));
if (member is Constructor) {
diff --git a/pkg/vm/lib/transformations/type_flow/table_selector_assigner.dart b/pkg/vm/lib/transformations/type_flow/table_selector_assigner.dart
index 2cfe329..0080748 100644
--- a/pkg/vm/lib/transformations/type_flow/table_selector_assigner.dart
+++ b/pkg/vm/lib/transformations/type_flow/table_selector_assigner.dart
@@ -16,7 +16,7 @@
final Map<Class, Map<Name, int>> _methodOrSetterMemberIds = {};
final UnionFind _unionFind = UnionFind();
- List<int> _selectorIdForMemberId;
+ late List<int?> _selectorIdForMemberId;
TableSelectorAssigner(Component component) {
for (Library library in component.libraries) {
@@ -42,20 +42,21 @@
}
}
- Map<Name, int> _memberIdsForClass(Class cls, {bool getter}) {
+ Map<Name, int> _memberIdsForClass(Class? cls, {required bool getter}) {
if (cls == null) return {};
final cache = getter ? _getterMemberIds : _methodOrSetterMemberIds;
// Already computed for this class?
- Map<Name, int> memberIds = cache[cls];
- if (memberIds != null) return memberIds;
+ final cachedMemberIds = cache[cls];
+ if (cachedMemberIds != null) return cachedMemberIds;
// Merge maps from supertypes.
- memberIds = Map.from(_memberIdsForClass(cls.superclass, getter: getter));
+ final memberIds =
+ Map<Name, int>.from(_memberIdsForClass(cls.superclass, getter: getter));
for (Supertype impl in cls.implementedTypes) {
_memberIdsForClass(impl.classNode, getter: getter).forEach((name, id) {
- final int firstId = memberIds[name];
+ final int? firstId = memberIds[name];
if (firstId == null) {
memberIds[name] = id;
} else if (firstId != id) {
@@ -97,9 +98,9 @@
return cache[cls] = memberIds;
}
- int _selectorIdForMember(Member member, {bool getter}) {
+ int _selectorIdForMember(Member member, {required bool getter}) {
final map = getter ? _getterMemberIds : _methodOrSetterMemberIds;
- int memberId = map[member.enclosingClass][member.name];
+ int? memberId = map[member.enclosingClass!]![member.name];
if (memberId == null) {
assert(member is Procedure &&
((identical(map, _getterMemberIds) &&
@@ -113,7 +114,7 @@
return ProcedureAttributesMetadata.kInvalidSelectorId;
}
memberId = _unionFind.find(memberId);
- int selectorId = _selectorIdForMemberId[memberId];
+ int? selectorId = _selectorIdForMemberId[memberId];
if (selectorId == null) {
_selectorIdForMemberId[memberId] = selectorId = metadata.addSelector();
}
diff --git a/pkg/vm/lib/transformations/type_flow/transformer.dart b/pkg/vm/lib/transformations/type_flow/transformer.dart
index e9473dd..e964f61 100644
--- a/pkg/vm/lib/transformations/type_flow/transformer.dart
+++ b/pkg/vm/lib/transformations/type_flow/transformer.dart
@@ -3,15 +3,16 @@
// BSD-style license that can be found in the LICENSE file.
/// Transformations based on type flow analysis.
-library vm.transformations.type_flow.transformer;
import 'dart:core' hide Type;
import 'package:kernel/target/targets.dart';
import 'package:kernel/ast.dart' hide Statement, StatementVisitor;
+import 'package:kernel/ast.dart' as ast show Statement;
import 'package:kernel/clone.dart' show CloneVisitorNotMembers;
import 'package:kernel/core_types.dart' show CoreTypes;
-import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
+import 'package:kernel/class_hierarchy.dart'
+ show ClassHierarchy, ClosedWorldClassHierarchy;
import 'package:kernel/library_index.dart' show LibraryIndex;
import 'package:kernel/type_environment.dart';
@@ -40,16 +41,18 @@
/// Assumes strong mode and closed world.
Component transformComponent(
Target target, CoreTypes coreTypes, Component component,
- {PragmaAnnotationParser matcher,
+ {PragmaAnnotationParser? matcher,
bool treeShakeSignatures: true,
bool treeShakeWriteOnlyFields: true,
bool treeShakeProtobufs: false}) {
void ignoreAmbiguousSupertypes(Class cls, Supertype a, Supertype b) {}
final hierarchy = new ClassHierarchy(component, coreTypes,
- onAmbiguousSupertypes: ignoreAmbiguousSupertypes);
+ onAmbiguousSupertypes: ignoreAmbiguousSupertypes)
+ as ClosedWorldClassHierarchy;
final types = new TypeEnvironment(coreTypes, hierarchy);
final libraryIndex = new LibraryIndex.all(component);
- final genericInterfacesInfo = new GenericInterfacesInfoImpl(hierarchy);
+ final genericInterfacesInfo =
+ new GenericInterfacesInfoImpl(coreTypes, hierarchy);
final protobufHandler = treeShakeProtobufs
? ProtobufHandler.forComponent(component, coreTypes)
: null;
@@ -70,7 +73,7 @@
protobufHandler,
matcher);
- Procedure main = component.mainMethod;
+ Procedure? main = component.mainMethod;
// `main` can be null, roots can also come from @pragma("vm:entry-point").
if (main != null) {
@@ -146,7 +149,7 @@
if (!f.isStatic &&
!f.isLate &&
f.initializer != null &&
- mayHaveSideEffects(f.initializer))
+ mayHaveSideEffects(f.initializer!))
f
];
if (fields.isEmpty) return;
@@ -170,7 +173,7 @@
};
final List<Initializer> newInitializers = [];
for (Field f in fields) {
- Expression initExpr = f.initializer;
+ Expression initExpr = f.initializer!;
if (!isFirst) {
initExpr = CloneVisitorNotMembers().clone(initExpr);
}
@@ -201,7 +204,7 @@
class CleanupAnnotations extends RecursiveVisitor {
final Class externalNameClass;
final Class pragmaClass;
- final ProtobufHandler protobufHandler;
+ final ProtobufHandler? protobufHandler;
CleanupAnnotations(
CoreTypes coreTypes, LibraryIndex index, this.protobufHandler)
@@ -235,7 +238,7 @@
return (cls == externalNameClass) ||
(cls == pragmaClass) ||
(protobufHandler != null &&
- protobufHandler.usesAnnotationClass(cls));
+ protobufHandler!.usesAnnotationClass(cls));
}
}
return false;
@@ -252,11 +255,11 @@
: super(_typeFlowAnalysis.environment.coreTypes, component, hierarchy);
@override
- DirectCallMetadata getDirectCall(TreeNode node, Member interfaceTarget,
+ DirectCallMetadata? getDirectCall(TreeNode node, Member? interfaceTarget,
{bool setter = false}) {
final callSite = _typeFlowAnalysis.callSite(node);
if (callSite != null) {
- final Member singleTarget = fieldMorpher
+ final Member? singleTarget = fieldMorpher
.getMorphedMember(callSite.monomorphicTarget, isSetter: setter);
if (singleTarget != null) {
return new DirectCallMetadata(
@@ -280,12 +283,13 @@
final UnboxingInfoMetadataRepository _unboxingInfoMetadata;
final UnboxingInfoManager _unboxingInfo;
final Class _intClass;
- Constant _nullConstant;
+ late final Constant _nullConstant = NullConstant();
AnnotateKernel(Component component, this._typeFlowAnalysis, this.fieldMorpher,
this._tableSelectorAssigner, this._unboxingInfo)
: _directCallMetadataRepository =
- component.metadata[DirectCallMetadataRepository.repositoryTag],
+ component.metadata[DirectCallMetadataRepository.repositoryTag]
+ as DirectCallMetadataRepository,
_inferredTypeMetadata = new InferredTypeMetadataRepository(),
_unreachableNodeMetadata = new UnreachableNodeMetadataRepository(),
_procedureAttributesMetadata =
@@ -305,12 +309,10 @@
return _directCallMetadataRepository.mapping.containsKey(node);
}
- InferredType _convertType(Type type,
+ InferredType? _convertType(Type type,
{bool skipCheck: false, bool receiverNotInt: false}) {
- assert(type != null);
-
- Class concreteClass;
- Constant constantValue;
+ Class? concreteClass;
+ Constant? constantValue;
bool isInt = false;
final nullable = type is NullableType;
@@ -321,7 +323,7 @@
if (nullable && type == const EmptyType()) {
concreteClass =
_typeFlowAnalysis.environment.coreTypes.deprecatedNullClass;
- constantValue = _nullConstant ??= new NullConstant();
+ constantValue = _nullConstant;
} else {
concreteClass = type.getConcreteClass(_typeFlowAnalysis.hierarchyCache);
@@ -334,9 +336,9 @@
}
}
- List<DartType> typeArgs;
+ List<DartType?>? typeArgs;
if (type is ConcreteType && type.typeArgs != null) {
- typeArgs = type.typeArgs
+ typeArgs = type.typeArgs!
.take(type.numImmediateTypeArgs)
.map((t) =>
t is UnknownType ? null : (t as RuntimeType).representedType)
@@ -371,7 +373,7 @@
_unreachableNodeMetadata.mapping[node] = const UnreachableNode();
}
- void _annotateCallSite(TreeNode node, Member interfaceTarget) {
+ void _annotateCallSite(TreeNode node, Member? interfaceTarget) {
final callSite = _typeFlowAnalysis.callSite(node);
if (callSite == null) return;
if (!callSite.isReachable) {
@@ -402,7 +404,7 @@
if (interfaceTarget == null ||
_typeFlowAnalysis.hierarchyCache.hierarchy.isSubtypeOf(
_typeFlowAnalysis.hierarchyCache.coreTypes.intClass,
- interfaceTarget.enclosingClass)) {
+ interfaceTarget.enclosingClass!)) {
markReceiverNotInt = true;
}
}
@@ -443,35 +445,33 @@
void _annotateMember(Member member) {
if (_typeFlowAnalysis.isMemberUsed(member)) {
if (member is Field) {
- _setInferredType(member, _typeFlowAnalysis.fieldType(member));
+ _setInferredType(member, _typeFlowAnalysis.fieldType(member)!);
} else {
- Args<Type> argTypes = _typeFlowAnalysis.argumentTypes(member);
+ Args<Type> argTypes = _typeFlowAnalysis.argumentTypes(member)!;
final uncheckedParameters =
_typeFlowAnalysis.uncheckedParameters(member);
- assert(argTypes != null);
final int firstParamIndex =
numTypeParams(member) + (hasReceiverArg(member) ? 1 : 0);
- final positionalParams = member.function.positionalParameters;
+ final positionalParams = member.function!.positionalParameters;
assert(argTypes.positionalCount ==
firstParamIndex + positionalParams.length);
for (int i = 0; i < positionalParams.length; i++) {
_setInferredType(
positionalParams[i], argTypes.values[firstParamIndex + i],
- skipCheck: uncheckedParameters.contains(positionalParams[i]));
+ skipCheck: uncheckedParameters!.contains(positionalParams[i]));
}
// TODO(dartbug.com/32292): make sure parameters are sorted in kernel
// AST and iterate parameters in parallel, without lookup.
final names = argTypes.names;
for (int i = 0; i < names.length; i++) {
- final param = findNamedParameter(member.function, names[i]);
- assert(param != null);
+ final param = findNamedParameter(member.function!, names[i])!;
_setInferredType(param,
argTypes.values[firstParamIndex + positionalParams.length + i],
- skipCheck: uncheckedParameters.contains(param));
+ skipCheck: uncheckedParameters!.contains(param));
}
// TODO(alexmarkov): figure out how to pass receiver type.
@@ -518,7 +518,7 @@
// interface target, and table dispatch calls need selector IDs for all
// interface targets.
if (member.isInstanceMember) {
- final original = fieldMorpher.getOriginalMember(member);
+ final original = fieldMorpher.getOriginalMember(member)!;
final attrs = new ProcedureAttributesMetadata(
methodOrSetterCalledDynamically:
_typeFlowAnalysis.isCalledDynamically(original),
@@ -686,11 +686,11 @@
final Set<Member> _usedMembers = new Set<Member>();
final Set<Extension> _usedExtensions = new Set<Extension>();
final Set<Typedef> _usedTypedefs = new Set<Typedef>();
- FieldMorpher fieldMorpher;
- _TreeShakerTypeVisitor typeVisitor;
- _TreeShakerConstantVisitor constantVisitor;
- _TreeShakerPass1 _pass1;
- _TreeShakerPass2 _pass2;
+ late final FieldMorpher fieldMorpher;
+ late final _TreeShakerTypeVisitor typeVisitor;
+ late final _TreeShakerConstantVisitor constantVisitor;
+ late final _TreeShakerPass1 _pass1;
+ late final _TreeShakerPass2 _pass2;
TreeShaker(Component component, this.typeFlowAnalysis,
{this.treeShakeWriteOnlyFields: true}) {
@@ -731,7 +731,7 @@
(!f.isStatic &&
f.initializer != null &&
isFieldInitializerReachable(f) &&
- mayHaveSideEffects(f.initializer)) ||
+ mayHaveSideEffects(f.initializer!)) ||
(f.isLate && f.isFinal)) ||
isMemberReferencedFromNativeCode(f) ||
_isInstanceFieldOfAllocatedEnum(f);
@@ -742,8 +742,8 @@
bool _isInstanceFieldOfAllocatedEnum(Field node) =>
!node.isStatic &&
node.enclosingClass != null &&
- node.enclosingClass.isEnum &&
- isClassAllocated(node.enclosingClass);
+ node.enclosingClass!.isEnum &&
+ isClassAllocated(node.enclosingClass!);
void addClassUsedInType(Class c) {
if (_classesUsedInType.add(c)) {
@@ -774,7 +774,7 @@
_usedClasses.add(enclosingClass);
}
- FunctionNode func = null;
+ FunctionNode? func = null;
if (m is Field) {
m.type.accept(typeVisitor);
} else if (m is Procedure) {
@@ -783,19 +783,19 @@
m.stubTarget = fieldMorpher.adjustInstanceCallTarget(
m.concreteForwardingStubTarget,
isSetter: m.isSetter);
- addUsedMember(m.concreteForwardingStubTarget);
+ addUsedMember(m.concreteForwardingStubTarget!);
}
if (m.abstractForwardingStubTarget != null) {
m.stubTarget = fieldMorpher.adjustInstanceCallTarget(
m.abstractForwardingStubTarget,
isSetter: m.isSetter);
- addUsedMember(m.abstractForwardingStubTarget);
+ addUsedMember(m.abstractForwardingStubTarget!);
}
if (m.memberSignatureOrigin != null) {
m.stubTarget = fieldMorpher.adjustInstanceCallTarget(
m.memberSignatureOrigin,
isSetter: m.isSetter);
- addUsedMember(m.memberSignatureOrigin);
+ addUsedMember(m.memberSignatureOrigin!);
}
} else if (m is Constructor) {
func = m.function;
@@ -818,8 +818,7 @@
final extension = m.enclosingLibrary.extensions.firstWhere((extension) {
return extension.members
.any((descriptor) => descriptor.member.asMember == m);
- }, orElse: () => null);
- assert(extension != null);
+ });
// Ensure we retain the [Extension] itself (though members might be
// shaken)
@@ -841,7 +840,7 @@
if (_usedExtensions.add(node)) {
node.annotations = const <Expression>[];
_pass1.transformTypeParameterList(node.typeParameters, node);
- node.onType?.accept(typeVisitor);
+ node.onType.accept(typeVisitor);
}
}
@@ -895,7 +894,7 @@
isAbstract: true, fileUri: field.fileUri);
}
accessor.fileOffset = field.fileOffset;
- field.enclosingClass.addProcedure(accessor);
+ field.enclosingClass!.addProcedure(accessor);
_removedFields[accessor] = field;
shaker.addUsedMember(accessor);
return accessor;
@@ -905,7 +904,7 @@
/// If necessary, creates a getter or setter as a replacement if target is a
/// field which is going to be removed by the tree shaker.
/// This method is used during tree shaker pass 1.
- Member adjustInstanceCallTarget(Member target, {bool isSetter = false}) {
+ Member? adjustInstanceCallTarget(Member? target, {bool isSetter = false}) {
if (target is Field && !shaker.retainField(target)) {
final targets =
isSetter ? _settersForRemovedFields : _gettersForRemovedFields;
@@ -920,9 +919,9 @@
/// Return a member which replaced [target] in instance calls.
/// This method can be used after tree shaking to discover replacement.
- Member getMorphedMember(Member target, {bool isSetter = false}) {
- if (target == null) {
- return null;
+ Member? getMorphedMember(Member? target, {bool isSetter = false}) {
+ if (target is! Field) {
+ return target;
}
final targets =
isSetter ? _settersForRemovedFields : _gettersForRemovedFields;
@@ -931,7 +930,7 @@
/// Return original member which was replaced by [target] in instance calls.
/// This method can be used after tree shaking.
- Member getOriginalMember(Member target) {
+ Member? getOriginalMember(Member? target) {
if (target == null) {
return null;
}
@@ -991,16 +990,15 @@
final TreeShaker shaker;
final FieldMorpher fieldMorpher;
final TypeEnvironment environment;
- Procedure _unsafeCast;
- StaticTypeContext _staticTypeContext;
- Member _currentMember;
+ StaticTypeContext? _staticTypeContext;
+ Member? _currentMember;
StaticTypeContext get staticTypeContext =>
_staticTypeContext ??= StaticTypeContext(currentMember, environment);
- Member get currentMember => _currentMember;
- set currentMember(Member m) {
+ Member get currentMember => _currentMember!;
+ set currentMember(Member? m) {
_currentMember = m;
_staticTypeContext = null;
}
@@ -1019,7 +1017,7 @@
}
List<Expression> _flattenArguments(Arguments arguments,
- {Expression receiver}) {
+ {Expression? receiver}) {
final args = <Expression>[];
if (receiver != null) {
args.add(receiver);
@@ -1030,23 +1028,42 @@
}
bool _isThrowExpression(Expression expr) {
- while (expr is Let) {
- expr = (expr as Let).body;
+ for (;;) {
+ if (expr is Let) {
+ expr = expr.body;
+ } else if (expr is BlockExpression) {
+ expr = expr.value;
+ } else {
+ break;
+ }
}
return expr is Throw;
}
- TreeNode _evaluateArguments(List<Expression> args, Expression result) {
- Expression node = result;
- for (var arg in args.reversed) {
+ Expression _evaluateArguments(List<Expression> args, Expression result) {
+ final List<ast.Statement> statements = <ast.Statement>[];
+ for (var arg in args) {
if (mayHaveSideEffects(arg)) {
- node = Let(VariableDeclaration(null, initializer: arg), node);
+ if (arg is BlockExpression && !mayHaveSideEffects(arg.value)) {
+ statements.add(arg.body);
+ } else {
+ statements.add(ExpressionStatement(arg));
+ }
}
}
- return node;
+ if (statements.isEmpty) {
+ return result;
+ }
+ // Merge nested BlockExpression nodes.
+ Expression value = result;
+ if (result is BlockExpression) {
+ statements.addAll(result.body.statements);
+ value = result.value;
+ }
+ return BlockExpression(Block(statements), value);
}
- TreeNode _makeUnreachableCall(List<Expression> args) {
+ Expression _makeUnreachableCall(List<Expression> args) {
Expression node;
final int last = args.indexWhere(_isThrowExpression);
if (last >= 0) {
@@ -1068,12 +1085,12 @@
new VariableDeclaration(null, initializer: _makeUnreachableCall(args)));
}
- NarrowNotNull _getNullTest(TreeNode node) =>
+ NarrowNotNull? _getNullTest(TreeNode node) =>
shaker.typeFlowAnalysis.nullTest(node);
- TreeNode _visitAssertNode(TreeNode node, TreeNode removalSentinel) {
+ TreeNode _visitAssertNode(TreeNode node, TreeNode? removalSentinel) {
if (kRemoveAsserts) {
- return removalSentinel;
+ return removalSentinel!;
} else {
node.transformOrRemoveChildren(this);
return node;
@@ -1081,31 +1098,31 @@
}
@override
- DartType visitDartType(DartType node, DartType removalSentinel) {
+ DartType visitDartType(DartType node, DartType? removalSentinel) {
node.accept(shaker.typeVisitor);
return node;
}
@override
- Supertype visitSupertype(Supertype node, Supertype removalSentinel) {
+ Supertype visitSupertype(Supertype node, Supertype? removalSentinel) {
node.accept(shaker.typeVisitor);
return node;
}
@override
- TreeNode visitTypedef(Typedef node, TreeNode removalSentinel) {
+ TreeNode visitTypedef(Typedef node, TreeNode? removalSentinel) {
return node; // Do not go deeper.
}
@override
- Extension visitExtension(Extension node, TreeNode removalSentinel) {
+ TreeNode visitExtension(Extension node, TreeNode? removalSentinel) {
// The extension can be considered a weak node, we'll only retain it if
// normal code references any of it's members.
return node;
}
@override
- TreeNode visitClass(Class node, TreeNode removalSentinel) {
+ TreeNode visitClass(Class node, TreeNode? removalSentinel) {
if (shaker.isClassAllocated(node) ||
shaker.isClassReferencedFromNativeCode(node)) {
shaker.addClassUsedInType(node);
@@ -1113,13 +1130,12 @@
transformConstructorList(node.constructors, node);
transformProcedureList(node.procedures, node);
transformFieldList(node.fields, node);
- transformRedirectingFactoryConstructorList(
- node.redirectingFactoryConstructors, node);
+ transformRedirectingFactoryList(node.redirectingFactories, node);
return node;
}
@override
- TreeNode defaultMember(Member node, TreeNode removalSentinel) {
+ TreeNode defaultMember(Member node, TreeNode? removalSentinel) {
currentMember = node;
if (shaker.isMemberBodyReachable(node)) {
if (kPrintTrace) {
@@ -1139,7 +1155,7 @@
}
@override
- TreeNode visitField(Field node, TreeNode removalSentinel) {
+ TreeNode visitField(Field node, TreeNode? removalSentinel) {
currentMember = node;
if (shaker.retainField(node)) {
if (kPrintTrace) {
@@ -1164,21 +1180,21 @@
@override
TreeNode visitInstanceInvocation(
- InstanceInvocation node, TreeNode removalSentinel) {
+ InstanceInvocation node, TreeNode? removalSentinel) {
node.transformOrRemoveChildren(this);
if (_isUnreachable(node)) {
return _makeUnreachableCall(
_flattenArguments(node.arguments, receiver: node.receiver));
}
- node.interfaceTarget =
- fieldMorpher.adjustInstanceCallTarget(node.interfaceTarget);
+ node.interfaceTarget = fieldMorpher
+ .adjustInstanceCallTarget(node.interfaceTarget) as Procedure;
shaker.addUsedMember(node.interfaceTarget);
return node;
}
@override
TreeNode visitDynamicInvocation(
- DynamicInvocation node, TreeNode removalSentinel) {
+ DynamicInvocation node, TreeNode? removalSentinel) {
node.transformOrRemoveChildren(this);
if (_isUnreachable(node)) {
return _makeUnreachableCall(
@@ -1189,7 +1205,7 @@
@override
TreeNode visitLocalFunctionInvocation(
- LocalFunctionInvocation node, TreeNode removalSentinel) {
+ LocalFunctionInvocation node, TreeNode? removalSentinel) {
node.transformOrRemoveChildren(this);
if (_isUnreachable(node)) {
return _makeUnreachableCall(_flattenArguments(node.arguments));
@@ -1199,7 +1215,7 @@
@override
TreeNode visitFunctionInvocation(
- FunctionInvocation node, TreeNode removalSentinel) {
+ FunctionInvocation node, TreeNode? removalSentinel) {
node.transformOrRemoveChildren(this);
if (_isUnreachable(node)) {
return _makeUnreachableCall(
@@ -1209,39 +1225,39 @@
}
@override
- TreeNode visitEqualsCall(EqualsCall node, TreeNode removalSentinel) {
+ TreeNode visitEqualsCall(EqualsCall node, TreeNode? removalSentinel) {
node.transformOrRemoveChildren(this);
if (_isUnreachable(node)) {
return _makeUnreachableCall([node.left, node.right]);
}
- node.interfaceTarget =
- fieldMorpher.adjustInstanceCallTarget(node.interfaceTarget);
+ node.interfaceTarget = fieldMorpher
+ .adjustInstanceCallTarget(node.interfaceTarget) as Procedure;
shaker.addUsedMember(node.interfaceTarget);
return node;
}
@override
- TreeNode visitEqualsNull(EqualsNull node, TreeNode removalSentinel) {
+ TreeNode visitEqualsNull(EqualsNull node, TreeNode? removalSentinel) {
node.transformOrRemoveChildren(this);
if (_isUnreachable(node)) {
return _makeUnreachableCall([node.expression]);
}
- final nullTest = _getNullTest(node);
+ final nullTest = _getNullTest(node)!;
if (nullTest.isAlwaysNull || nullTest.isAlwaysNotNull) {
- return _evaluateArguments(
- [node.expression], BoolLiteral(nullTest.isAlwaysNull));
+ return _evaluateArguments([node.expression],
+ BoolLiteral(nullTest.isAlwaysNull)..fileOffset = node.fileOffset);
}
return node;
}
@override
- TreeNode visitInstanceGet(InstanceGet node, TreeNode removalSentinel) {
+ TreeNode visitInstanceGet(InstanceGet node, TreeNode? removalSentinel) {
node.transformOrRemoveChildren(this);
if (_isUnreachable(node)) {
return _makeUnreachableCall([node.receiver]);
} else {
node.interfaceTarget =
- fieldMorpher.adjustInstanceCallTarget(node.interfaceTarget);
+ fieldMorpher.adjustInstanceCallTarget(node.interfaceTarget)!;
shaker.addUsedMember(node.interfaceTarget);
return node;
}
@@ -1249,20 +1265,20 @@
@override
TreeNode visitInstanceTearOff(
- InstanceTearOff node, TreeNode removalSentinel) {
+ InstanceTearOff node, TreeNode? removalSentinel) {
node.transformOrRemoveChildren(this);
if (_isUnreachable(node)) {
return _makeUnreachableCall([node.receiver]);
} else {
- node.interfaceTarget =
- fieldMorpher.adjustInstanceCallTarget(node.interfaceTarget);
+ node.interfaceTarget = fieldMorpher
+ .adjustInstanceCallTarget(node.interfaceTarget) as Procedure;
shaker.addUsedMember(node.interfaceTarget);
return node;
}
}
@override
- TreeNode visitDynamicGet(DynamicGet node, TreeNode removalSentinel) {
+ TreeNode visitDynamicGet(DynamicGet node, TreeNode? removalSentinel) {
node.transformOrRemoveChildren(this);
if (_isUnreachable(node)) {
return _makeUnreachableCall([node.receiver]);
@@ -1273,7 +1289,7 @@
@override
TreeNode visitFunctionTearOff(
- FunctionTearOff node, TreeNode removalSentinel) {
+ FunctionTearOff node, TreeNode? removalSentinel) {
node.transformOrRemoveChildren(this);
if (_isUnreachable(node)) {
return _makeUnreachableCall([node.receiver]);
@@ -1283,20 +1299,20 @@
}
@override
- TreeNode visitInstanceSet(InstanceSet node, TreeNode removalSentinel) {
+ TreeNode visitInstanceSet(InstanceSet node, TreeNode? removalSentinel) {
node.transformOrRemoveChildren(this);
if (_isUnreachable(node)) {
return _makeUnreachableCall([node.receiver, node.value]);
} else {
node.interfaceTarget = fieldMorpher
- .adjustInstanceCallTarget(node.interfaceTarget, isSetter: true);
+ .adjustInstanceCallTarget(node.interfaceTarget, isSetter: true)!;
shaker.addUsedMember(node.interfaceTarget);
return node;
}
}
@override
- TreeNode visitDynamicSet(DynamicSet node, TreeNode removalSentinel) {
+ TreeNode visitDynamicSet(DynamicSet node, TreeNode? removalSentinel) {
node.transformOrRemoveChildren(this);
if (_isUnreachable(node)) {
return _makeUnreachableCall([node.receiver, node.value]);
@@ -1307,15 +1323,15 @@
@override
TreeNode visitSuperMethodInvocation(
- SuperMethodInvocation node, TreeNode removalSentinel) {
+ SuperMethodInvocation node, TreeNode? removalSentinel) {
node.transformOrRemoveChildren(this);
if (_isUnreachable(node)) {
return _makeUnreachableCall(_flattenArguments(node.arguments));
} else {
- node.interfaceTarget =
- fieldMorpher.adjustInstanceCallTarget(node.interfaceTarget);
+ node.interfaceTarget = fieldMorpher
+ .adjustInstanceCallTarget(node.interfaceTarget) as Procedure?;
if (node.interfaceTarget != null) {
- shaker.addUsedMember(node.interfaceTarget);
+ shaker.addUsedMember(node.interfaceTarget!);
}
return node;
}
@@ -1323,7 +1339,7 @@
@override
TreeNode visitSuperPropertyGet(
- SuperPropertyGet node, TreeNode removalSentinel) {
+ SuperPropertyGet node, TreeNode? removalSentinel) {
node.transformOrRemoveChildren(this);
if (_isUnreachable(node)) {
return _makeUnreachableCall([]);
@@ -1331,7 +1347,7 @@
node.interfaceTarget =
fieldMorpher.adjustInstanceCallTarget(node.interfaceTarget);
if (node.interfaceTarget != null) {
- shaker.addUsedMember(node.interfaceTarget);
+ shaker.addUsedMember(node.interfaceTarget!);
}
return node;
}
@@ -1339,7 +1355,7 @@
@override
TreeNode visitSuperPropertySet(
- SuperPropertySet node, TreeNode removalSentinel) {
+ SuperPropertySet node, TreeNode? removalSentinel) {
node.transformOrRemoveChildren(this);
if (_isUnreachable(node)) {
return _makeUnreachableCall([node.value]);
@@ -1347,7 +1363,7 @@
node.interfaceTarget = fieldMorpher
.adjustInstanceCallTarget(node.interfaceTarget, isSetter: true);
if (node.interfaceTarget != null) {
- shaker.addUsedMember(node.interfaceTarget);
+ shaker.addUsedMember(node.interfaceTarget!);
}
return node;
}
@@ -1355,7 +1371,7 @@
@override
TreeNode visitStaticInvocation(
- StaticInvocation node, TreeNode removalSentinel) {
+ StaticInvocation node, TreeNode? removalSentinel) {
node.transformOrRemoveChildren(this);
if (_isUnreachable(node)) {
return _makeUnreachableCall(_flattenArguments(node.arguments));
@@ -1369,7 +1385,7 @@
}
@override
- TreeNode visitStaticGet(StaticGet node, TreeNode removalSentinel) {
+ TreeNode visitStaticGet(StaticGet node, TreeNode? removalSentinel) {
node.transformOrRemoveChildren(this);
if (_isUnreachable(node)) {
return _makeUnreachableCall([]);
@@ -1384,13 +1400,13 @@
}
@override
- Constant visitConstant(Constant node, Constant removalSentinel) {
+ Constant visitConstant(Constant node, Constant? removalSentinel) {
shaker.constantVisitor.analyzeConstant(node);
return node;
}
@override
- TreeNode visitStaticSet(StaticSet node, TreeNode removalSentinel) {
+ TreeNode visitStaticSet(StaticSet node, TreeNode? removalSentinel) {
node.transformOrRemoveChildren(this);
if (_isUnreachable(node)) {
return _makeUnreachableCall([node.value]);
@@ -1407,7 +1423,7 @@
@override
TreeNode visitConstructorInvocation(
- ConstructorInvocation node, TreeNode removalSentinel) {
+ ConstructorInvocation node, TreeNode? removalSentinel) {
node.transformOrRemoveChildren(this);
if (_isUnreachable(node)) {
return _makeUnreachableCall(_flattenArguments(node.arguments));
@@ -1423,7 +1439,7 @@
@override
TreeNode visitRedirectingInitializer(
- RedirectingInitializer node, TreeNode removalSentinel) {
+ RedirectingInitializer node, TreeNode? removalSentinel) {
node.transformOrRemoveChildren(this);
if (_isUnreachable(node)) {
return _makeUnreachableInitializer(_flattenArguments(node.arguments));
@@ -1436,7 +1452,7 @@
@override
TreeNode visitSuperInitializer(
- SuperInitializer node, TreeNode removalSentinel) {
+ SuperInitializer node, TreeNode? removalSentinel) {
node.transformOrRemoveChildren(this);
if (_isUnreachable(node)) {
return _makeUnreachableInitializer(_flattenArguments(node.arguments));
@@ -1448,7 +1464,7 @@
@override
TreeNode visitFieldInitializer(
- FieldInitializer node, TreeNode removalSentinel) {
+ FieldInitializer node, TreeNode? removalSentinel) {
node.transformOrRemoveChildren(this);
if (_isUnreachable(node)) {
return _makeUnreachableInitializer([node.value]);
@@ -1461,7 +1477,7 @@
return LocalInitializer(
VariableDeclaration(null, initializer: node.value));
} else {
- return removalSentinel;
+ return removalSentinel!;
}
}
return node;
@@ -1470,26 +1486,153 @@
@override
TreeNode visitAssertStatement(
- AssertStatement node, TreeNode removalSentinel) {
+ AssertStatement node, TreeNode? removalSentinel) {
return _visitAssertNode(node, removalSentinel);
}
@override
- TreeNode visitAssertBlock(AssertBlock node, TreeNode removalSentinel) {
+ TreeNode visitAssertBlock(AssertBlock node, TreeNode? removalSentinel) {
return _visitAssertNode(node, removalSentinel);
}
@override
TreeNode visitAssertInitializer(
- AssertInitializer node, TreeNode removalSentinel) {
+ AssertInitializer node, TreeNode? removalSentinel) {
return _visitAssertNode(node, removalSentinel);
}
+ // Expression is an extended bool literal if it is
+ // - a BoolLiteral
+ // - a BlockExpression with a BoolLiteral value.
+ bool _isExtendedBoolLiteral(Expression expr) =>
+ expr is BoolLiteral ||
+ (expr is BlockExpression && expr.value is BoolLiteral);
+
+ // Returns value of an extended bool literal.
+ bool _getExtendedBoolLiteralValue(Expression expr) => (expr is BoolLiteral)
+ ? expr.value
+ : ((expr as BlockExpression).value as BoolLiteral).value;
+
+ // Returns Block corresponding to the given extended bool literal,
+ // or null if the expression is a simple bool literal.
+ Block? _getExtendedBoolLiteralBlock(Expression expr) =>
+ (expr is BoolLiteral) ? null : (expr as BlockExpression).body;
+
@override
- TreeNode visitAsExpression(AsExpression node, TreeNode removalSentinel) {
+ TreeNode visitIfStatement(IfStatement node, TreeNode? removalSentinel) {
+ final condition = transform(node.condition);
+ if (_isExtendedBoolLiteral(condition)) {
+ final bool conditionValue = _getExtendedBoolLiteralValue(condition);
+ final Block? conditionBlock = _getExtendedBoolLiteralBlock(condition);
+ ast.Statement? body;
+ if (conditionValue) {
+ body = transform(node.then);
+ } else {
+ if (node.otherwise != null) {
+ body = transformOrRemoveStatement(node.otherwise!);
+ }
+ }
+ if (conditionBlock != null) {
+ if (body != null) {
+ conditionBlock.addStatement(body);
+ }
+ return conditionBlock;
+ } else {
+ return body ?? EmptyStatement();
+ }
+ }
+ node.condition = condition..parent = node;
+ node.then = transform(node.then)..parent = node;
+ if (node.otherwise != null) {
+ node.otherwise = transformOrRemoveStatement(node.otherwise!);
+ node.otherwise?.parent = node;
+ }
+ return node;
+ }
+
+ @override
+ visitConditionalExpression(
+ ConditionalExpression node, TreeNode? removalSentinel) {
+ final condition = transform(node.condition);
+ if (_isExtendedBoolLiteral(condition)) {
+ final bool value = _getExtendedBoolLiteralValue(condition);
+ final Expression expr = transform(value ? node.then : node.otherwise);
+ if (condition is BlockExpression) {
+ condition.value = expr;
+ expr.parent = condition;
+ return condition;
+ } else {
+ return expr;
+ }
+ }
+ node.condition = condition..parent = node;
+ node.then = transform(node.then)..parent = node;
+ node.otherwise = transform(node.otherwise)..parent = node;
+ node.staticType = visitDartType(node.staticType, cannotRemoveSentinel);
+ return node;
+ }
+
+ @override
+ TreeNode visitNot(Not node, TreeNode? removalSentinel) {
node.transformOrRemoveChildren(this);
- TypeCheck check = shaker.typeFlowAnalysis.explicitCast(node);
- if (check != null && check.canAlwaysSkip) {
+ final operand = node.operand;
+ if (_isExtendedBoolLiteral(operand)) {
+ final bool value = _getExtendedBoolLiteralValue(operand);
+ if (operand is BlockExpression) {
+ (operand.value as BoolLiteral).value = !value;
+ } else {
+ (operand as BoolLiteral).value = !value;
+ }
+ return operand;
+ }
+ return node;
+ }
+
+ @override
+ TreeNode visitLogicalExpression(
+ LogicalExpression node, TreeNode? removalSentinel) {
+ final left = transform(node.left);
+ final operatorEnum = node.operatorEnum;
+ if (_isExtendedBoolLiteral(left)) {
+ final leftValue = _getExtendedBoolLiteralValue(left);
+ if (leftValue && operatorEnum == LogicalExpressionOperator.OR) {
+ return left;
+ } else if (!leftValue && operatorEnum == LogicalExpressionOperator.AND) {
+ return left;
+ }
+ }
+ final right = transform(node.right);
+ // Without sound null safety arguments of logical expression
+ // are implicitly checked for null, so transform the node only
+ // if using sound null safety or it evaluates to a bool literal.
+ if (_isExtendedBoolLiteral(left) &&
+ (shaker.typeFlowAnalysis.target.flags.enableNullSafety ||
+ _isExtendedBoolLiteral(right))) {
+ return _evaluateArguments([left], right);
+ }
+ node.left = left..parent = node;
+ node.right = right..parent = node;
+ return node;
+ }
+
+ @override
+ TreeNode visitIsExpression(IsExpression node, TreeNode? removalSentinel) {
+ TypeCheck? check = shaker.typeFlowAnalysis.isTest(node);
+ if (check != null && (check.alwaysFail || check.alwaysPass)) {
+ final operand = transform(node.operand);
+ final result = BoolLiteral(!check.alwaysFail)
+ ..fileOffset = node.fileOffset;
+ return _evaluateArguments([operand], result);
+ }
+ node.transformOrRemoveChildren(this);
+ return node;
+ }
+
+ @override
+ TreeNode visitAsExpression(AsExpression node, TreeNode? removalSentinel) {
+ node.transformOrRemoveChildren(this);
+ TypeCheck? check = shaker.typeFlowAnalysis.explicitCast(node);
+ if (check != null && check.alwaysPass) {
return StaticInvocation(
unsafeCast, Arguments([node.operand], types: [node.type]))
..fileOffset = node.fileOffset;
@@ -1498,9 +1641,9 @@
}
@override
- TreeNode visitNullCheck(NullCheck node, TreeNode removalSentinel) {
+ TreeNode visitNullCheck(NullCheck node, TreeNode? removalSentinel) {
node.transformOrRemoveChildren(this);
- final nullTest = _getNullTest(node);
+ final nullTest = _getNullTest(node)!;
if (nullTest.isAlwaysNotNull) {
return StaticInvocation(
unsafeCast,
@@ -1511,12 +1654,9 @@
return node;
}
- Procedure get unsafeCast {
- _unsafeCast ??= shaker.typeFlowAnalysis.environment.coreTypes.index
- .getTopLevelMember('dart:_internal', 'unsafeCast');
- assert(_unsafeCast != null);
- return _unsafeCast;
- }
+ late final Procedure unsafeCast = shaker
+ .typeFlowAnalysis.environment.coreTypes.index
+ .getTopLevelProcedure('dart:_internal', 'unsafeCast');
}
/// The second pass of [TreeShaker]. It is called after set of used
@@ -1532,7 +1672,7 @@
void transformComponent(Component component) {
component.transformOrRemoveChildren(this);
for (Source source in component.uriToSource.values) {
- source?.constantCoverageConstructors?.removeWhere((Reference reference) {
+ source.constantCoverageConstructors?.removeWhere((Reference reference) {
Member node = reference.asMember;
return !shaker.isMemberUsed(node);
});
@@ -1540,7 +1680,7 @@
}
@override
- TreeNode visitLibrary(Library node, TreeNode removalSentinel) {
+ TreeNode visitLibrary(Library node, TreeNode? removalSentinel) {
node.transformOrRemoveChildren(this);
// The transformer API does not iterate over `Library.additionalExports`,
// so we manually delete the references to shaken nodes.
@@ -1560,12 +1700,12 @@
}
@override
- Typedef visitTypedef(Typedef node, TreeNode removalSentinel) {
- return shaker.isTypedefUsed(node) ? node : removalSentinel;
+ TreeNode visitTypedef(Typedef node, TreeNode? removalSentinel) {
+ return shaker.isTypedefUsed(node) ? node : removalSentinel!;
}
@override
- Class visitClass(Class node, TreeNode removalSentinel) {
+ TreeNode visitClass(Class node, TreeNode? removalSentinel) {
if (!shaker.isClassUsed(node)) {
debugPrint('Dropped class ${node.name}');
// Ensure that kernel file writer will not be able to
@@ -1576,7 +1716,7 @@
"been repurposed for ${node.reference.node}.");
node.reference.canonicalName?.unbind();
Statistics.classesDropped++;
- return removalSentinel; // Remove the class.
+ return removalSentinel!; // Remove the class.
}
if (!shaker.isClassUsedInType(node)) {
@@ -1607,7 +1747,7 @@
}
@override
- Member defaultMember(Member node, TreeNode removalSentinel) {
+ TreeNode defaultMember(Member node, TreeNode? removalSentinel) {
if (!shaker.isMemberUsed(node)) {
// Ensure that kernel file writer will not be able to
// write a dangling reference to the deleted member.
@@ -1619,10 +1759,10 @@
node.getterReference.canonicalName?.unbind();
if (node.hasSetter) {
assert(
- node.setterReference.node == node,
+ node.setterReference!.node == node,
"Trying to remove canonical name from reference on $node which "
- "has been repurposed for ${node.setterReference.node}.");
- node.setterReference.canonicalName?.unbind();
+ "has been repurposed for ${node.setterReference!.node}.");
+ node.setterReference!.canonicalName?.unbind();
}
} else {
assert(
@@ -1632,13 +1772,13 @@
node.reference.canonicalName?.unbind();
}
Statistics.membersDropped++;
- return removalSentinel;
+ return removalSentinel!;
}
if (!shaker.isMemberBodyReachable(node)) {
if (node is Procedure) {
// Remove body of unused member.
- if (!node.isStatic && node.enclosingClass.isAbstract) {
+ if (!node.isStatic && node.enclosingClass!.isAbstract) {
node.isAbstract = true;
node.function.body = null;
} else {
@@ -1681,7 +1821,7 @@
}
@override
- Extension visitExtension(Extension node, TreeNode removalSentinel) {
+ TreeNode visitExtension(Extension node, TreeNode? removalSentinel) {
if (shaker.isExtensionUsed(node)) {
int writeIndex = 0;
for (int i = 0; i < node.members.length; ++i) {
@@ -1692,7 +1832,7 @@
// member was already removed or it will be removed later.
final Reference memberReference = descriptor.member;
final bool isBound = memberReference.node != null;
- if (isBound && shaker.isMemberUsed(memberReference.node)) {
+ if (isBound && shaker.isMemberUsed(memberReference.asMember)) {
node.members[writeIndex++] = descriptor;
}
}
@@ -1702,7 +1842,7 @@
assert(node.members.length > 0);
return node;
}
- return removalSentinel;
+ return removalSentinel!;
}
void _makeUnreachableBody(FunctionNode function) {
@@ -1723,7 +1863,7 @@
}
@override
- TreeNode defaultTreeNode(TreeNode node, TreeNode removalSentinel) {
+ TreeNode defaultTreeNode(TreeNode node, TreeNode? removalSentinel) {
return node; // Do not traverse into other nodes.
}
}
@@ -1795,7 +1935,12 @@
@override
visitStaticTearOffConstant(StaticTearOffConstant constant) {
- shaker.addUsedMember(constant.procedure);
+ shaker.addUsedMember(constant.target);
+ }
+
+ @override
+ visitConstructorTearOffConstant(ConstructorTearOffConstant constant) {
+ shaker.addUsedMember(constant.target);
}
@override
diff --git a/pkg/vm/lib/transformations/type_flow/types.dart b/pkg/vm/lib/transformations/type_flow/types.dart
index a5e9561..3ed7b9b 100644
--- a/pkg/vm/lib/transformations/type_flow/types.dart
+++ b/pkg/vm/lib/transformations/type_flow/types.dart
@@ -3,7 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
/// Declares the type system used by global type flow analysis.
-library vm.transformations.type_flow.types;
import 'dart:core' hide Type;
@@ -136,10 +135,7 @@
/// values can flow through the program.
Type specializeTypeCone(TFClass base, {bool allowWideCone = false});
- Type _cachedIntType;
- Type get intType {
- return _cachedIntType ??= fromStaticType(coreTypes.intLegacyRawType, true);
- }
+ late final Type intType = fromStaticType(coreTypes.intLegacyRawType, true);
}
/// Base class for type expressions.
@@ -149,7 +145,14 @@
/// Returns computed type of this type expression.
/// [types] is the list of types computed for the statements in the summary.
- Type getComputedType(List<Type> types);
+ Type getComputedType(List<Type?> types);
+}
+
+/// Kind of a subtype test: subtype/cast/'as' test or instance check/'is' test.
+/// There is a subtle difference in how these tests handle null value.
+enum SubtypeTestKind {
+ Subtype,
+ IsTest,
}
/// Base class for types inferred by the type flow analysis.
@@ -165,18 +168,18 @@
/// Create a type representing arbitrary nullable object (`dynamic`).
factory Type.nullableAny() => new NullableType(const AnyType());
- Class getConcreteClass(TypeHierarchy typeHierarchy) => null;
+ Class? getConcreteClass(TypeHierarchy typeHierarchy) => null;
bool isSubtypeOf(TypeHierarchy typeHierarchy, Class cls) => false;
// Returns 'true' if this type will definitely pass a runtime type-check
// against 'runtimeType'. Returns 'false' if the test might fail (e.g. due to
// an approximation).
- bool isSubtypeOfRuntimeType(
- TypeHierarchy typeHierarchy, RuntimeType runtimeType);
+ bool isSubtypeOfRuntimeType(TypeHierarchy typeHierarchy,
+ RuntimeType runtimeType, SubtypeTestKind kind);
@override
- Type getComputedType(List<Type> types) => this;
+ Type getComputedType(List<Type?> types) => this;
/// Order of precedence for evaluation of union/intersection.
int get order;
@@ -239,7 +242,8 @@
@override
Type intersection(Type other, TypeHierarchy typeHierarchy) => this;
- bool isSubtypeOfRuntimeType(TypeHierarchy typeHierarchy, RuntimeType other) {
+ bool isSubtypeOfRuntimeType(
+ TypeHierarchy typeHierarchy, RuntimeType other, SubtypeTestKind kind) {
return true;
}
}
@@ -250,7 +254,6 @@
final Type baseType;
NullableType(this.baseType) {
- assert(baseType != null);
assert(baseType is! NullableType);
}
@@ -269,12 +272,27 @@
bool isSubtypeOf(TypeHierarchy typeHierarchy, Class cls) =>
baseType.isSubtypeOf(typeHierarchy, cls);
- bool isSubtypeOfRuntimeType(TypeHierarchy typeHierarchy, RuntimeType other) {
- if (typeHierarchy.nullSafety &&
- other.nullability == Nullability.nonNullable) {
- return false;
+ bool isSubtypeOfRuntimeType(
+ TypeHierarchy typeHierarchy, RuntimeType other, SubtypeTestKind kind) {
+ switch (kind) {
+ case SubtypeTestKind.Subtype:
+ if (typeHierarchy.nullSafety &&
+ other.nullability == Nullability.nonNullable) {
+ return false;
+ }
+ break;
+ case SubtypeTestKind.IsTest:
+ if (other.nullability != Nullability.nullable) {
+ final rhs = other._type;
+ if (!(rhs is InterfaceType &&
+ rhs.nullability == Nullability.legacy &&
+ rhs.classNode == typeHierarchy.coreTypes.objectClass)) {
+ return false;
+ }
+ }
+ break;
}
- return baseType.isSubtypeOfRuntimeType(typeHierarchy, other);
+ return baseType.isSubtypeOfRuntimeType(typeHierarchy, other, kind);
}
@override
@@ -347,7 +365,8 @@
return other;
}
- bool isSubtypeOfRuntimeType(TypeHierarchy typeHierarchy, RuntimeType other) {
+ bool isSubtypeOfRuntimeType(
+ TypeHierarchy typeHierarchy, RuntimeType other, SubtypeTestKind kind) {
final rhs = other._type;
return (rhs is DynamicType) ||
(rhs is VoidType) ||
@@ -361,7 +380,9 @@
class SetType extends Type {
/// List of concrete types, sorted by classId.
final List<ConcreteType> types;
- int _hashCode;
+
+ @override
+ late final int hashCode = _computeHashCode();
/// Creates a new SetType using list of concrete types sorted by classId.
SetType(this.types) {
@@ -369,9 +390,6 @@
assert(isSorted(types));
}
- @override
- int get hashCode => _hashCode ??= _computeHashCode();
-
int _computeHashCode() {
int hash = 1237;
for (var t in types) {
@@ -401,8 +419,9 @@
bool isSubtypeOf(TypeHierarchy typeHierarchy, Class cls) =>
types.every((ConcreteType t) => t.isSubtypeOf(typeHierarchy, cls));
- bool isSubtypeOfRuntimeType(TypeHierarchy typeHierarchy, RuntimeType other) =>
- types.every((t) => t.isSubtypeOfRuntimeType(typeHierarchy, other));
+ bool isSubtypeOfRuntimeType(TypeHierarchy typeHierarchy, RuntimeType other,
+ SubtypeTestKind kind) =>
+ types.every((t) => t.isSubtypeOfRuntimeType(typeHierarchy, other, kind));
@override
int get order => TypeOrder.Set.index;
@@ -443,8 +462,8 @@
return types;
}
- static List<ConcreteType> _intersectLists(
- List<ConcreteType> types1, List<ConcreteType> types2) {
+ static List<ConcreteType> _intersectLists(List<ConcreteType> types1,
+ List<ConcreteType> types2, TypeHierarchy typeHierarchy) {
int i1 = 0;
int i2 = 0;
List<ConcreteType> types = <ConcreteType>[];
@@ -464,9 +483,9 @@
t2.constant == null) {
types.add(t1);
} else {
- final intersect = t1.intersection(t2, null);
+ final intersect = t1.intersection(t2, typeHierarchy);
if (intersect is! EmptyType) {
- types.add(intersect);
+ types.add(intersect as ConcreteType);
}
}
++i1;
@@ -531,7 +550,8 @@
return other.intersection(this, typeHierarchy);
}
if (other is SetType) {
- List<ConcreteType> list = _intersectLists(types, other.types);
+ List<ConcreteType> list =
+ _intersectLists(types, other.types, typeHierarchy);
final size = list.length;
if (size == 0) {
return const EmptyType();
@@ -567,7 +587,7 @@
ConeType(this.cls);
@override
- Class getConcreteClass(TypeHierarchy typeHierarchy) => typeHierarchy
+ Class? getConcreteClass(TypeHierarchy typeHierarchy) => typeHierarchy
.specializeTypeCone(cls, allowWideCone: true)
.getConcreteClass(typeHierarchy);
@@ -575,7 +595,8 @@
bool isSubtypeOf(TypeHierarchy typeHierarchy, Class cls) =>
typeHierarchy.isSubtype(this.cls.classNode, cls);
- bool isSubtypeOfRuntimeType(TypeHierarchy typeHierarchy, RuntimeType other) {
+ bool isSubtypeOfRuntimeType(
+ TypeHierarchy typeHierarchy, RuntimeType other, SubtypeTestKind kind) {
final rhs = other._type;
if (rhs is DynamicType || rhs is VoidType) return true;
if (rhs is InterfaceType) {
@@ -668,7 +689,7 @@
WideConeType(TFClass cls) : super(cls);
@override
- Class getConcreteClass(TypeHierarchy typeHierarchy) => null;
+ Class? getConcreteClass(TypeHierarchy typeHierarchy) => null;
@override
int get hashCode => (cls.id + 41) & kHashMask;
@@ -755,7 +776,9 @@
/// or `null` object).
class ConcreteType extends Type implements Comparable<ConcreteType> {
final TFClass cls;
- int _hashCode;
+
+ @override
+ late final int hashCode = _computeHashCode();
// May be null if there are no type arguments constraints. The type arguments
// should represent type sets, i.e. `UnknownType` or `RuntimeType`. The type
@@ -768,19 +791,19 @@
// 'numImmediateTypeArgs' is the length of the prefix of 'typeArgs' which
// holds the type arguments to the class itself.
final int numImmediateTypeArgs;
- final List<Type> typeArgs;
+ final List<Type>? typeArgs;
// May be null if constant value is not inferred.
- final Constant constant;
+ final Constant? constant;
- ConcreteType(this.cls, [List<Type> typeArgs_, this.constant])
+ ConcreteType(this.cls, [List<Type>? typeArgs_, this.constant])
: typeArgs = typeArgs_,
numImmediateTypeArgs =
typeArgs_ != null ? cls.classNode.typeParameters.length : 0 {
// TODO(alexmarkov): support closures
assert(!cls.classNode.isAbstract);
assert(typeArgs == null || cls.classNode.typeParameters.isNotEmpty);
- assert(typeArgs == null || typeArgs.any((t) => t is RuntimeType));
+ assert(typeArgs == null || typeArgs!.any((t) => t is RuntimeType));
}
ConcreteType get raw => cls.concreteType;
@@ -793,8 +816,8 @@
bool isSubtypeOf(TypeHierarchy typeHierarchy, Class other) =>
typeHierarchy.isSubtype(cls.classNode, other);
- bool isSubtypeOfRuntimeType(
- TypeHierarchy typeHierarchy, RuntimeType runtimeType) {
+ bool isSubtypeOfRuntimeType(TypeHierarchy typeHierarchy,
+ RuntimeType runtimeType, SubtypeTestKind kind) {
final rhs = runtimeType._type;
if (rhs is DynamicType || rhs is VoidType) return true;
if (rhs is InterfaceType) {
@@ -811,7 +834,7 @@
if (rhs.typeArguments.isEmpty) return true;
- List<Type> usableTypeArgs = typeArgs;
+ List<Type>? usableTypeArgs = typeArgs;
if (usableTypeArgs == null) {
if (cls.classNode.typeParameters.isEmpty) {
usableTypeArgs =
@@ -834,7 +857,7 @@
}
assert(ta is RuntimeType);
if (!ta.isSubtypeOfRuntimeType(
- typeHierarchy, runtimeType.typeArgs[i])) {
+ typeHierarchy, runtimeType.typeArgs![i], SubtypeTestKind.Subtype)) {
return false;
}
}
@@ -849,28 +872,26 @@
} else {
final interfaceOffset = typeHierarchy.genericInterfaceOffsetFor(
cls.classNode, typeHierarchy.coreTypes.futureClass);
- typeArg = typeArgs[interfaceOffset];
+ typeArg = typeArgs![interfaceOffset];
}
final RuntimeType lhs =
typeArg is RuntimeType ? typeArg : RuntimeType(DynamicType(), null);
return lhs.isSubtypeOfRuntimeType(
- typeHierarchy, runtimeType.typeArgs[0]);
+ typeHierarchy, runtimeType.typeArgs![0], SubtypeTestKind.Subtype);
} else {
- return isSubtypeOfRuntimeType(typeHierarchy, runtimeType.typeArgs[0]);
+ return isSubtypeOfRuntimeType(
+ typeHierarchy, runtimeType.typeArgs![0], SubtypeTestKind.Subtype);
}
}
return false;
}
- @override
- int get hashCode => _hashCode ??= _computeHashCode();
-
int _computeHashCode() {
int hash = cls.hashCode ^ 0x1234 & kHashMask;
// We only need to hash the first type arguments vector, since the type
// arguments of the implemented interfaces are implied by it.
for (int i = 0; i < numImmediateTypeArgs; ++i) {
- hash = (((hash * 31) & kHashMask) + typeArgs[i].hashCode) & kHashMask;
+ hash = (((hash * 31) & kHashMask) + typeArgs![i].hashCode) & kHashMask;
}
hash = ((hash * 31) & kHashMask) + constant.hashCode;
return hash;
@@ -886,7 +907,7 @@
}
if (this.typeArgs != null) {
for (int i = 0; i < numImmediateTypeArgs; ++i) {
- if (this.typeArgs[i] != other.typeArgs[i]) {
+ if (this.typeArgs![i] != other.typeArgs![i]) {
return false;
}
}
@@ -913,10 +934,10 @@
final StringBuffer buf = new StringBuffer();
buf.write("_T (${cls}");
if (typeArgs != null) {
- buf.write("<${typeArgs.take(numImmediateTypeArgs).join(', ')}>");
+ buf.write("<${typeArgs!.take(numImmediateTypeArgs).join(', ')}>");
}
if (constant != null) {
- buf.write(", ${nodeToText(constant)}");
+ buf.write(", ${nodeToText(constant!)}");
}
buf.write(")");
return buf.toString();
@@ -968,17 +989,21 @@
return this;
}
- List<Type> mergedTypeArgs;
- if (typeArgs == null) {
- mergedTypeArgs = other.typeArgs;
- } else if (other.typeArgs == null) {
- mergedTypeArgs = typeArgs;
+ List<Type>? mergedTypeArgs;
+ final thisTypeArgs = this.typeArgs;
+ final otherTypeArgs = other.typeArgs;
+ if (thisTypeArgs == null) {
+ mergedTypeArgs = otherTypeArgs;
+ } else if (otherTypeArgs == null) {
+ mergedTypeArgs = thisTypeArgs;
} else {
- mergedTypeArgs = new List<Type>.filled(typeArgs.length, null);
+ assert(thisTypeArgs.length == otherTypeArgs.length);
+ mergedTypeArgs =
+ new List<Type>.filled(thisTypeArgs.length, const EmptyType());
bool hasRuntimeType = false;
- for (int i = 0; i < typeArgs.length; ++i) {
+ for (int i = 0; i < thisTypeArgs.length; ++i) {
final merged =
- typeArgs[i].intersection(other.typeArgs[i], typeHierarchy);
+ thisTypeArgs[i].intersection(otherTypeArgs[i], typeHierarchy);
if (merged is EmptyType) {
return const EmptyType();
} else if (merged is RuntimeType) {
@@ -991,7 +1016,7 @@
}
}
- Constant mergedConstant;
+ Constant? mergedConstant;
if (constant == null) {
mergedConstant = other.constant;
} else if (other.constant == null || constant == other.constant) {
@@ -1033,7 +1058,7 @@
final DartType _type; // Doesn't contain type args.
final int numImmediateTypeArgs;
- final List<RuntimeType> typeArgs;
+ final List<RuntimeType>? typeArgs;
RuntimeType(DartType type, this.typeArgs)
: _type = type,
@@ -1041,14 +1066,12 @@
? type.classNode.typeParameters.length
: (type is FutureOrType ? 1 : 0) {
if (_type is InterfaceType && numImmediateTypeArgs > 0) {
- assert(typeArgs != null);
- assert(typeArgs.length >= numImmediateTypeArgs);
+ assert(typeArgs!.length >= numImmediateTypeArgs);
assert((_type as InterfaceType)
.typeArguments
.every((t) => t == const DynamicType()));
} else if (_type is FutureOrType) {
- assert(typeArgs != null);
- assert(typeArgs.length >= numImmediateTypeArgs);
+ assert(typeArgs!.length >= numImmediateTypeArgs);
DartType typeArgument = (_type as FutureOrType).typeArgument;
assert(typeArgument == const DynamicType());
} else {
@@ -1069,25 +1092,27 @@
final type = _type;
if (type is InterfaceType && typeArgs != null) {
final klass = type.classNode;
- final typeArguments = typeArgs
+ final typeArguments = typeArgs!
.take(klass.typeParameters.length)
.map((pt) => pt.representedType)
.toList();
return new InterfaceType(klass, type.nullability, typeArguments);
} else if (type is FutureOrType) {
- return new FutureOrType(typeArgs[0].representedType, type.nullability);
+ return new FutureOrType(typeArgs![0].representedType, type.nullability);
} else {
return type;
}
}
@override
- int get hashCode {
+ late final int hashCode = _computeHashCode();
+
+ int _computeHashCode() {
int hash = _type.hashCode ^ 0x1234 & kHashMask;
// Only hash by the type arguments of the class. The type arguments of
// supertypes are are implied by them.
for (int i = 0; i < numImmediateTypeArgs; ++i) {
- hash = (((hash * 31) & kHashMask) + typeArgs[i].hashCode) & kHashMask;
+ hash = (((hash * 31) & kHashMask) + typeArgs![i].hashCode) & kHashMask;
}
return hash;
}
@@ -1098,7 +1123,7 @@
if (other is RuntimeType) {
if (other._type != _type) return false;
assert(numImmediateTypeArgs == other.numImmediateTypeArgs);
- return typeArgs == null || listEquals(typeArgs, other.typeArgs);
+ return typeArgs == null || listEquals(typeArgs!, other.typeArgs!);
}
return false;
}
@@ -1110,7 +1135,7 @@
: "${nodeToText(_type)}";
final typeArgsStrs = (numImmediateTypeArgs == 0)
? ""
- : "<${typeArgs.take(numImmediateTypeArgs).map((t) => "$t").join(", ")}>";
+ : "<${typeArgs!.take(numImmediateTypeArgs).map((t) => "$t").join(", ")}>";
final nullability = _type.nullability.suffix;
return "$head$typeArgsStrs$nullability";
}
@@ -1147,8 +1172,11 @@
Class getConcreteClass(TypeHierarchy typeHierarchy) =>
throw "ERROR: ConcreteClass does not support getConcreteClass.";
- bool isSubtypeOfRuntimeType(
- TypeHierarchy typeHierarchy, RuntimeType runtimeType) {
+ bool isSubtypeOfRuntimeType(TypeHierarchy typeHierarchy,
+ RuntimeType runtimeType, SubtypeTestKind kind) {
+ if (kind != SubtypeTestKind.Subtype) {
+ throw 'RuntimeType could be only tested for subtyping.';
+ }
final rhs = runtimeType._type;
if (typeHierarchy.nullSafety &&
_type.nullability == Nullability.nullable &&
@@ -1168,14 +1196,15 @@
if (_type is InterfaceType) {
Class thisClass = (_type as InterfaceType).classNode;
if (thisClass == typeHierarchy.coreTypes.futureClass) {
- return typeArgs[0]
- .isSubtypeOfRuntimeType(typeHierarchy, runtimeType.typeArgs[0]);
+ return typeArgs![0].isSubtypeOfRuntimeType(
+ typeHierarchy, runtimeType.typeArgs![0], SubtypeTestKind.Subtype);
} else {
- return isSubtypeOfRuntimeType(typeHierarchy, runtimeType.typeArgs[0]);
+ return isSubtypeOfRuntimeType(
+ typeHierarchy, runtimeType.typeArgs![0], SubtypeTestKind.Subtype);
}
} else if (_type is FutureOrType) {
- return typeArgs[0]
- .isSubtypeOfRuntimeType(typeHierarchy, runtimeType.typeArgs[0]);
+ return typeArgs![0].isSubtypeOfRuntimeType(
+ typeHierarchy, runtimeType.typeArgs![0], SubtypeTestKind.Subtype);
}
}
@@ -1203,7 +1232,7 @@
return true;
}
- List<Type> usableTypeArgs = typeArgs;
+ List<Type>? usableTypeArgs = typeArgs;
if (usableTypeArgs == null) {
assert(thisClass.typeParameters.isEmpty);
usableTypeArgs =
@@ -1214,8 +1243,8 @@
assert(usableTypeArgs.length - interfaceOffset >=
runtimeType.numImmediateTypeArgs);
for (int i = 0; i < runtimeType.numImmediateTypeArgs; ++i) {
- if (!usableTypeArgs[interfaceOffset + i]
- .isSubtypeOfRuntimeType(typeHierarchy, runtimeType.typeArgs[i])) {
+ if (!usableTypeArgs[interfaceOffset + i].isSubtypeOfRuntimeType(
+ typeHierarchy, runtimeType.typeArgs![i], SubtypeTestKind.Subtype)) {
return false;
}
}
@@ -1262,7 +1291,11 @@
throw "ERROR: UnknownType does not support intersection with ${other.runtimeType}";
}
- bool isSubtypeOfRuntimeType(TypeHierarchy typeHierarchy, RuntimeType other) {
+ bool isSubtypeOfRuntimeType(
+ TypeHierarchy typeHierarchy, RuntimeType other, SubtypeTestKind kind) {
+ if (kind != SubtypeTestKind.Subtype) {
+ throw 'UnknownType could be only tested for subtyping.';
+ }
final rhs = other._type;
return (rhs is DynamicType) ||
(rhs is VoidType) ||
diff --git a/pkg/vm/lib/transformations/type_flow/unboxing_info.dart b/pkg/vm/lib/transformations/type_flow/unboxing_info.dart
index 03f7ef2..682cf58 100644
--- a/pkg/vm/lib/transformations/type_flow/unboxing_info.dart
+++ b/pkg/vm/lib/transformations/type_flow/unboxing_info.dart
@@ -28,12 +28,12 @@
_coreTypes = typeFlowAnalysis.environment.coreTypes,
_nativeCodeOracle = typeFlowAnalysis.nativeCodeOracle;
- UnboxingInfoMetadata getUnboxingInfoOfMember(Member member) {
- final UnboxingInfoMetadata info = _memberInfo[member];
+ UnboxingInfoMetadata? getUnboxingInfoOfMember(Member member) {
+ final UnboxingInfoMetadata? info = _memberInfo[member];
if (member is Procedure && member.isGetter) {
// Remove placeholder parameter info slot for setters that the getter is
// grouped with.
- return UnboxingInfoMetadata(0)..returnInfo = info.returnInfo;
+ return UnboxingInfoMetadata(0)..returnInfo = info!.returnInfo;
}
return info;
}
@@ -79,8 +79,8 @@
? (member.hasSetter ? 1 : 0)
: member is Procedure && member.isGetter
? 1
- : member.function.requiredParameterCount;
- UnboxingInfoMetadata info;
+ : member.function!.requiredParameterCount;
+ UnboxingInfoMetadata? info;
if (member.isInstanceMember) {
int selectorId =
member is Field || member is Procedure && member.isGetter
@@ -119,20 +119,18 @@
void _updateUnboxingInfoOfMember(
Member member, TypeFlowAnalysis typeFlowAnalysis) {
if (typeFlowAnalysis.isMemberUsed(member)) {
- final UnboxingInfoMetadata unboxingInfo = _memberInfo[member];
+ final UnboxingInfoMetadata unboxingInfo = _memberInfo[member]!;
if (_cannotUnbox(member)) {
unboxingInfo.unboxedArgsInfo.length = 0;
unboxingInfo.returnInfo = UnboxingInfoMetadata.kBoxed;
return;
}
if (member is Procedure || member is Constructor) {
- final Args<Type> argTypes = typeFlowAnalysis.argumentTypes(member);
- assert(argTypes != null);
-
+ final Args<Type> argTypes = typeFlowAnalysis.argumentTypes(member)!;
final int firstParamIndex =
numTypeParams(member) + (hasReceiverArg(member) ? 1 : 0);
- final positionalParams = member.function.positionalParameters;
+ final positionalParams = member.function!.positionalParameters;
assert(argTypes.positionalCount ==
firstParamIndex + positionalParams.length);
diff --git a/pkg/vm/lib/transformations/type_flow/utils.dart b/pkg/vm/lib/transformations/type_flow/utils.dart
index 815736c..c85dfc7 100644
--- a/pkg/vm/lib/transformations/type_flow/utils.dart
+++ b/pkg/vm/lib/transformations/type_flow/utils.dart
@@ -6,6 +6,7 @@
/// analysis.
library vm.transformations.type_flow.utils;
+import 'package:collection/collection.dart' show IterableExtension;
import 'package:kernel/ast.dart';
import 'package:kernel/src/printer.dart';
@@ -121,9 +122,8 @@
return true;
}
-VariableDeclaration findNamedParameter(FunctionNode function, String name) {
- return function.namedParameters
- .firstWhere((p) => p.name == name, orElse: () => null);
+VariableDeclaration? findNamedParameter(FunctionNode function, String name) {
+ return function.namedParameters.firstWhereOrNull((p) => p.name == name);
}
class Histogram<K> {
@@ -141,7 +141,7 @@
print(
'-------------------------------------------------------------------');
List<K> keys = values.keys.toList();
- keys.sort((k1, k2) => values[k1].compareTo(values[k2]));
+ keys.sort((k1, k2) => values[k1]!.compareTo(values[k2]!));
final cut = keys.length < n ? 0 : keys.length - n;
for (int i = keys.length - 1; i >= cut; --i) {
final k = keys[i];
@@ -374,7 +374,7 @@
};
extension NullabilitySuffix on Nullability {
- String get suffix => nullabilitySuffix[this];
+ String get suffix => nullabilitySuffix[this]!;
}
bool mayHaveSideEffects(Expression node) {
diff --git a/pkg/vm/lib/transformations/unreachable_code_elimination.dart b/pkg/vm/lib/transformations/unreachable_code_elimination.dart
index 10bd958..d61b8f4 100644
--- a/pkg/vm/lib/transformations/unreachable_code_elimination.dart
+++ b/pkg/vm/lib/transformations/unreachable_code_elimination.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart=2.12
-
import 'package:kernel/ast.dart';
/// Simple unreachable code elimination: removes asserts and if statements
diff --git a/pkg/vm/pubspec.yaml b/pkg/vm/pubspec.yaml
index 95341eb..20b2cd7 100644
--- a/pkg/vm/pubspec.yaml
+++ b/pkg/vm/pubspec.yaml
@@ -4,7 +4,7 @@
publish_to: none
environment:
- sdk: "^2.7.0"
+ sdk: '>=2.12.0 <3.0.0'
dependencies:
args: ^1.4.4
@@ -15,9 +15,8 @@
path: ../front_end
kernel:
path: ../kernel
- meta:
- path: ../meta
package_config: any
+ collection: ^1.15.0
dev_dependencies:
expect:
diff --git a/pkg/vm/test/common_test_utils.dart b/pkg/vm/test/common_test_utils.dart
index a45a95d..1ff586a 100644
--- a/pkg/vm/test/common_test_utils.dart
+++ b/pkg/vm/test/common_test_utils.dart
@@ -35,11 +35,11 @@
}
Future<Component> compileTestCaseToKernelProgram(Uri sourceUri,
- {Target target,
+ {Target? target,
bool enableSuperMixins = false,
- List<String> experimentalFlags,
- Map<String, String> environmentDefines,
- Uri packagesFileUri}) async {
+ List<String>? experimentalFlags,
+ Map<String, String>? environmentDefines,
+ Uri? packagesFileUri}) async {
final platformKernel =
computePlatformBinariesLocation().resolve('vm_platform_strong.dill');
target ??= new TestingVmTarget(new TargetFlags())
@@ -60,11 +60,11 @@
};
final Component component =
- (await kernelForProgram(sourceUri, options)).component;
+ (await kernelForProgram(sourceUri, options))!.component!;
// Make sure the library name is the same and does not depend on the order
// of test cases.
- component.mainMethod.enclosingLibrary.name = '#lib';
+ component.mainMethod!.enclosingLibrary.name = '#lib';
return component;
}
@@ -73,19 +73,19 @@
final StringBuffer buffer = new StringBuffer();
final printer = new Printer(buffer, showMetadata: true);
printer.writeLibraryFile(library);
- printer.writeConstantTable(library.enclosingComponent);
+ printer.writeConstantTable(library.enclosingComponent!);
return buffer
.toString()
- .replaceAll(library.importUri.toString(), library.name);
+ .replaceAll(library.importUri.toString(), library.name!);
}
String kernelComponentToString(Component component) {
final StringBuffer buffer = new StringBuffer();
new Printer(buffer, showMetadata: true).writeComponentFile(component);
- final mainLibrary = component.mainMethod.enclosingLibrary;
+ final mainLibrary = component.mainMethod!.enclosingLibrary;
return buffer
.toString()
- .replaceAll(mainLibrary.importUri.toString(), mainLibrary.name);
+ .replaceAll(mainLibrary.importUri.toString(), mainLibrary.name!);
}
class DevNullSink<T> extends Sink<T> {
diff --git a/pkg/vm/test/incremental_compiler_test.dart b/pkg/vm/test/incremental_compiler_test.dart
index 2fc1928..5b175e4 100644
--- a/pkg/vm/test/incremental_compiler_test.dart
+++ b/pkg/vm/test/incremental_compiler_test.dart
@@ -6,6 +6,7 @@
import 'dart:convert';
import 'dart:io';
+import 'package:collection/collection.dart' show IterableExtension;
import 'package:front_end/src/api_unstable/vm.dart'
show
CompilerOptions,
@@ -45,8 +46,8 @@
final options = getFreshOptions();
group('basic', () {
- Directory mytest;
- File main;
+ late Directory mytest;
+ late File main;
setUpAll(() {
mytest = Directory.systemTemp.createTempSync('incremental');
@@ -68,7 +69,7 @@
final StringBuffer buffer = new StringBuffer();
new Printer(buffer, showMetadata: true)
- .writeLibraryFile(component.mainMethod.enclosingLibrary);
+ .writeLibraryFile(component.mainMethod!.enclosingLibrary);
expect(
buffer.toString(),
equals('library /*isNonNullableByDefault*/;\n'
@@ -90,7 +91,7 @@
final StringBuffer buffer = new StringBuffer();
new Printer(buffer, showMetadata: true)
- .writeLibraryFile(component.mainMethod.enclosingLibrary);
+ .writeLibraryFile(component.mainMethod!.enclosingLibrary);
expect(
buffer.toString(),
equals('library /*isNonNullableByDefault*/;\n'
@@ -111,13 +112,13 @@
await compiler.compile();
compiler.accept();
{
- Procedure procedure = await compiler.compileExpression(
+ Procedure? procedure = await compiler.compileExpression(
'main', <String>[], <String>[], main.uri.toString(), null, true);
expect(procedure, isNotNull);
expect(errorsReported, equals(0));
}
{
- Procedure procedure = await compiler.compileExpression(
+ Procedure? procedure = await compiler.compileExpression(
'main1', <String>[], <String>[], main.uri.toString(), null, true);
expect(procedure, isNotNull);
expect(errorsReported, equals(1));
@@ -136,7 +137,7 @@
Future<Set<int>> collectAndCheckCoverageData(int port, bool getAllSources,
{bool resume: true,
bool onGetAllVerifyCount: true,
- Set<int> coverageForLines}) async {
+ Set<int>? coverageForLines}) async {
RemoteVm remoteVm = new RemoteVm(port);
// Wait for the script to have finished.
@@ -175,7 +176,7 @@
// Ensure that we can get a line and column number for all reported
// positions in the scripts we care about.
for (Map sourceReport in sourceReports) {
- List scripts = sourceReport["scripts"];
+ List<Map> scripts = sourceReport["scripts"].cast<Map>();
Map<String, int> scriptIdToIndex = new Map<String, int>();
Set<int> lib1scriptIndices = new Set<int>();
int i = 0;
@@ -199,9 +200,9 @@
Map<int, Map> scriptIndexToScript = new Map<int, Map>();
for (String scriptId in scriptIdToIndex.keys) {
Map script = await remoteVm.getObject(scriptId);
- int scriptIdx = scriptIdToIndex[scriptId];
+ int scriptIdx = scriptIdToIndex[scriptId]!;
scriptIndexToScript[scriptIdx] = script;
- List tokenPosTable = script["tokenPosTable"];
+ List? tokenPosTable = script["tokenPosTable"];
if (tokenPosTable == null) {
errorMessages.add("Script with uri ${script['uri']} "
"and id ${script['id']} "
@@ -213,7 +214,7 @@
}
}
- List ranges = sourceReport["ranges"];
+ List<Map> ranges = sourceReport["ranges"].cast<Map>();
Set<int> scriptIndexesSet = new Set<int>.from(scriptIndexToScript.keys);
for (Map range in ranges) {
if (scriptIndexesSet.contains(range["scriptIndex"])) {
@@ -231,7 +232,7 @@
if (range["possibleBreakpoints"] != null) {
for (int pos in range["possibleBreakpoints"]) positions.add(pos);
}
- Map script = scriptIndexToScript[range["scriptIndex"]];
+ Map script = scriptIndexToScript[range["scriptIndex"]]!;
Set<int> knownPositions = new Set<int>();
Map<int, int> tokenPosToLine = {};
if (script["tokenPosTable"] != null) {
@@ -254,7 +255,7 @@
if (coverageForLines != null) {
for (int pos in coverage["hits"]) {
if (lib1scriptIndices.contains(range["scriptIndex"])) {
- coverageForLines.add(tokenPosToLine[pos]);
+ coverageForLines.add(tokenPosToLine[pos]!);
}
}
}
@@ -269,10 +270,10 @@
}
group('multiple kernels', () {
- Directory mytest;
- File main;
- File lib;
- Process vm;
+ late Directory mytest;
+ late File main;
+ late File lib;
+ late Process vm;
setUpAll(() {
mytest = Directory.systemTemp.createTempSync('incremental');
main = new File('${mytest.path}/main.dart')..createSync();
@@ -483,8 +484,8 @@
.listen((String s) async {
if (s.startsWith(kObservatoryListening)) {
expect(observatoryPortRegExp.hasMatch(s), isTrue);
- final match = observatoryPortRegExp.firstMatch(s);
- port = int.parse(match.group(1));
+ final match = observatoryPortRegExp.firstMatch(s)!;
+ port = int.parse(match.group(1)!);
await collectAndCheckCoverageData(port, true);
if (!portLineCompleter.isCompleted) {
portLineCompleter.complete("done");
@@ -501,12 +502,12 @@
});
group('multiple kernels constant coverage', () {
- Directory mytest;
- File main;
- File lib1;
- int lineForUnnamedConstructor;
- int lineForNamedConstructor;
- Process vm;
+ late Directory mytest;
+ late File main;
+ late File lib1;
+ late int lineForUnnamedConstructor;
+ late int lineForNamedConstructor;
+ late Process vm;
setUpAll(() {
mytest = Directory.systemTemp.createTempSync('incremental');
main = new File('${mytest.path}/main.dart')..createSync();
@@ -592,8 +593,8 @@
}
if (s.startsWith(kObservatoryListening)) {
expect(observatoryPortRegExp.hasMatch(s), isTrue);
- final match = observatoryPortRegExp.firstMatch(s);
- port = int.parse(match.group(1));
+ final match = observatoryPortRegExp.firstMatch(s)!;
+ port = int.parse(match.group(1)!);
await collectAndCheckCoverageData(port, true,
onGetAllVerifyCount: false, coverageForLines: coverageLines);
if (!portLineCompleter.isCompleted) {
@@ -738,11 +739,11 @@
});
group('multiple kernels 2', () {
- Directory mytest;
- File main;
- File lib1;
- File lib2;
- Process vm;
+ late Directory mytest;
+ late File main;
+ late File lib1;
+ late File lib2;
+ late Process vm;
setUpAll(() {
mytest = Directory.systemTemp.createTempSync('incremental');
main = new File('${mytest.path}/main.dart')..createSync();
@@ -847,8 +848,8 @@
.listen((String s) async {
if (s.startsWith(kObservatoryListening)) {
expect(observatoryPortRegExp.hasMatch(s), isTrue);
- final match = observatoryPortRegExp.firstMatch(s);
- port = int.parse(match.group(1));
+ final match = observatoryPortRegExp.firstMatch(s)!;
+ port = int.parse(match.group(1)!);
Set<int> hits1 =
await collectAndCheckCoverageData(port, true, resume: false);
Set<int> hits2 =
@@ -869,7 +870,7 @@
});
group('reload', () {
- Directory mytest;
+ late Directory mytest;
setUpAll(() {
mytest = Directory.systemTemp.createTempSync('incremental');
@@ -939,8 +940,8 @@
final RegExp observatoryPortRegExp =
new RegExp("Observatory listening on http://127.0.0.1:\([0-9]*\)");
expect(observatoryPortRegExp.hasMatch(portLine), isTrue);
- final match = observatoryPortRegExp.firstMatch(portLine);
- final port = int.parse(match.group(1));
+ final match = observatoryPortRegExp.firstMatch(portLine)!;
+ final port = int.parse(match.group(1)!);
var remoteVm = new RemoteVm(port);
await remoteVm.resume();
@@ -976,7 +977,7 @@
});
group('reject', () {
- Directory mytest;
+ late Directory mytest;
setUpAll(() {
mytest = Directory.systemTemp.createTempSync('incremental_reject');
});
@@ -1023,7 +1024,7 @@
}
compiler.accept();
{
- Procedure procedure = await compiler.compileExpression(
+ Procedure? procedure = await compiler.compileExpression(
'a', <String>[], <String>[], 'package:foo/bar.dart', 'A', true);
expect(procedure, isNotNull);
}
@@ -1038,7 +1039,7 @@
}
await compiler.reject();
{
- Procedure procedure = await compiler.compileExpression(
+ Procedure? procedure = await compiler.compileExpression(
'a', <String>[], <String>[], 'package:foo/bar.dart', 'A', true);
expect(procedure, isNotNull);
}
@@ -1086,9 +1087,8 @@
}
compiler.accept();
{
- final Procedure procedure = await compiler.compileExpression(
- 'a', <String>[], <String>[], barUri.toString(), 'A', true);
- expect(procedure, isNotNull);
+ final Procedure procedure = (await compiler.compileExpression(
+ 'a', <String>[], <String>[], barUri.toString(), 'A', true))!;
// Verify that the expression only has links to the only bar we know
// about.
final LibraryReferenceCollector lrc = new LibraryReferenceCollector();
@@ -1105,8 +1105,8 @@
compiler.invalidate(barUri);
{
final Component component = await compiler.compile(entryPoint: fooUri);
- final Library fooLib2 = component.libraries
- .firstWhere((lib) => lib.fileUri == fooUri, orElse: () => null);
+ final Library? fooLib2 = component.libraries
+ .firstWhereOrNull((lib) => lib.fileUri == fooUri);
expect(fooLib2, isNull);
final Library barLib2 =
component.libraries.firstWhere((lib) => lib.fileUri == barUri);
@@ -1128,13 +1128,12 @@
// Verify that the saved "last known good" compnent only contains links
// to the original 'foo' and 'bar' libraries.
final LibraryReferenceCollector lrc = new LibraryReferenceCollector();
- compiler.lastKnownGoodComponent.accept(lrc);
+ compiler.lastKnownGoodComponent!.accept(lrc);
expect(lrc.librariesReferenced, equals(<Library>{fooLib, barLib}));
}
{
- final Procedure procedure = await compiler.compileExpression(
- 'a', <String>[], <String>[], barUri.toString(), 'A', true);
- expect(procedure, isNotNull);
+ final Procedure procedure = (await compiler.compileExpression(
+ 'a', <String>[], <String>[], barUri.toString(), 'A', true))!;
// Verify that the expression only has links to the original bar.
final LibraryReferenceCollector lrc = new LibraryReferenceCollector();
procedure.accept(lrc);
@@ -1144,8 +1143,8 @@
});
group('expression evaluation', () {
- Directory mytest;
- Process vm;
+ late Directory mytest;
+ late Process vm;
setUpAll(() {
mytest = Directory.systemTemp.createTempSync('expression_evaluation');
@@ -1166,7 +1165,7 @@
launchBreakAndEvaluate(File scriptOrDill, String scriptUriToBreakIn,
int lineToBreakAt, List<String> expressionsAndExpectedResults,
- {Future Function(RemoteVm remoteVm) callback}) async {
+ {Future Function(RemoteVm remoteVm)? callback}) async {
vm = await Process.start(Platform.resolvedExecutable, <String>[
"--pause-isolates-on-start",
"--enable-vm-service:0",
@@ -1188,8 +1187,8 @@
print("vm stdout: $s");
if (s.startsWith(kObservatoryListening)) {
expect(observatoryPortRegExp.hasMatch(s), isTrue);
- final match = observatoryPortRegExp.firstMatch(s);
- port = int.parse(match.group(1));
+ final match = observatoryPortRegExp.firstMatch(s)!;
+ port = int.parse(match.group(1)!);
RemoteVm remoteVm = new RemoteVm(port);
// Wait for the script to have loaded.
@@ -1589,7 +1588,7 @@
RemoteVm remoteVm, String scriptUriToBreakIn, int lineToBreakAt) async {
Map scriptsMap = await remoteVm.getScripts();
List scripts = scriptsMap["scripts"];
- String scriptId;
+ String? scriptId;
for (int i = 0; i < scripts.length; i++) {
Map script = scripts[i];
String scriptUri = script["uri"];
@@ -1600,7 +1599,7 @@
}
expect(scriptId, isNotNull);
- return await remoteVm.addBreakpoint(scriptId, lineToBreakAt);
+ return await remoteVm.addBreakpoint(scriptId!, lineToBreakAt);
}
Future deletePossibleBreakpoint(
@@ -1641,12 +1640,12 @@
/// An peer point used to send service protocol messages. The service
/// protocol uses JSON rpc on top of web-sockets.
json_rpc.Peer get rpc => _rpc ??= _createPeer();
- json_rpc.Peer _rpc;
+ json_rpc.Peer? _rpc;
/// The main isolate ID of the running VM. Needed to indicate to the VM which
/// isolate to reload.
FutureOr<String> get mainId async => _mainId ??= await _computeMainId();
- String _mainId;
+ String? _mainId;
RemoteVm([this.port = 8181]);
@@ -1699,41 +1698,34 @@
await rpc.sendRequest('resume', {'isolateId': id});
}
- Future getIsolate() async {
+ Future<Map> getIsolate() async {
var id = await mainId;
- return await rpc.sendRequest('getIsolate', {'isolateId': id});
+ return (await rpc.sendRequest('getIsolate', {'isolateId': id})) as Map;
}
- Future getScripts() async {
+ Future<Map> getScripts() async {
var id = await mainId;
- return await rpc.sendRequest('getScripts', {
+ return (await rpc.sendRequest('getScripts', {
'isolateId': id,
- });
+ })) as Map;
}
- Future getSourceReport([String scriptId]) async {
+ Future<Map> getSourceReport([String? scriptId]) async {
var id = await mainId;
- if (scriptId != null) {
- return await rpc.sendRequest('getSourceReport', {
- 'isolateId': id,
- 'scriptId': scriptId,
- 'reports': ['Coverage', 'PossibleBreakpoints'],
- 'forceCompile': true
- });
- }
- return await rpc.sendRequest('getSourceReport', {
+ return (await rpc.sendRequest('getSourceReport', {
'isolateId': id,
+ if (scriptId != null) 'scriptId': scriptId,
'reports': ['Coverage', 'PossibleBreakpoints'],
- 'forceCompile': true
- });
+ 'forceCompile': true,
+ })) as Map;
}
- Future getObject(String objectId) async {
+ Future<Map> getObject(String objectId) async {
var id = await mainId;
- return await rpc.sendRequest('getObject', {
+ return (await rpc.sendRequest('getObject', {
'isolateId': id,
'objectId': objectId,
- });
+ })) as Map;
}
Future addBreakpoint(String scriptId, int line) async {
@@ -1767,21 +1759,22 @@
int expectGcAfter = new DateTime.now().millisecondsSinceEpoch;
while (true) {
var id = await mainId;
- Map result = await rpc.sendRequest('getAllocationProfile', {
+ Map result = (await rpc.sendRequest('getAllocationProfile', {
'isolateId': id,
"gc": true,
- });
- String lastGc = result["dateLastServiceGC"];
+ })) as Map;
+ String? lastGc = result["dateLastServiceGC"];
if (lastGc != null && int.parse(lastGc) >= expectGcAfter) return;
}
}
/// Close any connections used to communicate with the VM.
Future disconnect() async {
- if (_rpc == null) return null;
+ final rpc = this._rpc;
+ if (rpc == null) return null;
this._mainId = null;
- if (!_rpc.isClosed) {
- var future = _rpc.close();
+ if (!rpc.isClosed) {
+ var future = rpc.close();
_rpc = null;
return future;
}
diff --git a/pkg/vm/test/kernel_front_end_test.dart b/pkg/vm/test/kernel_front_end_test.dart
index 711b616..effa84d 100644
--- a/pkg/vm/test/kernel_front_end_test.dart
+++ b/pkg/vm/test/kernel_front_end_test.dart
@@ -20,14 +20,14 @@
const String packagesFile = '.packages';
const String packageConfigFile = '.dart_tool/package_config.json';
-void testCompile(List<String> args) async {
+Future<void> testCompile(List<String> args) async {
final compilerExitCode =
await runCompiler(createCompilerArgParser().parse(args), '');
expect(compilerExitCode, successExitCode);
}
main() {
- Directory tempDir;
+ late Directory tempDir;
setUp(() {
var systemTempDir = Directory.systemTemp;
tempDir = systemTempDir.createTempSync('kernel_front_end_test');
diff --git a/pkg/vm/test/modular_kernel_plus_aot_test.dart b/pkg/vm/test/modular_kernel_plus_aot_test.dart
index 8d9419d..c853b01 100644
--- a/pkg/vm/test/modular_kernel_plus_aot_test.dart
+++ b/pkg/vm/test/modular_kernel_plus_aot_test.dart
@@ -33,14 +33,14 @@
await withTempDirectory((Uri uri) async {
final mixinFilename = uri.resolve('mixin.dart');
final mixinDillFilename = uri.resolve('mixin.dart.dill');
- await File.fromUri(mixinFilename).writeAsStringSync(mixinFile);
+ File.fromUri(mixinFilename).writeAsStringSync(mixinFile);
await compileToKernel(vmTarget, librariesFile, sdkSummary, packagesFile,
mixinDillFilename, <Uri>[mixinFilename], <Uri>[]);
final mainFilename = uri.resolve('main.dart');
final mainDillFilename = uri.resolve('main.dart.dill');
- await File.fromUri(mainFilename).writeAsStringSync(mainFile);
+ File.fromUri(mainFilename).writeAsStringSync(mainFile);
await compileToKernel(vmTarget, librariesFile, sdkSummary, packagesFile,
mainDillFilename, <Uri>[mainFilename], <Uri>[mixinDillFilename]);
@@ -96,9 +96,9 @@
message.plainTextFormatted.forEach(print);
}
- final Component component =
+ final Component? component =
await fe.compileComponent(state, sources, onDiagnostic);
- final Uint8List kernel = fe.serializeComponent(component,
+ final Uint8List kernel = fe.serializeComponent(component!,
filter: (library) => sources.contains(library.importUri));
await File(outputFile.toFilePath()).writeAsBytes(kernel);
}
diff --git a/pkg/vm/test/transformations/protobuf_aware_treeshaker/treeshaker_test.dart b/pkg/vm/test/transformations/protobuf_aware_treeshaker/treeshaker_test.dart
index 023c93e..741c2b9 100644
--- a/pkg/vm/test/transformations/protobuf_aware_treeshaker/treeshaker_test.dart
+++ b/pkg/vm/test/transformations/protobuf_aware_treeshaker/treeshaker_test.dart
@@ -36,7 +36,7 @@
.expand(
(lib) => lib.classes.where((klass) =>
klass.superclass != null &&
- klass.superclass.name == "GeneratedMessage"),
+ klass.superclass!.name == "GeneratedMessage"),
)
.toList();
diff --git a/pkg/vm/test/transformations/to_string_transformer_test.dart b/pkg/vm/test/transformations/to_string_transformer_test.dart
index ef94ca8..34f775f 100644
--- a/pkg/vm/test/transformations/to_string_transformer_test.dart
+++ b/pkg/vm/test/transformations/to_string_transformer_test.dart
@@ -27,7 +27,7 @@
transformComponent(component, packageUris);
verifyComponent(component);
- final actual = kernelLibraryToString(component.mainMethod.enclosingLibrary);
+ final actual = kernelLibraryToString(component.mainMethod!.enclosingLibrary);
compareResultWithExpectationsFile(
testCasesUri.resolve(expectationName), actual);
diff --git a/pkg/vm/test/transformations/type_flow/summary_collector_test.dart b/pkg/vm/test/transformations/type_flow/summary_collector_test.dart
index cad4936..09831bd8 100644
--- a/pkg/vm/test/transformations/type_flow/summary_collector_test.dart
+++ b/pkg/vm/test/transformations/type_flow/summary_collector_test.dart
@@ -58,11 +58,11 @@
void recordMemberCalledViaThis(Member target) {}
@override
- void recordTearOff(Procedure target) {}
+ void recordTearOff(Member target) {}
}
class PrintSummaries extends RecursiveVisitor {
- SummaryCollector _summaryCollector;
+ late SummaryCollector _summaryCollector;
final StringBuffer _buf = new StringBuffer();
PrintSummaries(Target target, TypeEnvironment environment,
@@ -75,12 +75,12 @@
new FakeEntryPointsListener(typesBuilder),
typesBuilder,
new NativeCodeOracle(
- null, new ConstantPragmaAnnotationParser(coreTypes)),
- new GenericInterfacesInfoImpl(hierarchy),
+ coreTypes.index, new ConstantPragmaAnnotationParser(coreTypes)),
+ new GenericInterfacesInfoImpl(coreTypes, hierarchy),
/*_protobufHandler=*/ null);
}
- String print(TreeNode node) {
+ String print(Library node) {
visitLibrary(node);
return _buf.toString();
}
@@ -99,10 +99,11 @@
runTestCase(Uri source) async {
final Target target = new TestingVmTarget(new TargetFlags());
final Component component = await compileTestCaseToKernelProgram(source);
- final Library library = component.mainMethod.enclosingLibrary;
+ final Library library = component.mainMethod!.enclosingLibrary;
final CoreTypes coreTypes = new CoreTypes(component);
- final ClassHierarchy hierarchy = new ClassHierarchy(component, coreTypes);
+ final ClosedWorldClassHierarchy hierarchy =
+ new ClassHierarchy(component, coreTypes) as ClosedWorldClassHierarchy;
final typeEnvironment = new TypeEnvironment(coreTypes, hierarchy);
final actual =
diff --git a/pkg/vm/test/transformations/type_flow/transformer_test.dart b/pkg/vm/test/transformations/type_flow/transformer_test.dart
index b1e876fe..0fee483 100644
--- a/pkg/vm/test/transformations/type_flow/transformer_test.dart
+++ b/pkg/vm/test/transformations/type_flow/transformer_test.dart
@@ -18,12 +18,11 @@
final String pkgVmDir = Platform.script.resolve('../../..').toFilePath();
-runTestCase(
- Uri source, List<String> experimentalFlags, bool enableNullSafety) async {
+runTestCase(Uri source, bool enableNullSafety) async {
final target =
new TestingVmTarget(new TargetFlags(enableNullSafety: enableNullSafety));
- Component component = await compileTestCaseToKernelProgram(source,
- target: target, experimentalFlags: experimentalFlags);
+ Component component =
+ await compileTestCaseToKernelProgram(source, target: target);
final coreTypes = new CoreTypes(component);
@@ -31,7 +30,7 @@
matcher: new ConstantPragmaAnnotationParser(coreTypes),
treeShakeProtobufs: true);
- String actual = kernelLibraryToString(component.mainMethod.enclosingLibrary);
+ String actual = kernelLibraryToString(component.mainMethod!.enclosingLibrary);
// Tests in /protobuf_handler consist of multiple libraries.
// Include libraries with protobuf generated messages into the result.
@@ -53,7 +52,7 @@
ensureKernelCanBeSerializedToBinary(component);
}
-String argsTestName(List<String> args) {
+String? argsTestName(List<String> args) {
if (args.length > 0) {
return args.last;
}
@@ -74,12 +73,7 @@
!path.endsWith('.pb.dart') &&
(testNameFilter == null || path.contains(testNameFilter))) {
final bool enableNullSafety = path.endsWith('_nnbd_strong.dart');
- final bool enableNNBD = enableNullSafety || path.endsWith('_nnbd.dart');
- final List<String> experimentalFlags = [
- if (enableNNBD) 'non-nullable',
- ];
- test(path,
- () => runTestCase(entry.uri, experimentalFlags, enableNullSafety));
+ test(path, () => runTestCase(entry.uri, enableNullSafety));
}
}
}, timeout: Timeout.none);
diff --git a/pkg/vm/test/transformations/type_flow/types_test.dart b/pkg/vm/test/transformations/type_flow/types_test.dart
index 0945917..203700be 100644
--- a/pkg/vm/test/transformations/type_flow/types_test.dart
+++ b/pkg/vm/test/transformations/type_flow/types_test.dart
@@ -21,15 +21,12 @@
@override
bool isSubtype(Class sub, Class sup) {
- return subtypes[sup].contains(sub);
+ return subtypes[sup]!.contains(sub);
}
@override
Type specializeTypeCone(TFClass base, {bool allowWideCone = false}) {
- Type result = specializations[base.classNode];
- expect(result, isNotNull,
- reason: "specializeTypeCone($base) is not defined");
- return result;
+ return specializations[base.classNode]!;
}
@override
@@ -102,10 +99,10 @@
test('union-intersection', () {
// T1 <: T3, T2 <: T3
- final c1 = new Class(name: 'T1', fileUri: dummyUri);
- final c2 = new Class(name: 'T2', fileUri: dummyUri);
- final c3 = new Class(name: 'T3', fileUri: dummyUri);
- final c4 = new Class(name: 'T4', fileUri: dummyUri);
+ final c1 = new Class(name: 'T1', fileUri: dummyUri)..parent = dummyLibrary;
+ final c2 = new Class(name: 'T2', fileUri: dummyUri)..parent = dummyLibrary;
+ final c3 = new Class(name: 'T3', fileUri: dummyUri)..parent = dummyLibrary;
+ final c4 = new Class(name: 'T4', fileUri: dummyUri)..parent = dummyLibrary;
final tfc1 = new TFClass(1, c1);
final tfc2 = new TFClass(2, c2);
@@ -293,9 +290,9 @@
});
test('hashcode-equals', () {
- final c1 = new Class(name: 'C1', fileUri: dummyUri);
- final c2 = new Class(name: 'C2', fileUri: dummyUri);
- final c3 = new Class(name: 'C3', fileUri: dummyUri);
+ final c1 = new Class(name: 'C1', fileUri: dummyUri)..parent = dummyLibrary;
+ final c2 = new Class(name: 'C2', fileUri: dummyUri)..parent = dummyLibrary;
+ final c3 = new Class(name: 'C3', fileUri: dummyUri)..parent = dummyLibrary;
final tfc1 = new TFClass(1, c1);
final tfc2 = new TFClass(2, c2);
diff --git a/pkg/vm/test/transformations/unreachable_code_elimination_test.dart b/pkg/vm/test/transformations/unreachable_code_elimination_test.dart
index d1471bb..c433611 100644
--- a/pkg/vm/test/transformations/unreachable_code_elimination_test.dart
+++ b/pkg/vm/test/transformations/unreachable_code_elimination_test.dart
@@ -28,7 +28,7 @@
component = transformComponent(component, /* enableAsserts = */ false);
verifyComponent(component);
- final actual = kernelLibraryToString(component.mainMethod.enclosingLibrary);
+ final actual = kernelLibraryToString(component.mainMethod!.enclosingLibrary);
compareResultWithExpectationsFile(source, actual);
}
diff --git a/pkg/vm/testcases/transformations/deferred_loading/main.dart.expect b/pkg/vm/testcases/transformations/deferred_loading/main.dart.expect
index 0d07eae..328e71f 100644
--- a/pkg/vm/testcases/transformations/deferred_loading/main.dart.expect
+++ b/pkg/vm/testcases/transformations/deferred_loading/main.dart.expect
@@ -46,12 +46,12 @@
import "#pkg/vm/testcases/transformations/deferred_loading/a.dart" as a;
static method j() → dynamic /* originally async */ {
- final dart.async::_Future<dynamic>* :async_future = new dart.async::_Future::•<dynamic>();
+ final dart.async::_Future<dynamic> :async_future = new dart.async::_Future::•<dynamic>();
dart.core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
- (dynamic) →* dynamic :async_op_then;
- (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
- dart.core::int* :await_jump_var = 0;
+ FutureOr<dynamic>? :return_value;
+ (dynamic) → dynamic :async_op_then;
+ (dart.core::Object, dart.core::StackTrace) → dynamic :async_op_error;
+ dart.core::int :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -62,12 +62,12 @@
dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
- on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
+ on dynamic catch(dynamic exception, dart.core::StackTrace stack_trace) {
dart.async::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
}
:async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
:async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
- :async_op(){() →* dynamic};
+ :async_op(){() → dynamic};
:is_sync = true;
return :async_future;
}
@@ -77,12 +77,12 @@
import "#pkg/vm/testcases/transformations/deferred_loading/g.dart" as g;
static method h() → dynamic /* originally async */ {
- final dart.async::_Future<dynamic>* :async_future = new dart.async::_Future::•<dynamic>();
+ final dart.async::_Future<dynamic> :async_future = new dart.async::_Future::•<dynamic>();
dart.core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
- (dynamic) →* dynamic :async_op_then;
- (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
- dart.core::int* :await_jump_var = 0;
+ FutureOr<dynamic>? :return_value;
+ (dynamic) → dynamic :async_op_then;
+ (dart.core::Object, dart.core::StackTrace) → dynamic :async_op_error;
+ dart.core::int :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -93,12 +93,12 @@
dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
- on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
+ on dynamic catch(dynamic exception, dart.core::StackTrace stack_trace) {
dart.async::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
}
:async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
:async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
- :async_op(){() →* dynamic};
+ :async_op(){() → dynamic};
:is_sync = true;
return :async_future;
}
@@ -109,12 +109,12 @@
import "#pkg/vm/testcases/transformations/deferred_loading/b.dart" as b;
static method i() → dynamic /* originally async */ {
- final dart.async::_Future<dynamic>* :async_future = new dart.async::_Future::•<dynamic>();
+ final dart.async::_Future<dynamic> :async_future = new dart.async::_Future::•<dynamic>();
dart.core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
- (dynamic) →* dynamic :async_op_then;
- (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
- dart.core::int* :await_jump_var = 0;
+ FutureOr<dynamic>? :return_value;
+ (dynamic) → dynamic :async_op_then;
+ (dart.core::Object, dart.core::StackTrace) → dynamic :async_op_error;
+ dart.core::int :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
@@ -130,12 +130,12 @@
dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
- on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
+ on dynamic catch(dynamic exception, dart.core::StackTrace stack_trace) {
dart.async::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
}
:async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
:async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
- :async_op(){() →* dynamic};
+ :async_op(){() → dynamic};
:is_sync = true;
return :async_future;
}
@@ -145,12 +145,12 @@
import "#pkg/vm/testcases/transformations/deferred_loading/h.dart" as h;
static method g() → dynamic /* originally async */ {
- final dart.async::_Future<dynamic>* :async_future = new dart.async::_Future::•<dynamic>();
+ final dart.async::_Future<dynamic> :async_future = new dart.async::_Future::•<dynamic>();
dart.core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
- (dynamic) →* dynamic :async_op_then;
- (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
- dart.core::int* :await_jump_var = 0;
+ FutureOr<dynamic>? :return_value;
+ (dynamic) → dynamic :async_op_then;
+ (dart.core::Object, dart.core::StackTrace) → dynamic :async_op_error;
+ dart.core::int :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -161,12 +161,12 @@
dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
- on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
+ on dynamic catch(dynamic exception, dart.core::StackTrace stack_trace) {
dart.async::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
}
:async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
:async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
- :async_op(){() →* dynamic};
+ :async_op(){() → dynamic};
:is_sync = true;
return :async_future;
}
@@ -177,12 +177,12 @@
import "#pkg/vm/testcases/transformations/deferred_loading/i.dart" deferred as i;
static method f() → dynamic /* originally async */ {
- final dart.async::_Future<dynamic>* :async_future = new dart.async::_Future::•<dynamic>();
+ final dart.async::_Future<dynamic> :async_future = new dart.async::_Future::•<dynamic>();
dart.core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
- (dynamic) →* dynamic :async_op_then;
- (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
- dart.core::int* :await_jump_var = 0;
+ FutureOr<dynamic>? :return_value;
+ (dynamic) → dynamic :async_op_then;
+ (dart.core::Object, dart.core::StackTrace) → dynamic :async_op_error;
+ dart.core::int :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
@@ -202,12 +202,12 @@
dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
- on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
+ on dynamic catch(dynamic exception, dart.core::StackTrace stack_trace) {
dart.async::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
}
:async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
:async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
- :async_op(){() →* dynamic};
+ :async_op(){() → dynamic};
:is_sync = true;
return :async_future;
}
@@ -217,12 +217,12 @@
import "#pkg/vm/testcases/transformations/deferred_loading/g.dart" deferred as g;
static method e() → dynamic /* originally async */ {
- final dart.async::_Future<dynamic>* :async_future = new dart.async::_Future::•<dynamic>();
+ final dart.async::_Future<dynamic> :async_future = new dart.async::_Future::•<dynamic>();
dart.core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
- (dynamic) →* dynamic :async_op_then;
- (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
- dart.core::int* :await_jump_var = 0;
+ FutureOr<dynamic>? :return_value;
+ (dynamic) → dynamic :async_op_then;
+ (dart.core::Object, dart.core::StackTrace) → dynamic :async_op_error;
+ dart.core::int :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
@@ -238,12 +238,12 @@
dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
- on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
+ on dynamic catch(dynamic exception, dart.core::StackTrace stack_trace) {
dart.async::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
}
:async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
:async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
- :async_op(){() →* dynamic};
+ :async_op(){() → dynamic};
:is_sync = true;
return :async_future;
}
@@ -254,12 +254,12 @@
import "#pkg/vm/testcases/transformations/deferred_loading/f.dart" deferred as f;
static method c() → dynamic /* originally async */ {
- final dart.async::_Future<dynamic>* :async_future = new dart.async::_Future::•<dynamic>();
+ final dart.async::_Future<dynamic> :async_future = new dart.async::_Future::•<dynamic>();
dart.core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
- (dynamic) →* dynamic :async_op_then;
- (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
- dart.core::int* :await_jump_var = 0;
+ FutureOr<dynamic>? :return_value;
+ (dynamic) → dynamic :async_op_then;
+ (dart.core::Object, dart.core::StackTrace) → dynamic :async_op_error;
+ dart.core::int :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
@@ -275,12 +275,12 @@
dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
- on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
+ on dynamic catch(dynamic exception, dart.core::StackTrace stack_trace) {
dart.async::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
}
:async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
:async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
- :async_op(){() →* dynamic};
+ :async_op(){() → dynamic};
:is_sync = true;
return :async_future;
}
@@ -290,12 +290,12 @@
import "#pkg/vm/testcases/transformations/deferred_loading/e.dart" as e;
static method d() → dynamic /* originally async */ {
- final dart.async::_Future<dynamic>* :async_future = new dart.async::_Future::•<dynamic>();
+ final dart.async::_Future<dynamic> :async_future = new dart.async::_Future::•<dynamic>();
dart.core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
- (dynamic) →* dynamic :async_op_then;
- (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
- dart.core::int* :await_jump_var = 0;
+ FutureOr<dynamic>? :return_value;
+ (dynamic) → dynamic :async_op_then;
+ (dart.core::Object, dart.core::StackTrace) → dynamic :async_op_error;
+ dart.core::int :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -308,12 +308,12 @@
dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
- on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
+ on dynamic catch(dynamic exception, dart.core::StackTrace stack_trace) {
dart.async::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
}
:async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
:async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
- :async_op(){() →* dynamic};
+ :async_op(){() → dynamic};
:is_sync = true;
return :async_future;
}
@@ -323,12 +323,12 @@
import "#pkg/vm/testcases/transformations/deferred_loading/c.dart" as c;
static method b() → dynamic /* originally async */ {
- final dart.async::_Future<dynamic>* :async_future = new dart.async::_Future::•<dynamic>();
+ final dart.async::_Future<dynamic> :async_future = new dart.async::_Future::•<dynamic>();
dart.core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
- (dynamic) →* dynamic :async_op_then;
- (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
- dart.core::int* :await_jump_var = 0;
+ FutureOr<dynamic>? :return_value;
+ (dynamic) → dynamic :async_op_then;
+ (dart.core::Object, dart.core::StackTrace) → dynamic :async_op_error;
+ dart.core::int :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -341,12 +341,12 @@
dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
- on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
+ on dynamic catch(dynamic exception, dart.core::StackTrace stack_trace) {
dart.async::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
}
:async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
:async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
- :async_op(){() →* dynamic};
+ :async_op(){() → dynamic};
:is_sync = true;
return :async_future;
}
@@ -356,12 +356,12 @@
import "#pkg/vm/testcases/transformations/deferred_loading/d.dart" deferred as d;
static method a() → dynamic /* originally async */ {
- final dart.async::_Future<dynamic>* :async_future = new dart.async::_Future::•<dynamic>();
+ final dart.async::_Future<dynamic> :async_future = new dart.async::_Future::•<dynamic>();
dart.core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
- (dynamic) →* dynamic :async_op_then;
- (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
- dart.core::int* :await_jump_var = 0;
+ FutureOr<dynamic>? :return_value;
+ (dynamic) → dynamic :async_op_then;
+ (dart.core::Object, dart.core::StackTrace) → dynamic :async_op_error;
+ dart.core::int :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
@@ -377,12 +377,12 @@
dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
- on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
+ on dynamic catch(dynamic exception, dart.core::StackTrace stack_trace) {
dart.async::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
}
:async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
:async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
- :async_op(){() →* dynamic};
+ :async_op(){() → dynamic};
:is_sync = true;
return :async_future;
}
@@ -393,12 +393,12 @@
import "#pkg/vm/testcases/transformations/deferred_loading/b.dart";
static method main() → dynamic /* originally async */ {
- final dart.async::_Future<dynamic>* :async_future = new dart.async::_Future::•<dynamic>();
+ final dart.async::_Future<dynamic> :async_future = new dart.async::_Future::•<dynamic>();
dart.core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
- (dynamic) →* dynamic :async_op_then;
- (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
- dart.core::int* :await_jump_var = 0;
+ FutureOr<dynamic>? :return_value;
+ (dynamic) → dynamic :async_op_then;
+ (dart.core::Object, dart.core::StackTrace) → dynamic :async_op_error;
+ dart.core::int :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
@@ -413,12 +413,12 @@
dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
- on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
+ on dynamic catch(dynamic exception, dart.core::StackTrace stack_trace) {
dart.async::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
}
:async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
:async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
- :async_op(){() →* dynamic};
+ :async_op(){() → dynamic};
:is_sync = true;
return :async_future;
}
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/bool_expressions.dart b/pkg/vm/testcases/transformations/type_flow/summary_collector/bool_expressions.dart
index a22bad2..64dbb46 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/bool_expressions.dart
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/bool_expressions.dart
@@ -3,7 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
dynamic foo() => null;
-bool bar() => null;
+bool bar() => false;
void bool_expressions() {
if (foo()) {}
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/bool_expressions.dart.expect b/pkg/vm/testcases/transformations/type_flow/summary_collector/bool_expressions.dart.expect
index 625d97f..85822829 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/bool_expressions.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/bool_expressions.dart.expect
@@ -3,25 +3,26 @@
RESULT: _T {}?
------------ bar ------------
-RESULT: _T {}?
+RESULT: _T (dart.core::bool, false)
------------ bool_expressions ------------
t0* = _Call direct [#lib::foo] ()
-t1 = _TypeCheck (t0 against dart.core::bool*) (for #lib::foo() as dart.core::bool*)
+t1 = _TypeCheck (t0 against dart.core::bool) (for #lib::foo() as dart.core::bool)
t2* = _Call direct [#lib::bar] ()
t3* = _Call [dart.core::num.+] (_T (dart.core::int)+, _T (dart.core::_Smi, 1))
-i_0 = _Join [dart.core::int*] (_T (dart.core::_Smi, 0), t3)
+i_0 = _Join [dart.core::int] (_T (dart.core::_Smi, 0), t3)
t5* = _Call [dart.core::num.<] (i_0, _T (dart.core::_Smi, 10))
t6* = _Call direct [#lib::bar] ()
-t7* = _Call direct [#lib::foo] ()
-t8 = _Join [dynamic] (_T (dart.core::bool, true), t7)
-t9 = _TypeCheck (t8 against dart.core::bool*) (for (x ?{dynamic} true : #lib::foo()) as dart.core::bool*)
-t10* = _Call direct [#lib::bar] ()
+t7 = _TypeCheck (t6 against dart.core::bool) (for x is dart.core::bool)
+t8* = _Call direct [#lib::foo] ()
+t9 = _Join [dynamic] (_T (dart.core::bool, true), t8)
+t10 = _TypeCheck (t9 against dart.core::bool) (for (x ?{dynamic} true : #lib::foo()) as dart.core::bool)
t11* = _Call direct [#lib::bar] ()
-t12* = _Call direct [#lib::foo] ()
-t13 = _TypeCheck (t12 against dart.core::bool*) (for #lib::foo() as dart.core::bool*)
-t14* = _Call direct [#lib::foo] ()
-t15 = _TypeCheck (t14 against dart.core::bool*) (for #lib::foo() as dart.core::bool*)
-y_0 = _Join [dart.core::bool*] (_T (dart.core::bool), _T (dart.core::bool, true))
+t12* = _Call direct [#lib::bar] ()
+t13* = _Call direct [#lib::foo] ()
+t14 = _TypeCheck (t13 against dart.core::bool) (for #lib::foo() as dart.core::bool)
+t15* = _Call direct [#lib::foo] ()
+t16 = _TypeCheck (t15 against dart.core::bool) (for #lib::foo() as dart.core::bool)
+y_0 = _Join [dart.core::bool] (_T (dart.core::bool), _T (dart.core::bool, true))
RESULT: _T {}?
------------ main ------------
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/calls.dart b/pkg/vm/testcases/transformations/type_flow/summary_collector/calls.dart
index 06cf7ea..d507ee0 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/calls.dart
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/calls.dart
@@ -11,19 +11,19 @@
class B {
void bar1(Object arg) {}
dynamic get bar2 => null;
- set bar3(int y) {}
- int bar4;
+ set bar3(int? y) {}
+ int? bar4;
}
class C {
- interfaceCalls(A aa, Object a2, Object a3, Object a4) {
+ interfaceCalls(A aa, Object a2, Object a3, Object? a4) {
aa.foo1(new B());
aa.foo3 = aa.foo2;
a4 = aa.foo2(a2, a3, aa.foo1);
return a4;
}
- dynamicCalls(dynamic aa, Object a2, Object a3, Object a4) {
+ dynamicCalls(dynamic aa, Object a2, Object a3, Object? a4) {
aa.foo1(new B());
aa.foo3 = aa.foo2;
a4 = aa.foo2(a2, a3, aa.foo1);
@@ -32,7 +32,7 @@
}
class D extends B {
- superCalls(Object a1, Object a2, Object a3, Object a4) {
+ superCalls(Object a1, Object a2, Object a3, Object? a4) {
super.bar1(a1);
super.bar3 = super.bar4;
a4 = super.bar2(a2, a3, super.bar1);
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/calls.dart.expect b/pkg/vm/testcases/transformations/type_flow/summary_collector/calls.dart.expect
index bbd410a..2731094 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/calls.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/calls.dart.expect
@@ -34,11 +34,11 @@
%a2 = _Parameter #2 [_T (dart.core::Object)+?]
%a3 = _Parameter #3 [_T (dart.core::Object)+?]
%a4 = _Parameter #4 [_T (dart.core::Object)+?]
-t5 = _Call direct [#lib::B.] (_T (#lib::B))
-t6 = _Call [#lib::A.foo1] (%aa, _T (#lib::B))
+t5* = _Call direct [#lib::B.] (_T (#lib::B))
+t6 = _Call [#lib::A.foo1] (%aa, t5)
t7 = _Narrow (%aa to _T ANY)
t8* = _Call get [#lib::A.foo2] (t7)
-t9 = _TypeCheck (t8 against dart.core::int*) (for aa.{#lib::A.foo2} as dart.core::int*)
+t9 = _TypeCheck (t8 against dart.core::int) (for aa.{#lib::A.foo2} as dart.core::int)
t10 = _Call set [#lib::A.foo3] (t7, t9)
t11* = _Call get [#lib::A.foo1] (t7)
t12* = _Call get [#lib::A.foo2] (t7)
@@ -50,8 +50,8 @@
%a2 = _Parameter #2 [_T (dart.core::Object)+?]
%a3 = _Parameter #3 [_T (dart.core::Object)+?]
%a4 = _Parameter #4 [_T (dart.core::Object)+?]
-t5 = _Call direct [#lib::B.] (_T (#lib::B))
-t6 = _Call dynamic [foo1] (%aa, _T (#lib::B))
+t5* = _Call direct [#lib::B.] (_T (#lib::B))
+t6 = _Call dynamic [foo1] (%aa, t5)
t7 = _Narrow (%aa to _T ANY)
t8* = _Call dynamic get [foo2] (t7)
t9 = _Call dynamic set [foo3] (t7, t8)
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/class_generics_basic.dart.expect b/pkg/vm/testcases/transformations/type_flow/summary_collector/class_generics_basic.dart.expect
index 6f36339..18d97a8 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/class_generics_basic.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/class_generics_basic.dart.expect
@@ -4,21 +4,21 @@
RESULT: _T {}?
------------ C.foo ------------
%this = _Parameter #0 [_T (#lib::C)+]
-t1 = _Extract (%this[#lib::C/0]*)
+t1 = _Extract (%this[#lib::C/0])
t2 = _CreateConcreteType (#lib::D @ (t1))
-t3 = _Call direct [#lib::D.] (t2)
-RESULT: t2
+t3* = _Call direct [#lib::D.] (t2)
+RESULT: t3
------------ C.id1 ------------
%this = _Parameter #0 [_T (#lib::C)+]
%x = _Parameter #1
-t2 = _Extract (%this[#lib::C/0]*)
-t3 = _TypeCheck (%x against t2) (for #lib::C.T* x;)
+t2 = _Extract (%this[#lib::C/0])
+t3 = _TypeCheck (%x against t2) (for #lib::C.T% x;)
RESULT: t3
------------ C.id2 ------------
%this = _Parameter #0 [_T (#lib::C)+]
%x = _Parameter #1
-t2 = _Extract (%this[#lib::C/0]*)
-t3 = _TypeCheck (%x against t2) (for #lib::C.T* x;)
+t2 = _Extract (%this[#lib::C/0])
+t3 = _TypeCheck (%x against t2) (for #lib::C.T% x;)
RESULT: t3
------------ D. ------------
%this = _Parameter #0 [_T (#lib::D)+]
@@ -34,16 +34,16 @@
RESULT: t1
------------ E.bar ------------
%this = _Parameter #0 [_T (#lib::E)+]
-t1 = _Extract (%this[#lib::E/0]*)
+t1 = _Extract (%this[#lib::E/0])
t2 = _CreateConcreteType (#lib::D @ (t1))
-t3 = _Call direct [#lib::D.] (t2)
-RESULT: t2
+t3* = _Call direct [#lib::D.] (t2)
+RESULT: t3
------------ E.baz ------------
%this = _Parameter #0 [_T (#lib::E)+]
-t1 = _Extract (%this[#lib::E/1]*)
+t1 = _Extract (%this[#lib::E/1])
t2 = _CreateConcreteType (#lib::D @ (t1))
-t3 = _Call direct [#lib::D.] (t2)
-RESULT: t2
+t3* = _Call direct [#lib::D.] (t2)
+RESULT: t3
------------ X. ------------
%this = _Parameter #0 [_T (#lib::X)+]
t1 = _Call direct [dart.core::Object.] (%this)
@@ -75,34 +75,34 @@
------------ C2.id3 ------------
%this = _Parameter #0 [_T (#lib::C2)+]
%x = _Parameter #1
-t2 = _Extract (%this[#lib::C2/0]*)
-t3 = _CreateRuntimeType (dart.core::Comparable @ (t2)*)
-t4 = _TypeCheck (%x against t3) (for dart.core::Comparable<#lib::C2.T*>* x;)
+t2 = _Extract (%this[#lib::C2/0])
+t3 = _CreateRuntimeType (dart.core::Comparable @ (t2))
+t4 = _TypeCheck (%x against t3) (for dart.core::Comparable<#lib::C2.T%> x;)
RESULT: t4
------------ C2.id4 ------------
%this = _Parameter #0 [_T (#lib::C2)+]
%x = _Parameter #1
-t2 = _Extract (%this[#lib::C2/0]*)
-t3 = _CreateRuntimeType (#lib::I @ (t2)*)
-t4 = _CreateRuntimeType (#lib::K @ (t3)*)
-t5 = _TypeCheck (%x against t4) (for #lib::K<#lib::I<#lib::C2.T*>*>* x;)
+t2 = _Extract (%this[#lib::C2/0])
+t3 = _CreateRuntimeType (#lib::I @ (t2))
+t4 = _CreateRuntimeType (#lib::K @ (t3))
+t5 = _TypeCheck (%x against t4) (for #lib::K<#lib::I<#lib::C2.T%>> x;)
RESULT: t5
------------ main ------------
-t0 = _Call direct [#lib::C.] (_T (#lib::C<dart.core::int*>))
-t1 = _Call [#lib::C.foo] (_T (#lib::C<dart.core::int*>))
-t2 = _Call direct [#lib::E.] (_T (#lib::E<dart.core::int*, dart.core::String*>))
-t3 = _Call [#lib::E.foo] (_T (#lib::E<dart.core::int*, dart.core::String*>))
-t4 = _Call direct [#lib::E.] (_T (#lib::E<dart.core::int*, dart.core::String*>))
-t5 = _Call [#lib::E.bar] (_T (#lib::E<dart.core::int*, dart.core::String*>))
-t6 = _Call direct [#lib::E.] (_T (#lib::E<dart.core::int*, dart.core::String*>))
-t7* = _Call [#lib::E.baz] (_T (#lib::E<dart.core::int*, dart.core::String*>))
-t8 = _Call direct [#lib::C.] (_T (#lib::C<#lib::Y*>))
-t9 = _Call direct [#lib::Y.] (_T (#lib::Y))
-t10 = _Call [#lib::C.id1] (_T (#lib::C<#lib::Y*>), _T (#lib::Y))
-t11 = _Call direct [#lib::Z.] (_T (#lib::Z))
-t12 = _Call [#lib::C.id2] (_T (#lib::C<#lib::Y*>), _T (#lib::Z))
-t13 = _Call direct [#lib::C2.] (_T (#lib::C2<dart.core::num*>))
-t14 = _Call [#lib::C2.id3] (_T (#lib::C2<dart.core::num*>), _T (dart.core::_Double, 3.0))
-t15 = _Call direct [#lib::K.] (_T (#lib::K<#lib::J*>))
-t16 = _Call [#lib::C2.id4] (_T (#lib::C2<dart.core::num*>), _T (#lib::K<#lib::J*>))
+t0* = _Call direct [#lib::C.] (_T (#lib::C<dart.core::int>))
+t1 = _Call [#lib::C.foo] (t0)
+t2* = _Call direct [#lib::E.] (_T (#lib::E<dart.core::int, dart.core::String>))
+t3 = _Call [#lib::E.foo] (t2)
+t4* = _Call direct [#lib::E.] (_T (#lib::E<dart.core::int, dart.core::String>))
+t5 = _Call [#lib::E.bar] (t4)
+t6* = _Call direct [#lib::E.] (_T (#lib::E<dart.core::int, dart.core::String>))
+t7* = _Call [#lib::E.baz] (t6)
+t8* = _Call direct [#lib::C.] (_T (#lib::C<#lib::Y>))
+t9* = _Call direct [#lib::Y.] (_T (#lib::Y))
+t10 = _Call [#lib::C.id1] (t8, t9)
+t11* = _Call direct [#lib::Z.] (_T (#lib::Z))
+t12 = _Call [#lib::C.id2] (t8, t11)
+t13* = _Call direct [#lib::C2.] (_T (#lib::C2<dart.core::num>))
+t14 = _Call [#lib::C2.id3] (t13, _T (dart.core::_Double, 3.0))
+t15* = _Call direct [#lib::K.] (_T (#lib::K<#lib::J>))
+t16 = _Call [#lib::C2.id4] (t13, t15)
RESULT: t7
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/class_generics_case1.dart b/pkg/vm/testcases/transformations/type_flow/summary_collector/class_generics_case1.dart
index 3b211f3..fe65bb4 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/class_generics_case1.dart
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/class_generics_case1.dart
@@ -30,10 +30,10 @@
class InheritedElement extends Element {
// The inferred type for '_dependents' needs to be concrete and have exact
// type arguments.
- final MockHashMap<Element, Object> _dependents =
- MockHashMap<Element, Object>();
+ final MockHashMap<Element, Object?> _dependents =
+ MockHashMap<Element, Object?>();
- void setDependencies(Element dependent, Object value) {
+ void setDependencies(Element dependent, Object? value) {
_dependents.setEntry(dependent, value);
}
}
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/class_generics_case1.dart.expect b/pkg/vm/testcases/transformations/type_flow/summary_collector/class_generics_case1.dart.expect
index 0eea29d..f833ff4 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/class_generics_case1.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/class_generics_case1.dart.expect
@@ -6,8 +6,8 @@
%K = _Parameter #0
%V = _Parameter #1
t2 = _CreateConcreteType (#lib::_NotRealHashMap @ (%K, %V))
-t3 = _Call direct [#lib::_NotRealHashMap.] (t2)
-RESULT: t2
+t3* = _Call direct [#lib::_NotRealHashMap.] (t2)
+RESULT: t3
------------ _NotRealHashMap. ------------
%this = _Parameter #0 [_T (#lib::_NotRealHashMap)+]
t1 = _Call direct [dart.core::Object.] (%this)
@@ -16,10 +16,10 @@
%this = _Parameter #0 [_T (#lib::_NotRealHashMap)+]
%key = _Parameter #1
%value = _Parameter #2
-t3 = _Extract (%this[#lib::_NotRealHashMap/0]*)
-t4 = _TypeCheck (%key against t3) (for #lib::_NotRealHashMap.K* key;)
-t5 = _Extract (%this[#lib::_NotRealHashMap/1]*)
-t6 = _TypeCheck (%value against t5) (for #lib::_NotRealHashMap.V* value;)
+t3 = _Extract (%this[#lib::_NotRealHashMap/0])
+t4 = _TypeCheck (%key against t3) (for #lib::_NotRealHashMap.K% key;)
+t5 = _Extract (%this[#lib::_NotRealHashMap/1])
+t6 = _TypeCheck (%value against t5) (for #lib::_NotRealHashMap.V% value;)
RESULT: _T {}?
------------ InheritedElement. ------------
%this = _Parameter #0 [_T (#lib::InheritedElement)+]
@@ -34,11 +34,11 @@
RESULT: _T {}?
------------ InheritedElement._dependents ------------
%this = _Parameter #0 [_T (#lib::InheritedElement)+]
-t1* = _Call direct [#lib::MockHashMap.] (#lib::Element*, dart.core::Object*)
+t1* = _Call direct [#lib::MockHashMap.] (#lib::Element, dart.core::Object?)
RESULT: t1
------------ main ------------
-t0 = _Call direct [#lib::InheritedElement.] (_T (#lib::InheritedElement))
-t1 = _Call [#lib::InheritedElement.setDependencies] (_T (#lib::InheritedElement), _T (#lib::InheritedElement), _T (dart.core::_Smi, 0))
-t2 = _Call direct [#lib::Element.] (_T (#lib::Element))
-t3 = _Call [#lib::InheritedElement.setDependencies] (_T (#lib::InheritedElement), _T (#lib::Element), _T {}?)
+t0* = _Call direct [#lib::InheritedElement.] (_T (#lib::InheritedElement))
+t1 = _Call [#lib::InheritedElement.setDependencies] (t0, t0, _T (dart.core::_Smi, 0))
+t2* = _Call direct [#lib::Element.] (_T (#lib::Element))
+t3 = _Call [#lib::InheritedElement.setDependencies] (t0, t2, _T {}?)
RESULT: _T {}?
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/constants.dart.expect b/pkg/vm/testcases/transformations/type_flow/summary_collector/constants.dart.expect
index a894b41..010aa92 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/constants.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/constants.dart.expect
@@ -13,7 +13,7 @@
RESULT: t1
------------ indexingIntoConstantList2 ------------
%i = _Parameter #0 [_T (dart.core::int)+?]
-t1 = _Join [dart.core::Object*] (_T (dart.core::_OneByteString, "hi"), _T (dart.core::_Smi, 33), _T {}?, _T (dart.core::_Smi, -5))
+t1 = _Join [dart.core::Object?] (_T (dart.core::_OneByteString, "hi"), _T (dart.core::_Smi, 33), _T {}?, _T (dart.core::_Smi, -5))
RESULT: t1
------------ main ------------
@@ -23,4 +23,4 @@
RESULT: _T (dart.core::_ImmutableList, const <dart.core::int*>[1, 2, 3])
------------ _constList2 ------------
-RESULT: _T (dart.core::_ImmutableList, const <dart.core::Object*>["hi", 33, null, -5])
+RESULT: _T (dart.core::_ImmutableList, const <dart.core::Object?>["hi", 33, null, -5])
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/control_flow.dart.expect b/pkg/vm/testcases/transformations/type_flow/summary_collector/control_flow.dart.expect
index d0227dd..80bbada 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/control_flow.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/control_flow.dart.expect
@@ -47,64 +47,64 @@
------------ sequence ------------
t0 = _Call direct [#lib::C1.] (_T (#lib::C1))
t1 = _Call direct [#lib::C2.] (_T (#lib::C2))
-t2 = _Call direct [#lib::C3.] (_T (#lib::C3))
-RESULT: _T (#lib::C3)
+t2* = _Call direct [#lib::C3.] (_T (#lib::C3))
+RESULT: t2
------------ if1 ------------
%cond = _Parameter #0 [_T (dart.core::bool)+?]
-t1 = _Call direct [#lib::C1.] (_T (#lib::C1))
-t2 = _Call direct [#lib::C2.] (_T (#lib::C2))
-t3 = _Call direct [#lib::foo] (_T (#lib::C2))
-x_0 = _Join [dynamic] (_T (#lib::C2), _T (#lib::C1))
+t1* = _Call direct [#lib::C1.] (_T (#lib::C1))
+t2* = _Call direct [#lib::C2.] (_T (#lib::C2))
+t3 = _Call direct [#lib::foo] (t2)
+x_0 = _Join [dynamic] (t2, t1)
RESULT: x_0
------------ if2 ------------
%cond1 = _Parameter #0 [_T (dart.core::bool)+?]
%cond2 = _Parameter #1 [_T (dart.core::bool)+?]
-t2 = _Call direct [#lib::C1.] (_T (#lib::C1))
-t3 = _Call direct [#lib::foo] (_T (#lib::C1))
-t4 = _Call direct [#lib::C2.] (_T (#lib::C2))
-t5 = _Call direct [#lib::bar] (_T (#lib::C2))
-x_0 = _Join [dynamic] (_T (#lib::C1), _T (#lib::C2))
+t2* = _Call direct [#lib::C1.] (_T (#lib::C1))
+t3 = _Call direct [#lib::foo] (t2)
+t4* = _Call direct [#lib::C2.] (_T (#lib::C2))
+t5 = _Call direct [#lib::bar] (t4)
+x_0 = _Join [dynamic] (t2, t4)
RESULT: x_0
------------ if3 ------------
%cond1 = _Parameter #0 [_T (dart.core::bool)+?]
%cond2 = _Parameter #1 [_T (dart.core::bool)+?]
t2 = _Call direct [#lib::C1.] (_T (#lib::C1))
-t3 = _Call direct [#lib::C2.] (_T (#lib::C2))
-t4* = _Call direct [#lib::foo] (_T (#lib::C2))
-t5 = _TypeCheck (t4 against dart.core::bool*) (for #lib::foo(x = new #lib::C2()) as dart.core::bool*)
-t6 = _Call direct [#lib::C3.] (_T (#lib::C3))
-t7* = _Call direct [#lib::foo] (_T (#lib::C3))
-t8 = _TypeCheck (t7 against dart.core::bool*) (for #lib::foo(x = new #lib::C3()) as dart.core::bool*)
-x_0 = _Join [dynamic] (_T (#lib::C2), _T (#lib::C3))
+t3* = _Call direct [#lib::C2.] (_T (#lib::C2))
+t4* = _Call direct [#lib::foo] (t3)
+t5 = _TypeCheck (t4 against dart.core::bool) (for #lib::foo(x = new #lib::C2()) as dart.core::bool)
+t6* = _Call direct [#lib::C3.] (_T (#lib::C3))
+t7* = _Call direct [#lib::foo] (t6)
+t8 = _TypeCheck (t7 against dart.core::bool) (for #lib::foo(x = new #lib::C3()) as dart.core::bool)
+x_0 = _Join [dynamic] (t3, t6)
t10 = _Call direct [#lib::bar] (x_0)
RESULT: x_0
------------ if4 ------------
t0 = _Call direct [#lib::C1.] (_T (#lib::C1))
-t1 = _Call direct [#lib::C2.] (_T (#lib::C2))
-t2* = _Call direct [#lib::foo] (_T (#lib::C2))
-t3 = _TypeCheck (t2 against dart.core::bool*) (for #lib::foo(x = new #lib::C2()) as dart.core::bool*)
-t4 = _Call direct [#lib::C3.] (_T (#lib::C3))
-t5* = _Call direct [#lib::foo] (_T (#lib::C3))
-t6 = _TypeCheck (t5 against dart.core::bool*) (for #lib::foo(x = new #lib::C3()) as dart.core::bool*)
-t7 = _Call direct [#lib::bar] (_T (#lib::C3))
-x_0 = _Join [dynamic] (_T (#lib::C2), _T (#lib::C3))
+t1* = _Call direct [#lib::C2.] (_T (#lib::C2))
+t2* = _Call direct [#lib::foo] (t1)
+t3 = _TypeCheck (t2 against dart.core::bool) (for #lib::foo(x = new #lib::C2()) as dart.core::bool)
+t4* = _Call direct [#lib::C3.] (_T (#lib::C3))
+t5* = _Call direct [#lib::foo] (t4)
+t6 = _TypeCheck (t5 against dart.core::bool) (for #lib::foo(x = new #lib::C3()) as dart.core::bool)
+t7 = _Call direct [#lib::bar] (t4)
+x_0 = _Join [dynamic] (t1, t4)
RESULT: x_0
------------ if5 ------------
%cond = _Parameter #0 [_T (dart.core::bool)+?]
-t1 = _Call direct [#lib::C1.] (_T (#lib::C1))
+t1* = _Call direct [#lib::C1.] (_T (#lib::C1))
t2 = _Call direct [#lib::C2.] (_T (#lib::C2))
-t3 = _Call direct [#lib::foo] (_T (#lib::C1))
+t3 = _Call direct [#lib::foo] (t1)
RESULT: _T {}?
------------ if6a ------------
%x = _Parameter #0 [_T (dart.core::bool)+?]
t1 = _Call direct [#lib::foo] (_T (dart.core::bool, true))
t2 = _Call direct [#lib::bar] (_T (dart.core::bool, false))
-x_0 = _Join [dart.core::bool*] (_T (dart.core::bool, true), _T (dart.core::bool, false))
+x_0 = _Join [dart.core::bool] (_T (dart.core::bool, true), _T (dart.core::bool, false))
t4 = _Call direct [#lib::baz] (x_0)
RESULT: _T {}?
------------ if6b ------------
%x = _Parameter #0 [_T ANY?]
-t1 = _TypeCheck (%x against dart.core::bool*) (for x as dart.core::bool*)
+t1 = _TypeCheck (%x against dart.core::bool) (for x as dart.core::bool)
t2 = _Call direct [#lib::foo] (_T (dart.core::bool, true))
t3 = _Call direct [#lib::bar] (_T (dart.core::bool, false))
x_0 = _Join [dynamic] (_T (dart.core::bool, true), _T (dart.core::bool, false))
@@ -124,26 +124,26 @@
RESULT: _T {}?
------------ if8 ------------
%x = _Parameter #0 [_T ANY?]
-t1 = _Narrow (%x to _T (dart.core::String)+)
+t1 = _TypeCheck (%x against dart.core::String) (for x is dart.core::String)
t2 = _Call direct [#lib::foo] (t1)
RESULT: _T {}?
------------ if9 ------------
%x = _Parameter #0 [_T (#lib::TestEnum)+?]
-t1* = _Call [#lib::TestEnum.==] (%x, _T (#lib::TestEnum, const #lib::TestEnum{#lib::TestEnum.index: 0, #lib::TestEnum._name: "TestEnum.v1"}))
+t1* = _Call [dart.core::Object.==] (%x, _T (#lib::TestEnum, const #lib::TestEnum{#lib::TestEnum.index: 0, #lib::TestEnum._name: "TestEnum.v1"}))
t2 = _Call direct [#lib::foo] (_T (#lib::TestEnum, const #lib::TestEnum{#lib::TestEnum.index: 0, #lib::TestEnum._name: "TestEnum.v1"}))
RESULT: _T {}?
------------ conditional1 ------------
%cond1 = _Parameter #0 [_T (dart.core::bool)+?]
%cond2 = _Parameter #1 [_T (dart.core::bool)+?]
t2 = _Call direct [#lib::C1.] (_T (#lib::C1))
-t3 = _Call direct [#lib::C2.] (_T (#lib::C2))
-t4* = _Call direct [#lib::foo] (_T (#lib::C2))
-t5 = _TypeCheck (t4 against dart.core::bool*) (for #lib::foo(x = new #lib::C2()) as dart.core::bool*)
-t6 = _Call direct [#lib::C3.] (_T (#lib::C3))
-t7 = _Call direct [#lib::C4.] (_T (#lib::C4))
-x_0 = _Join [dynamic] (_T (#lib::C3), _T (#lib::C4))
+t3* = _Call direct [#lib::C2.] (_T (#lib::C2))
+t4* = _Call direct [#lib::foo] (t3)
+t5 = _TypeCheck (t4 against dart.core::bool) (for #lib::foo(x = new #lib::C2()) as dart.core::bool)
+t6* = _Call direct [#lib::C3.] (_T (#lib::C3))
+t7* = _Call direct [#lib::C4.] (_T (#lib::C4))
+x_0 = _Join [dynamic] (t6, t7)
t9 = _Call direct [#lib::foo] (x_0)
-t10 = _Join [dart.core::Object*] (_T (#lib::C3), _T (#lib::C4))
+t10 = _Join [dart.core::Object] (t6, t7)
t11 = _Narrow (t10 to _T (dart.core::Object)+?)
t12 = _Call direct [#lib::bar] (t11)
RESULT: _T {}?
@@ -151,129 +151,129 @@
%cond1 = _Parameter #0 [_T (dart.core::bool)+?]
%cond2 = _Parameter #1 [_T (dart.core::bool)+?]
t2 = _Call direct [#lib::C1.] (_T (#lib::C1))
-t3 = _Call direct [#lib::C2.] (_T (#lib::C2))
-t4* = _Call direct [#lib::foo] (_T (#lib::C2))
-t5 = _TypeCheck (t4 against dart.core::bool*) (for #lib::foo(x = new #lib::C2()) as dart.core::bool*)
-t6 = _Call direct [#lib::C3.] (_T (#lib::C3))
-t7 = _Call direct [#lib::C4.] (_T (#lib::C4))
-t8* = _Call direct [dart.core::_GrowableList._literal2] (#lib::C4*, _T (#lib::C4), _T {})
+t3* = _Call direct [#lib::C2.] (_T (#lib::C2))
+t4* = _Call direct [#lib::foo] (t3)
+t5 = _TypeCheck (t4 against dart.core::bool) (for #lib::foo(x = new #lib::C2()) as dart.core::bool)
+t6* = _Call direct [#lib::C3.] (_T (#lib::C3))
+t7* = _Call direct [#lib::C4.] (_T (#lib::C4))
+t8* = _Call direct [dart.core::_GrowableList._literal2] (#lib::C4, t7, _T {})
t9* = _Call direct [#lib::foo] (t8)
-t10 = _Call direct [#lib::foo] (_T (#lib::C3))
-t11 = _Join [dynamic] (_T (#lib::C3), t9)
+t10 = _Call direct [#lib::foo] (t6)
+t11 = _Join [dynamic] (t6, t9)
t12 = _Call direct [#lib::bar] (t11)
RESULT: _T {}?
------------ loop1 ------------
-t0 = _Call direct [#lib::C1.] (_T (#lib::C1))
-x_0 = _Join [dynamic] (_T (#lib::C1), _T (#lib::C2))
-t2* = _Call direct [#lib::foo] (x_0)
-t3 = _TypeCheck (t2 against dart.core::bool*) (for #lib::foo(x) as dart.core::bool*)
-t4 = _Call direct [#lib::C2.] (_T (#lib::C2))
+t0* = _Call direct [#lib::C1.] (_T (#lib::C1))
+t1* = _Call direct [#lib::C2.] (_T (#lib::C2))
+x_0 = _Join [dynamic] (t0, t1)
+t3* = _Call direct [#lib::foo] (x_0)
+t4 = _TypeCheck (t3 against dart.core::bool) (for #lib::foo(x) as dart.core::bool)
t5 = _Call direct [#lib::bar] (x_0)
RESULT: x_0
------------ loop2 ------------
-t0 = _Call direct [#lib::C1.] (_T (#lib::C1))
-x_0 = _Join [dynamic] (_T (#lib::C1), _T (#lib::C3))
-t2 = _Call direct [#lib::foo] (x_0)
-t3 = _Call direct [#lib::C2.] (_T (#lib::C2))
-t4 = _Call direct [#lib::bar] (_T (#lib::C2))
-t5 = _Call direct [#lib::C3.] (_T (#lib::C3))
-t6* = _Call direct [#lib::bar] (_T (#lib::C3))
-t7 = _TypeCheck (t6 against dart.core::bool*) (for #lib::bar(x = new #lib::C3()) as dart.core::bool*)
-RESULT: _T (#lib::C3)
+t0* = _Call direct [#lib::C1.] (_T (#lib::C1))
+t1* = _Call direct [#lib::C3.] (_T (#lib::C3))
+x_0 = _Join [dynamic] (t0, t1)
+t3 = _Call direct [#lib::foo] (x_0)
+t4* = _Call direct [#lib::C2.] (_T (#lib::C2))
+t5 = _Call direct [#lib::bar] (t4)
+t6* = _Call direct [#lib::bar] (t1)
+t7 = _TypeCheck (t6 against dart.core::bool) (for #lib::bar(x = new #lib::C3()) as dart.core::bool)
+RESULT: t1
------------ loop3 ------------
t0 = _Call direct [#lib::C1.] (_T (#lib::C1))
-t1 = _Call direct [#lib::C2.] (_T (#lib::C2))
-t2* = _Call direct [#lib::foo] (_T (#lib::C2))
-t3 = _TypeCheck (t2 against dart.core::bool*) (for #lib::foo(x = new #lib::C2()) as dart.core::bool*)
+t1* = _Call direct [#lib::C2.] (_T (#lib::C2))
+t2* = _Call direct [#lib::foo] (t1)
+t3 = _TypeCheck (t2 against dart.core::bool) (for #lib::foo(x = new #lib::C2()) as dart.core::bool)
t4 = _Call direct [#lib::C3.] (_T (#lib::C3))
-t5 = _Call direct [#lib::bar] (_T (#lib::C2))
-RESULT: _T (#lib::C2)
+t5 = _Call direct [#lib::bar] (t1)
+RESULT: t1
------------ loop4 ------------
t0 = _Call direct [#lib::C1.] (_T (#lib::C1))
-t1 = _Call direct [#lib::C2.] (_T (#lib::C2))
-t2* = _Call direct [#lib::foo] (_T (#lib::C2))
+t1* = _Call direct [#lib::C2.] (_T (#lib::C2))
+t2* = _Call direct [#lib::foo] (t1)
t3* = _Call direct [dart.core::_GrowableList._literal1] (dynamic?, t2)
t4* = _Call get [dart.core::Iterable.iterator] (t3)
t5* = _Call [dart.core::Iterator.moveNext] (t4)
t6 = _Narrow (t4 to _T ANY)
t7 = _Call get [dart.core::Iterator.current] (t6)
-x_0 = _Join [dynamic] (_T (#lib::C2), _T (#lib::C3))
-t9 = _Call direct [#lib::foo] (x_0)
-t10 = _Call direct [#lib::C3.] (_T (#lib::C3))
+t8* = _Call direct [#lib::C3.] (_T (#lib::C3))
+x_0 = _Join [dynamic] (t1, t8)
+t10 = _Call direct [#lib::foo] (x_0)
RESULT: x_0
------------ loop5 ------------
-t0 = _Call direct [#lib::C1.] (_T (#lib::C1))
-x_0 = _Join [dynamic] (_T (#lib::C1), _T (#lib::C3))
-t2* = _Call direct [#lib::foo] (x_0)
-t3 = _TypeCheck (t2 against dart.core::bool*) (for #lib::foo(x) as dart.core::bool*)
-t4 = _Call direct [#lib::C2.] (_T (#lib::C2))
-t5* = _Call direct [#lib::bar] (_T (#lib::C2))
-t6 = _TypeCheck (t5 against dart.core::bool*) (for #lib::bar(x) as dart.core::bool*)
-t7 = _Call direct [#lib::C3.] (_T (#lib::C3))
-x_1 = _Join [dynamic] (x_0, _T (#lib::C2))
+t0* = _Call direct [#lib::C1.] (_T (#lib::C1))
+t1* = _Call direct [#lib::C3.] (_T (#lib::C3))
+x_0 = _Join [dynamic] (t0, t1)
+t3* = _Call direct [#lib::foo] (x_0)
+t4 = _TypeCheck (t3 against dart.core::bool) (for #lib::foo(x) as dart.core::bool)
+t5* = _Call direct [#lib::C2.] (_T (#lib::C2))
+t6* = _Call direct [#lib::bar] (t5)
+t7 = _TypeCheck (t6 against dart.core::bool) (for #lib::bar(x) as dart.core::bool)
+x_1 = _Join [dynamic] (x_0, t5)
RESULT: x_1
------------ loop6 ------------
-t0 = _Call direct [#lib::C1.] (_T (#lib::C1))
-x_1 = _Join [dynamic] (_T (#lib::C3), _T (#lib::C2))
-x_0 = _Join [dynamic] (_T (#lib::C1), x_1)
-t3* = _Call direct [#lib::foo] (x_0)
-t4 = _TypeCheck (t3 against dart.core::bool*) (for #lib::foo(x) as dart.core::bool*)
-t5 = _Call direct [#lib::C2.] (_T (#lib::C2))
-t6* = _Call direct [#lib::bar] (_T (#lib::C2))
-t7 = _TypeCheck (t6 against dart.core::bool*) (for #lib::bar(x) as dart.core::bool*)
-t8 = _Call direct [#lib::C3.] (_T (#lib::C3))
+t0* = _Call direct [#lib::C1.] (_T (#lib::C1))
+t1* = _Call direct [#lib::C3.] (_T (#lib::C3))
+t2* = _Call direct [#lib::C2.] (_T (#lib::C2))
+x_1 = _Join [dynamic] (t1, t2)
+x_0 = _Join [dynamic] (t0, x_1)
+t5* = _Call direct [#lib::foo] (x_0)
+t6 = _TypeCheck (t5 against dart.core::bool) (for #lib::foo(x) as dart.core::bool)
+t7* = _Call direct [#lib::bar] (t2)
+t8 = _TypeCheck (t7 against dart.core::bool) (for #lib::bar(x) as dart.core::bool)
RESULT: x_0
------------ try1 ------------
-t0 = _Call direct [#lib::C1.] (_T (#lib::C1))
-t1 = _Call direct [#lib::C2.] (_T (#lib::C2))
-x_0 = _Join [dynamic] (_T (#lib::C1), _T (#lib::C2), _T (#lib::C3))
-t3 = _Call direct [#lib::foo] (x_0)
-t4 = _Call direct [#lib::C3.] (_T (#lib::C3))
+t0* = _Call direct [#lib::C1.] (_T (#lib::C1))
+t1* = _Call direct [#lib::C2.] (_T (#lib::C2))
+t2* = _Call direct [#lib::C3.] (_T (#lib::C3))
+x_0 = _Join [dynamic] (t0, t1, t2)
+t4 = _Call direct [#lib::foo] (x_0)
t5 = _Call direct [#lib::bar] (x_0)
-t6 = _Call direct [#lib::C4.] (_T (#lib::C4))
-RESULT: _T (#lib::C4)
+t6* = _Call direct [#lib::C4.] (_T (#lib::C4))
+RESULT: t6
------------ closure1 ------------
-t0 = _Call direct [#lib::C1.] (_T (#lib::C1))
-x_0 = _Join [dynamic] (_T (#lib::C1), _T (#lib::C2))
-t2 = _Call direct [#lib::foo] (x_0)
-t3 = _Call direct [#lib::bar] (x_0)
-t4 = _Call direct [#lib::foo] (_T ANY?)
-t5 = _Call direct [#lib::C2.] (_T (#lib::C2))
+t0* = _Call direct [#lib::C1.] (_T (#lib::C1))
+t1* = _Call direct [#lib::C2.] (_T (#lib::C2))
+x_0 = _Join [dynamic] (t0, t1)
+t3 = _Call direct [#lib::foo] (x_0)
+t4 = _Call direct [#lib::bar] (x_0)
+t5 = _Call direct [#lib::foo] (_T ANY?)
RESULT: _T {}?
------------ closure2 ------------
-t0 = _Call direct [#lib::C1.] (_T (#lib::C1))
-x_0 = _Join [dynamic] (_T (#lib::C1), _T (#lib::C2))
-t2 = _Call direct [#lib::foo] (x_0)
-t3 = _Call direct [#lib::C2.] (_T (#lib::C2))
+t0* = _Call direct [#lib::C1.] (_T (#lib::C1))
+t1* = _Call direct [#lib::C2.] (_T (#lib::C2))
+x_0 = _Join [dynamic] (t0, t1)
+t3 = _Call direct [#lib::foo] (x_0)
t4 = _Call direct [#lib::foo] (_T ANY?)
RESULT: x_0
------------ switch1 ------------
%selector = _Parameter #0 [_T (dart.core::int)+?]
-t1 = _Call direct [#lib::C1.] (_T (#lib::C1))
-t2 = _Call direct [#lib::C2.] (_T (#lib::C2))
-t3 = _Call direct [#lib::C3.] (_T (#lib::C3))
-x_2 = _Join [dynamic] (_T (#lib::C3), _T (#lib::C1))
-x_3 = _Join [dynamic] (x_2, _T (#lib::C2))
+t1* = _Call direct [#lib::C1.] (_T (#lib::C1))
+t2* = _Call direct [#lib::C2.] (_T (#lib::C2))
+t3* = _Call direct [#lib::C3.] (_T (#lib::C3))
+x_2 = _Join [dynamic] (t3, t1)
+x_3 = _Join [dynamic] (x_2, t2)
RESULT: x_3
------------ switch2 ------------
%selector = _Parameter #0 [_T (dart.core::int)+?]
t1 = _Call direct [#lib::C1.] (_T (#lib::C1))
-t2 = _Call direct [#lib::C2.] (_T (#lib::C2))
-t3 = _Call direct [#lib::C3.] (_T (#lib::C3))
-x_2 = _Join [dynamic] (_T (#lib::C3), _T (#lib::C2))
+t2* = _Call direct [#lib::C2.] (_T (#lib::C2))
+t3* = _Call direct [#lib::C3.] (_T (#lib::C3))
+x_2 = _Join [dynamic] (t3, t2)
RESULT: x_2
------------ switch3 ------------
%selector = _Parameter #0 [_T (dart.core::int)+?]
-t1 = _Call direct [#lib::C1.] (_T (#lib::C1))
-t2 = _Call direct [#lib::C2.] (_T (#lib::C2))
-x_1 = _Join [dynamic] (_T (#lib::C1), _T (#lib::C2))
+t1* = _Call direct [#lib::C1.] (_T (#lib::C1))
+t2* = _Call direct [#lib::C2.] (_T (#lib::C2))
+x_1 = _Join [dynamic] (t1, t2)
t4 = _Call direct [#lib::foo] (x_1)
-t5 = _Call direct [#lib::C3.] (_T (#lib::C3))
-x_2 = _Join [dynamic] (_T (#lib::C1), _T (#lib::C3))
+t5* = _Call direct [#lib::C3.] (_T (#lib::C3))
+x_2 = _Join [dynamic] (t1, t5)
RESULT: x_2
------------ cast1 ------------
%x = _Parameter #0 [_T ANY?]
-t1 = _TypeCheck (%x against #lib::C1*) (for x as #lib::C1*)
+t1 = _TypeCheck (%x against #lib::C1) (for x as #lib::C1)
t2 = _Call direct [#lib::foo] (t1)
t3 = _Call direct [#lib::bar] (t1)
RESULT: _T {}?
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/implicit_return_null.dart b/pkg/vm/testcases/transformations/type_flow/summary_collector/implicit_return_null.dart
index 11518c5..3757ca5 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/implicit_return_null.dart
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/implicit_return_null.dart
@@ -7,7 +7,7 @@
empty1() {}
void empty2() {}
dynamic empty3() {} // ignore: missing_return
-Object empty4() {} // ignore: missing_return
+Object? empty4() {} // ignore: missing_return
Object return1() {
return new T();
@@ -184,7 +184,8 @@
if (c) {
return new T();
}
- try {} on ArgumentError {} finally {
+ try {} on ArgumentError {
+ } finally {
throw 'Error!';
}
}
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/implicit_return_null.dart.expect b/pkg/vm/testcases/transformations/type_flow/summary_collector/implicit_return_null.dart.expect
index b584c86..8b3a909 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/implicit_return_null.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/implicit_return_null.dart.expect
@@ -15,16 +15,16 @@
RESULT: _T {}?
------------ return1 ------------
-t0 = _Call direct [#lib::T.] (_T (#lib::T))
-RESULT: _T (#lib::T)
+t0* = _Call direct [#lib::T.] (_T (#lib::T))
+RESULT: t0
------------ return2 ------------
%i = _Parameter #0 [_T (dart.core::int)+?]
t1* = _Call [dart.core::num.-] (%i, _T (dart.core::_Smi, 1))
t2* = _Call direct [#lib::return2] (t1)
RESULT: t2
------------ return3 ------------
-t0 = _Call direct [#lib::T.] (_T (#lib::T))
-RESULT: _T (#lib::T)
+t0* = _Call direct [#lib::T.] (_T (#lib::T))
+RESULT: t0
------------ return4 ------------
RESULT: _T {}?
@@ -33,16 +33,16 @@
RESULT: _T {}?
------------ expr2 ------------
%c = _Parameter #0 [_T (dart.core::bool)+?]
-t1 = _Call direct [#lib::T.] (_T (#lib::T))
+t1* = _Call direct [#lib::T.] (_T (#lib::T))
t2 = _Call direct [#lib::T.] (_T (#lib::T))
-%result = _Join [dynamic] (_T (#lib::T), _T {}?)
+%result = _Join [dynamic] (t1, _T {}?)
RESULT: %result
------------ expr3 ------------
%c = _Parameter #0 [_T (dart.core::bool)+?]
%x = _Parameter #1 [_T (dart.core::Object)+?]
-t2 = _Call direct [#lib::T.] (_T (#lib::T))
+t2* = _Call direct [#lib::T.] (_T (#lib::T))
t3 = _Call [dart.core::Object.toString] (%x)
-%result = _Join [dynamic] (_T (#lib::T), _T {}?)
+%result = _Join [dynamic] (t2, _T {}?)
RESULT: %result
------------ throw1 ------------
%c = _Parameter #0 [_T (dart.core::bool)+?]
@@ -51,8 +51,8 @@
------------ throw2 ------------
%c = _Parameter #0 [_T (dart.core::bool)+?]
%x = _Parameter #1 [_T (dart.core::Object)+?]
-t2 = _Call direct [#lib::T.] (_T (#lib::T))
-RESULT: _T (#lib::T)
+t2* = _Call direct [#lib::T.] (_T (#lib::T))
+RESULT: t2
------------ loop1 ------------
%c = _Parameter #0 [_T (dart.core::bool)+?]
%x = _Parameter #1 [_T (dart.core::Object)+?]
@@ -60,29 +60,29 @@
------------ loop2 ------------
%c = _Parameter #0 [_T (dart.core::bool)+?]
%x = _Parameter #1 [_T (dart.core::Object)+?]
-t2 = _Call direct [#lib::T.] (_T (#lib::T))
-%result = _Join [dynamic] (_T (#lib::T), _T {}?)
+t2* = _Call direct [#lib::T.] (_T (#lib::T))
+%result = _Join [dynamic] (t2, _T {}?)
RESULT: %result
------------ loop3 ------------
%c = _Parameter #0 [_T (dart.core::bool)+?]
%x = _Parameter #1 [_T (dart.core::Object)+?]
-t2 = _Call direct [#lib::T.] (_T (#lib::T))
-%result = _Join [dynamic] (_T (#lib::T), _T {}?)
+t2* = _Call direct [#lib::T.] (_T (#lib::T))
+%result = _Join [dynamic] (t2, _T {}?)
RESULT: %result
------------ switch_ ------------
%c = _Parameter #0 [_T (dart.core::bool)+?]
%i = _Parameter #1 [_T (dart.core::int)+?]
-t2 = _Call direct [#lib::T.] (_T (#lib::T))
-%result = _Join [dynamic] (_T (#lib::T), _T {}?)
+t2* = _Call direct [#lib::T.] (_T (#lib::T))
+%result = _Join [dynamic] (t2, _T {}?)
RESULT: %result
------------ if1 ------------
%c = _Parameter #0 [_T (dart.core::bool)+?]
-t1 = _Call direct [#lib::T.] (_T (#lib::T))
-RESULT: _T (#lib::T)
+t1* = _Call direct [#lib::T.] (_T (#lib::T))
+RESULT: t1
------------ if2 ------------
%c = _Parameter #0 [_T (dart.core::bool)+?]
-t1 = _Call direct [#lib::T.] (_T (#lib::T))
-%result = _Join [dynamic] (_T (#lib::T), _T {}?)
+t1* = _Call direct [#lib::T.] (_T (#lib::T))
+%result = _Join [dynamic] (t1, _T {}?)
RESULT: %result
------------ if3 ------------
%c = _Parameter #0 [_T (dart.core::bool)+?]
@@ -98,36 +98,36 @@
RESULT: %result
------------ label1 ------------
%c = _Parameter #0 [_T (dart.core::bool)+?]
-t1 = _Call direct [#lib::T.] (_T (#lib::T))
-%result = _Join [dynamic] (_T (#lib::T), _T {}?)
+t1* = _Call direct [#lib::T.] (_T (#lib::T))
+%result = _Join [dynamic] (t1, _T {}?)
RESULT: %result
------------ try1 ------------
%c = _Parameter #0 [_T (dart.core::bool)+?]
-t1 = _Call direct [#lib::T.] (_T (#lib::T))
-%result = _Join [dynamic] (_T (#lib::T), _T {}?)
+t1* = _Call direct [#lib::T.] (_T (#lib::T))
+%result = _Join [dynamic] (t1, _T {}?)
RESULT: %result
------------ try2 ------------
-t0 = _Call direct [#lib::T.] (_T (#lib::T))
-%result = _Join [dynamic] (_T (#lib::T), _T {}?)
+t0* = _Call direct [#lib::T.] (_T (#lib::T))
+%result = _Join [dynamic] (t0, _T {}?)
RESULT: %result
------------ try3 ------------
-t0 = _Call direct [#lib::T.] (_T (#lib::T))
-RESULT: _T (#lib::T)
+t0* = _Call direct [#lib::T.] (_T (#lib::T))
+RESULT: t0
------------ try4 ------------
%c = _Parameter #0 [_T (dart.core::bool)+?]
-t1 = _Call direct [#lib::T.] (_T (#lib::T))
-%result = _Join [dynamic] (_T (#lib::T), _T {}?)
+t1* = _Call direct [#lib::T.] (_T (#lib::T))
+%result = _Join [dynamic] (t1, _T {}?)
RESULT: %result
------------ try5 ------------
-t0 = _Call direct [#lib::T.] (_T (#lib::T))
-RESULT: _T (#lib::T)
+t0* = _Call direct [#lib::T.] (_T (#lib::T))
+RESULT: t0
------------ try6 ------------
-t0 = _Call direct [#lib::T.] (_T (#lib::T))
-RESULT: _T (#lib::T)
+t0* = _Call direct [#lib::T.] (_T (#lib::T))
+RESULT: t0
------------ try7 ------------
%c = _Parameter #0 [_T (dart.core::bool)+?]
-t1 = _Call direct [#lib::T.] (_T (#lib::T))
-RESULT: _T (#lib::T)
+t1* = _Call direct [#lib::T.] (_T (#lib::T))
+RESULT: t1
------------ main ------------
RESULT: _T {}?
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/vars.dart b/pkg/vm/testcases/transformations/type_flow/summary_collector/vars.dart
index 753486f..4101ae0 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/vars.dart
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/vars.dart
@@ -2,13 +2,13 @@
// 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.
-bool someStatic;
+late bool someStatic;
class A {}
class B {}
-Object foo(Object a1, [Object a2]) {
+Object? foo(Object a1, [Object? a2]) {
if (someStatic) {
a1 = new A();
}
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/vars.dart.expect b/pkg/vm/testcases/transformations/type_flow/summary_collector/vars.dart.expect
index d46d957..b559883 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/vars.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/vars.dart.expect
@@ -10,22 +10,22 @@
%a1 = _Parameter #0 [_T (dart.core::Object)+?]
%a2 = _Parameter #1 [_T (dart.core::Object)+?]
t2* = _Call direct get [#lib::someStatic] ()
-t3 = _Call direct [#lib::A.] (_T (#lib::A))
-a1_0 = _Join [dart.core::Object*] (_T (#lib::A), %a1)
+t3* = _Call direct [#lib::A.] (_T (#lib::A))
+a1_0 = _Join [dart.core::Object] (t3, %a1)
t5 = _Call direct [#lib::bar] (a1_0, _T (dart.core::_Smi, 42))
-t6 = _Call direct [#lib::B.] (_T (#lib::B))
-t7* = _Call [dart.core::Object.==] (_T (#lib::B), %a2)
-t8 = _Join [dart.core::Object*] (_T (#lib::B), %a2)
+t6* = _Call direct [#lib::B.] (_T (#lib::B))
+t7* = _Call [dart.core::Object.==] (t6, %a2)
+t8 = _Join [dart.core::Object?] (t6, %a2)
t9 = _Narrow (t8 to _T (dart.core::Object)+?)
RESULT: t9
------------ bar ------------
%a1 = _Parameter #0 [_T (dart.core::Object)+?]
%a2 = _Parameter #1 [_T (dart.core::int)+?]
-t2 = _Narrow (%a1 to _T (dart.core::int)+)
+t2 = _TypeCheck (%a1 against dart.core::int) (for v1 is dart.core::int)
t3* = _Call [dart.core::num.+] (t2, %a2)
t4* = _Call [dart.core::num.*] (t3, _T (dart.core::_Smi, 3))
t5* = _Call [dart.core::int.unary-] (_T (dart.core::_Smi, 1))
-%result = _Join [dart.core::int*] (t4, t5)
+%result = _Join [dart.core::int] (t4, t5)
RESULT: %result
------------ loop1 ------------
%a1 = _Parameter #0 [_T (dart.core::Object)+?]
@@ -35,10 +35,10 @@
------------ loop2 ------------
%x = _Parameter #0 [_T (dart.core::int)+?]
t1* = _Call [dart.core::num.+] (_T (dart.core::int)+, _T (dart.core::_Smi, 1))
-i_0 = _Join [dart.core::int*] (_T (dart.core::_Smi, 0), t1)
+i_0 = _Join [dart.core::int] (_T (dart.core::_Smi, 0), t1)
t3* = _Call [dart.core::num.<] (i_0, _T (dart.core::_Smi, 5))
t4* = _Call [dart.core::num.+] (_T (dart.core::int)+?, _T (dart.core::_Smi, 10))
-x_0 = _Join [dart.core::int*] (%x, t4)
+x_0 = _Join [dart.core::int] (%x, t4)
RESULT: x_0
------------ main ------------
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/abstract_class_entry_point.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/abstract_class_entry_point.dart.expect
index 02a29c4..46131e7 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/abstract_class_entry_point.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/abstract_class_entry_point.dart.expect
@@ -1,4 +1,4 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/annotation.dart b/pkg/vm/testcases/transformations/type_flow/transformer/annotation.dart
index b5b68eb..5fbfc30 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/annotation.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/annotation.dart
@@ -45,7 +45,7 @@
@TypedefAnnotation([1, 2, 3])
typedef void SomeType<T>(List<T> arg);
-int foo(SomeType<int> a) {
+int foo(SomeType<int>? a) {
@VarAnnotation()
int x = 2;
return x + 2;
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/annotation.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/annotation.dart.expect
index 70239f8..a86774c 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/annotation.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/annotation.dart.expect
@@ -1,23 +1,23 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
-typedef SomeType<contravariant T extends core::Object* = dynamic> = (core::List<T*>*) →* void;
+typedef SomeType<contravariant T extends core::Object? = dynamic> = (core::List<T%>) → void;
abstract class A extends core::Object {
static method staticMethod() → void {}
}
class B extends core::Object {
- synthetic constructor •() → self::B*
+ synthetic constructor •() → self::B
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method instanceMethod() → void {}
}
-[@vm.unboxing-info.metadata=()->i]static method foo() → core::int* {
- core::int* x = 2;
- return [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] x.{core::num::+}(2){(core::num*) →* core::int*};
+[@vm.unboxing-info.metadata=()->i]static method foo() → core::int {
+ core::int x = 2;
+ return [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] x.{core::num::+}(2){(core::num) → core::int};
}
-static method main(core::List<core::String*>* args) → dynamic {
+static method main(core::List<core::String> args) → dynamic {
self::A::staticMethod();
- [@vm.direct-call.metadata=#lib::B.instanceMethod] [@vm.inferred-type.metadata=!? (skip check)] new self::B::•().{self::B::instanceMethod}(){() →* void};
+ [@vm.direct-call.metadata=#lib::B.instanceMethod] [@vm.inferred-type.metadata=!? (skip check)] new self::B::•().{self::B::instanceMethod}(){() → void};
self::foo();
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/async_await.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/async_await.dart.expect
index d1f3c4e..fc5a260 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/async_await.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/async_await.dart.expect
@@ -1,20 +1,19 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
import "dart:async" as asy;
-import "dart:_internal" as _in;
class A extends core::Object {
- synthetic constructor •() → self::A*
+ synthetic constructor •() → self::A
: super core::Object::•()
;
-[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method bar(dynamic x) → asy::Future<dynamic>* /* originally async */ {
- final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method bar(dynamic x) → asy::Future<dynamic> /* originally async */ {
+ final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
- (dynamic) →* dynamic :async_op_then;
- (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
- core::int* :await_jump_var = 0;
+ FutureOr<dynamic>? :return_value;
+ (dynamic) → dynamic :async_op_then;
+ (core::Object, core::StackTrace) → dynamic :async_op_error;
+ core::int :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -26,30 +25,30 @@
asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
- on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
+ on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
}
:async_op_then = asy::_asyncThenWrapperHelper(:async_op);
:async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
- :async_op(){() →* dynamic};
+ :async_op(){() → dynamic};
:is_sync = true;
return :async_future;
}
}
class B extends core::Object {
- synthetic constructor •() → self::B*
+ synthetic constructor •() → self::B
: super core::Object::•()
;
}
static method foo() → dynamic
return new self::A::•();
-static method baz() → asy::Future<dynamic>* /* originally async */ {
- final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
+static method baz() → asy::Future<dynamic> /* originally async */ {
+ final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
- (dynamic) →* dynamic :async_op_then;
- (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
- core::int* :await_jump_var = 0;
+ FutureOr<dynamic>? :return_value;
+ (dynamic) → dynamic :async_op_then;
+ (core::Object, core::StackTrace) → dynamic :async_op_error;
+ core::int :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -61,22 +60,22 @@
asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
- on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
+ on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
}
:async_op_then = asy::_asyncThenWrapperHelper(:async_op);
:async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
- :async_op(){() →* dynamic};
+ :async_op(){() → dynamic};
:is_sync = true;
return :async_future;
}
static method main() → dynamic /* originally async */ {
- final asy::_Future<dynamic>* :async_future = new asy::_Future::•<dynamic>();
+ final asy::_Future<dynamic> :async_future = new asy::_Future::•<dynamic>();
core::bool* :is_sync = false;
- FutureOr<dynamic>* :return_value;
- (dynamic) →* dynamic :async_op_then;
- (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
- core::int* :await_jump_var = 0;
+ FutureOr<dynamic>? :return_value;
+ (dynamic) → dynamic :async_op_then;
+ (core::Object, core::StackTrace) → dynamic :async_op_error;
+ core::int :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
dynamic :async_temporary_0;
@@ -86,18 +85,18 @@
{
:async_temporary_0 = [@vm.inferred-type.metadata=#lib::A] self::foo();
[yield] let dynamic #t1 = asy::_awaitHelper([@vm.inferred-type.metadata=dart.async::_Future<dynamic>] self::baz(), :async_op_then, :async_op_error, :async_op) in null;
- [yield] let dynamic #t2 = asy::_awaitHelper([@vm.direct-call.metadata=#lib::A.bar??] [@vm.inferred-type.metadata=dart.async::_Future<dynamic> (receiver not int)] _in::unsafeCast<dynamic>(:async_temporary_0){dynamic}.bar(:result), :async_op_then, :async_op_error, :async_op) in null;
+ [yield] let dynamic #t2 = asy::_awaitHelper([@vm.direct-call.metadata=#lib::A.bar??] [@vm.inferred-type.metadata=dart.async::_Future<dynamic> (receiver not int)] :async_temporary_0{dynamic}.bar(:result), :async_op_then, :async_op_error, :async_op) in null;
:result;
}
asy::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
return;
}
- on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
+ on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
asy::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
}
:async_op_then = asy::_asyncThenWrapperHelper(:async_op);
:async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
- :async_op(){() →* dynamic};
+ :async_op(){() → dynamic};
:is_sync = true;
return :async_future;
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/bench_is_prime.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/bench_is_prime.dart.expect
index dc738d5..0a0c97a 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/bench_is_prime.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/bench_is_prime.dart.expect
@@ -1,43 +1,43 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
import "dart:_internal" as _in;
-[@vm.unboxing-info.metadata=(i)->b]static method isPrime([@vm.inferred-type.metadata=int] dynamic n) → core::bool* {
- if(_in::unsafeCast<core::bool*>([@vm.direct-call.metadata=dart.core::_IntegerImplementation.<] [@vm.inferred-type.metadata=dart.core::bool] n{dynamic}.<(2)))
+[@vm.unboxing-info.metadata=(i)->b]static method isPrime([@vm.inferred-type.metadata=int] dynamic n) → core::bool {
+ if(_in::unsafeCast<core::bool>([@vm.direct-call.metadata=dart.core::_IntegerImplementation.<] [@vm.inferred-type.metadata=dart.core::bool] n{dynamic}.<(2)))
return false;
- for (core::int* i = 2; [@vm.direct-call.metadata=dart.core::_IntegerImplementation.<=] [@vm.inferred-type.metadata=dart.core::bool (skip check)] [@vm.direct-call.metadata=dart.core::_IntegerImplementation.*] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::*}(i){(core::num*) →* core::int*}.{core::num::<=}(_in::unsafeCast<core::num*>(n)){(core::num*) →* core::bool*}; i = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(1){(core::num*) →* core::int*}) {
- if([@vm.direct-call.metadata=dart.core::_IntegerImplementation.==] [@vm.inferred-type.metadata=dart.core::bool (skip check)] [@vm.direct-call.metadata=dart.core::_IntegerImplementation.%] [@vm.inferred-type.metadata=int] n{dynamic}.%(i) =={core::Object::==}{(core::Object*) →* core::bool*} 0)
+ for (core::int i = 2; [@vm.direct-call.metadata=dart.core::_IntegerImplementation.<=] [@vm.inferred-type.metadata=dart.core::bool (skip check)] [@vm.direct-call.metadata=dart.core::_IntegerImplementation.*] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::*}(i){(core::num) → core::int}.{core::num::<=}(_in::unsafeCast<core::num>(n)){(core::num) → core::bool}; i = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(1){(core::num) → core::int}) {
+ if([@vm.direct-call.metadata=dart.core::_IntegerImplementation.==] [@vm.inferred-type.metadata=dart.core::bool (skip check)] [@vm.direct-call.metadata=dart.core::_IntegerImplementation.%] [@vm.inferred-type.metadata=int] n{dynamic}.%(i) =={core::Object::==}{(core::Object) → core::bool} 0)
return false;
}
return true;
}
-static method nThPrimeNumber() → core::int* {
- core::int* counter = 0;
- for (core::int* i = 1; ; i = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+??] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(1){(core::num*) →* core::int*}) {
+static method nThPrimeNumber() → core::int {
+ core::int counter = 0;
+ for (core::int i = 1; ; i = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+??] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(1){(core::num) → core::int}) {
if([@vm.inferred-type.metadata=dart.core::bool] self::isPrime(i))
- counter = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+??] [@vm.inferred-type.metadata=int (skip check)] counter.{core::num::+}(1){(core::num*) →* core::int*};
- if([@vm.inferred-type.metadata=dart.core::bool] counter =={core::num::==}{(core::Object*) →* core::bool*} (#C1)) {
+ counter = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+??] [@vm.inferred-type.metadata=int (skip check)] counter.{core::num::+}(1){(core::num) → core::int};
+ if([@vm.inferred-type.metadata=dart.core::bool] counter =={core::num::==}{(core::Object) → core::bool} (#C1)) {
return i;
}
}
}
static method run() → void {
- core::int* e = 611953;
- core::int* p = [@vm.inferred-type.metadata=int?] self::nThPrimeNumber();
- if(!([@vm.inferred-type.metadata=dart.core::bool] p =={core::num::==}{(core::Object*) →* core::bool*} e)) {
+ core::int e = 611953;
+ core::int p = [@vm.inferred-type.metadata=int?] self::nThPrimeNumber();
+ if(!([@vm.inferred-type.metadata=dart.core::bool] p =={core::num::==}{(core::Object) → core::bool} e)) {
throw core::Exception::•("Unexpected result: ${p} != ${e}");
}
}
-static method main(core::List<core::String*>* args) → dynamic {
- core::Stopwatch* timer = let final core::Stopwatch* #t1 = new core::Stopwatch::•() in block {
- [@vm.direct-call.metadata=dart.core::Stopwatch.start] [@vm.inferred-type.metadata=!? (skip check)] #t1.{core::Stopwatch::start}(){() →* void};
+static method main(core::List<core::String> args) → dynamic {
+ core::Stopwatch timer = let final core::Stopwatch #t1 = new core::Stopwatch::•() in block {
+ [@vm.direct-call.metadata=dart.core::Stopwatch.start] [@vm.inferred-type.metadata=!? (skip check)] #t1.{core::Stopwatch::start}(){() → void};
} =>#t1;
- for (core::int* i = 0; [@vm.direct-call.metadata=dart.core::_IntegerImplementation.<] [@vm.inferred-type.metadata=dart.core::bool (skip check)] i.{core::num::<}(100){(core::num*) →* core::bool*}; i = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(1){(core::num*) →* core::int*}) {
+ for (core::int i = 0; [@vm.direct-call.metadata=dart.core::_IntegerImplementation.<] [@vm.inferred-type.metadata=dart.core::bool (skip check)] i.{core::num::<}(100){(core::num) → core::bool}; i = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(1){(core::num) → core::int}) {
self::run();
}
- [@vm.direct-call.metadata=dart.core::Stopwatch.stop] [@vm.inferred-type.metadata=!? (skip check)] timer.{core::Stopwatch::stop}(){() →* void};
- core::print("Elapsed ${[@vm.direct-call.metadata=dart.core::Stopwatch.elapsedMilliseconds] timer.{core::Stopwatch::elapsedMilliseconds}{core::int*}}ms");
+ [@vm.direct-call.metadata=dart.core::Stopwatch.stop] [@vm.inferred-type.metadata=!? (skip check)] timer.{core::Stopwatch::stop}(){() → void};
+ core::print("Elapsed ${[@vm.direct-call.metadata=dart.core::Stopwatch.elapsedMilliseconds] timer.{core::Stopwatch::elapsedMilliseconds}{core::int}}ms");
}
constants {
#C1 = 50000
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/bench_vector.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/bench_vector.dart.expect
index 92746ce..370e042 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/bench_vector.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/bench_vector.dart.expect
@@ -1,4 +1,4 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
import "dart:typed_data" as typ;
@@ -6,35 +6,38 @@
import "dart:typed_data";
class _Vector extends core::Object {
-[@vm.inferred-type.metadata=dart.core::_Smi (value: 0)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] [@vm.unboxing-info.metadata=()->i] final field core::int* _offset;
-[@vm.inferred-type.metadata=dart.core::_Smi (value: 10)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i] final field core::int* _length;
-[@vm.inferred-type.metadata=dart.typed_data::_Float64List] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3] final field core::List<core::double*>* _elements;
- constructor •() → self::_Vector*
+[@vm.inferred-type.metadata=dart.core::_Smi (value: 0)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] [@vm.unboxing-info.metadata=()->i] final field core::int _offset;
+[@vm.inferred-type.metadata=dart.core::_Smi (value: 10)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i] final field core::int _length;
+[@vm.inferred-type.metadata=dart.typed_data::_Float64List] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3] final field core::List<core::double> _elements;
+ constructor •() → self::_Vector
: self::_Vector::_offset = 0, self::_Vector::_length = #C1, self::_Vector::_elements = [@vm.inferred-type.metadata=dart.typed_data::_Float64List] typ::Float64List::•(#C1), super core::Object::•()
;
-[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasTearOffUses:false,methodOrSetterSelectorId:4] [@vm.unboxing-info.metadata=(b)->d] operator []([@vm.inferred-type.metadata=!] core::int* i) → core::double*
- return [@vm.direct-call.metadata=dart.typed_data::_Float64List.[]] [@vm.inferred-type.metadata=dart.core::_Double (skip check)] [@vm.direct-call.metadata=#lib::_Vector._elements] [@vm.inferred-type.metadata=dart.typed_data::_Float64List] this.{self::_Vector::_elements}{core::List<core::double*>*}.{core::List::[]}([@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}([@vm.direct-call.metadata=#lib::_Vector._offset] [@vm.inferred-type.metadata=dart.core::_Smi (value: 0)] this.{self::_Vector::_offset}{core::int*}){(core::num*) →* core::int*}){(core::int*) →* core::double*};
-[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5] operator []=([@vm.inferred-type.metadata=dart.core::_OneByteString] core::int* i, core::double* value) → void {
- let dynamic #t1 = [@vm.direct-call.metadata=#lib::_Vector._elements] [@vm.inferred-type.metadata=dart.typed_data::_Float64List] this.{self::_Vector::_elements}{core::List<core::double*>*} in let dynamic #t2 = [@vm.direct-call.metadata=#lib::_Vector._offset] [@vm.inferred-type.metadata=dart.core::_Smi (value: 0)] this.{self::_Vector::_offset}{core::int*} in throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasTearOffUses:false,methodOrSetterSelectorId:4] [@vm.unboxing-info.metadata=(b)->d] operator []([@vm.inferred-type.metadata=!] core::int i) → core::double
+ return [@vm.direct-call.metadata=dart.typed_data::_Float64List.[]] [@vm.inferred-type.metadata=dart.core::_Double (skip check)] [@vm.direct-call.metadata=#lib::_Vector._elements] [@vm.inferred-type.metadata=dart.typed_data::_Float64List] this.{self::_Vector::_elements}{core::List<core::double>}.{core::List::[]}([@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}([@vm.direct-call.metadata=#lib::_Vector._offset] [@vm.inferred-type.metadata=dart.core::_Smi (value: 0)] this.{self::_Vector::_offset}{core::int}){(core::num) → core::int}){(core::int) → core::double};
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5] operator []=([@vm.inferred-type.metadata=dart.core::_OneByteString] core::int i, core::double value) → void {
+ block {
+ [@vm.direct-call.metadata=#lib::_Vector._elements] [@vm.inferred-type.metadata=dart.typed_data::_Float64List] this.{self::_Vector::_elements}{core::List<core::double>};
+ [@vm.direct-call.metadata=#lib::_Vector._offset] [@vm.inferred-type.metadata=dart.core::_Smi (value: 0)] this.{self::_Vector::_offset}{core::int};
+ } =>throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
}
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6] [@vm.unboxing-info.metadata=(b)->d] operator *([@vm.inferred-type.metadata=#lib::_Vector?] self::_Vector* a) → core::double* {
- core::double* result = 0.0;
- for (core::int* i = 0; [@vm.direct-call.metadata=dart.core::_IntegerImplementation.<] [@vm.inferred-type.metadata=dart.core::bool (skip check)] i.{core::num::<}([@vm.direct-call.metadata=#lib::_Vector._length] [@vm.inferred-type.metadata=dart.core::_Smi (value: 10)] this.{self::_Vector::_length}{core::int*}){(core::num*) →* core::bool*}; i = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(1){(core::num*) →* core::int*})
- result = [@vm.direct-call.metadata=dart.core::_Double.+??] [@vm.inferred-type.metadata=dart.core::_Double (skip check)] result.{core::double::+}([@vm.direct-call.metadata=dart.core::_Double.*] [@vm.inferred-type.metadata=dart.core::_Double (skip check)] [@vm.direct-call.metadata=#lib::_Vector.[]] [@vm.inferred-type.metadata=dart.core::_Double (skip check)] this.{self::_Vector::[]}(i){(core::int*) →* core::double*}.{core::double::*}([@vm.direct-call.metadata=#lib::_Vector.[]??] [@vm.inferred-type.metadata=dart.core::_Double (skip check)] a.{self::_Vector::[]}(i){(core::int*) →* core::double*}){(core::num*) →* core::double*}){(core::num*) →* core::double*};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6] [@vm.unboxing-info.metadata=(b)->d] operator *([@vm.inferred-type.metadata=#lib::_Vector?] self::_Vector a) → core::double {
+ core::double result = 0.0;
+ for (core::int i = 0; [@vm.direct-call.metadata=dart.core::_IntegerImplementation.<] [@vm.inferred-type.metadata=dart.core::bool (skip check)] i.{core::num::<}([@vm.direct-call.metadata=#lib::_Vector._length] [@vm.inferred-type.metadata=dart.core::_Smi (value: 10)] this.{self::_Vector::_length}{core::int}){(core::num) → core::bool}; i = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(1){(core::num) → core::int})
+ result = [@vm.direct-call.metadata=dart.core::_Double.+??] [@vm.inferred-type.metadata=dart.core::_Double (skip check)] result.{core::double::+}([@vm.direct-call.metadata=dart.core::_Double.*] [@vm.inferred-type.metadata=dart.core::_Double (skip check)] [@vm.direct-call.metadata=#lib::_Vector.[]] [@vm.inferred-type.metadata=dart.core::_Double (skip check)] this.{self::_Vector::[]}(i){(core::int) → core::double}.{core::double::*}([@vm.direct-call.metadata=#lib::_Vector.[]??] [@vm.inferred-type.metadata=dart.core::_Double (skip check)] a.{self::_Vector::[]}(i){(core::int) → core::double}){(core::num) → core::double}){(core::num) → core::double};
return result;
}
}
-[@vm.inferred-type.metadata=#lib::_Vector?]static field self::_Vector* v = new self::_Vector::•();
-[@vm.inferred-type.metadata=dart.core::_Double?]static field core::double* x = 0.0;
-static method main(core::List<core::String*>* args) → dynamic {
- core::Stopwatch* timer = let final core::Stopwatch* #t3 = new core::Stopwatch::•() in block {
- [@vm.direct-call.metadata=dart.core::Stopwatch.start] [@vm.inferred-type.metadata=!? (skip check)] #t3.{core::Stopwatch::start}(){() →* void};
- } =>#t3;
- for (core::int* i = 0; [@vm.direct-call.metadata=dart.core::_IntegerImplementation.<] [@vm.inferred-type.metadata=dart.core::bool (skip check)] i.{core::num::<}(100000000){(core::num*) →* core::bool*}; i = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(1){(core::num*) →* core::int*}) {
- self::x = [@vm.direct-call.metadata=dart.core::_Double.+??] [@vm.inferred-type.metadata=dart.core::_Double (skip check)] [@vm.inferred-type.metadata=dart.core::_Double?] self::x.{core::double::+}([@vm.direct-call.metadata=#lib::_Vector.*??] [@vm.inferred-type.metadata=dart.core::_Double (skip check)] [@vm.inferred-type.metadata=#lib::_Vector?] self::v.{self::_Vector::*}([@vm.inferred-type.metadata=#lib::_Vector?] self::v){(self::_Vector*) →* core::double*}){(core::num*) →* core::double*};
+[@vm.inferred-type.metadata=#lib::_Vector?]static field self::_Vector v = new self::_Vector::•();
+[@vm.inferred-type.metadata=dart.core::_Double?]static field core::double x = 0.0;
+static method main(core::List<core::String> args) → dynamic {
+ core::Stopwatch timer = let final core::Stopwatch #t1 = new core::Stopwatch::•() in block {
+ [@vm.direct-call.metadata=dart.core::Stopwatch.start] [@vm.inferred-type.metadata=!? (skip check)] #t1.{core::Stopwatch::start}(){() → void};
+ } =>#t1;
+ for (core::int i = 0; [@vm.direct-call.metadata=dart.core::_IntegerImplementation.<] [@vm.inferred-type.metadata=dart.core::bool (skip check)] i.{core::num::<}(100000000){(core::num) → core::bool}; i = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(1){(core::num) → core::int}) {
+ self::x = [@vm.direct-call.metadata=dart.core::_Double.+??] [@vm.inferred-type.metadata=dart.core::_Double (skip check)] [@vm.inferred-type.metadata=dart.core::_Double?] self::x.{core::double::+}([@vm.direct-call.metadata=#lib::_Vector.*??] [@vm.inferred-type.metadata=dart.core::_Double (skip check)] [@vm.inferred-type.metadata=#lib::_Vector?] self::v.{self::_Vector::*}([@vm.inferred-type.metadata=#lib::_Vector?] self::v){(self::_Vector) → core::double}){(core::num) → core::double};
}
- [@vm.direct-call.metadata=dart.core::Stopwatch.stop] [@vm.inferred-type.metadata=!? (skip check)] timer.{core::Stopwatch::stop}(){() →* void};
- core::print("Elapsed ${[@vm.direct-call.metadata=dart.core::Stopwatch.elapsedMilliseconds] timer.{core::Stopwatch::elapsedMilliseconds}{core::int*}}ms, result ${self::x}");
+ [@vm.direct-call.metadata=dart.core::Stopwatch.stop] [@vm.inferred-type.metadata=!? (skip check)] timer.{core::Stopwatch::stop}(){() → void};
+ core::print("Elapsed ${[@vm.direct-call.metadata=dart.core::Stopwatch.elapsedMilliseconds] timer.{core::Stopwatch::elapsedMilliseconds}{core::int}}ms, result ${self::x}");
}
constants {
#C1 = 10
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/class_generics_basic.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/class_generics_basic.dart.expect
index 00cfa5c..c42f78c 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/class_generics_basic.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/class_generics_basic.dart.expect
@@ -1,76 +1,76 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
-class C<T extends core::Object* = dynamic> extends core::Object {
- synthetic constructor •() → self::C<self::C::T*>*
+class C<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::C<self::C::T%>
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method foo() → dynamic
- return new self::D::•<self::C::T*>();
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] method id1([@vm.inferred-type.metadata=#lib::Y (skip check)] generic-covariant-impl self::C::T* x) → dynamic
+ return new self::D::•<self::C::T%>();
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] method id1([@vm.inferred-type.metadata=#lib::Y (skip check)] generic-covariant-impl self::C::T% x) → dynamic
return x;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] method id2([@vm.inferred-type.metadata=#lib::Z] generic-covariant-impl self::C::T* x) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] method id2([@vm.inferred-type.metadata=#lib::Z] generic-covariant-impl self::C::T% x) → dynamic
return x;
}
-class D<T extends core::Object* = dynamic> extends core::Object {
- synthetic constructor •() → self::D<self::D::T*>*
+class D<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::D<self::D::T%>
: super core::Object::•()
;
}
-class E<S extends core::Object* = dynamic, T extends core::Object* = dynamic> extends self::C<self::E::T*> {
- synthetic constructor •() → self::E<self::E::S*, self::E::T*>*
+class E<S extends core::Object? = dynamic, T extends core::Object? = dynamic> extends self::C<self::E::T%> {
+ synthetic constructor •() → self::E<self::E::S%, self::E::T%>
: super self::C::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method foo() → dynamic
- return [@vm.inferred-type.metadata=#lib::D<dart.core::String*>] super.{self::C::foo}();
+ return [@vm.inferred-type.metadata=#lib::D<dart.core::String>] super.{self::C::foo}();
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] method bar() → dynamic
- return new self::D::•<self::E::S*>();
+ return new self::D::•<self::E::S%>();
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10] method baz() → dynamic
- return new self::D::•<self::E::T*>();
+ return new self::D::•<self::E::T%>();
}
abstract class X extends core::Object {
- synthetic constructor •() → self::X*
+ synthetic constructor •() → self::X
: super core::Object::•()
;
}
class Y extends self::X {
- synthetic constructor •() → self::Y*
+ synthetic constructor •() → self::Y
: super self::X::•()
;
}
class Z extends self::X {
- synthetic constructor •() → self::Z*
+ synthetic constructor •() → self::Z
: super self::X::•()
;
}
-abstract class I<T extends core::Object* = dynamic> extends core::Object {
+abstract class I<T extends core::Object? = dynamic> extends core::Object {
}
-abstract class J extends self::I<core::int*> {
+abstract class J extends self::I<core::int> {
}
-class K<T extends core::Object* = dynamic> extends core::Object {
- synthetic constructor •() → self::K<self::K::T*>*
+class K<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::K<self::K::T%>
: super core::Object::•()
;
}
-class C2<T extends core::Object* = dynamic> extends core::Object {
- synthetic constructor •() → self::C2<self::C2::T*>*
+class C2<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::C2<self::C2::T%>
: super core::Object::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] [@vm.unboxing-info.metadata=(d)->d] method id3([@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.0)] generic-covariant-impl core::Comparable<self::C2::T*>* x) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] [@vm.unboxing-info.metadata=(d)->d] method id3([@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.0)] generic-covariant-impl core::Comparable<self::C2::T%> x) → dynamic
return x;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14] method id4([@vm.inferred-type.metadata=#lib::K<#lib::J*> (skip check)] generic-covariant-impl self::K<self::I<self::C2::T*>*>* x) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14] method id4([@vm.inferred-type.metadata=#lib::K<#lib::J> (skip check)] generic-covariant-impl self::K<self::I<self::C2::T%>> x) → dynamic
return x;
}
static method main() → dynamic {
- core::print([@vm.direct-call.metadata=#lib::C.foo] [@vm.inferred-type.metadata=#lib::D<dart.core::int*> (skip check)] new self::C::•<core::int*>().{self::C::foo}(){() →* dynamic});
- core::print([@vm.direct-call.metadata=#lib::E.foo] [@vm.inferred-type.metadata=#lib::D<dart.core::String*> (skip check)] new self::E::•<core::int*, core::String*>().{self::E::foo}(){() →* dynamic});
- core::print([@vm.direct-call.metadata=#lib::E.bar] [@vm.inferred-type.metadata=#lib::D<dart.core::int*> (skip check)] new self::E::•<core::int*, core::String*>().{self::E::bar}(){() →* dynamic});
- core::print([@vm.direct-call.metadata=#lib::E.baz] [@vm.inferred-type.metadata=#lib::D<dart.core::String*> (skip check)] new self::E::•<core::int*, core::String*>().{self::E::baz}(){() →* dynamic});
- self::C<self::X*>* c = new self::C::•<self::Y*>();
- [@vm.call-site-attributes.metadata=receiverType:#lib::C<#lib::X*>*] [@vm.direct-call.metadata=#lib::C.id1] [@vm.inferred-type.metadata=!? (skip check)] c.{self::C::id1}(new self::Y::•()){(self::X*) →* dynamic};
- [@vm.call-site-attributes.metadata=receiverType:#lib::C<#lib::X*>*] [@vm.direct-call.metadata=#lib::C.id2] c.{self::C::id2}(new self::Z::•()){(self::X*) →* dynamic};
- self::C2<core::num*>* c2 = new self::C2::•<core::num*>();
- [@vm.call-site-attributes.metadata=receiverType:#lib::C2<dart.core::num*>*] [@vm.direct-call.metadata=#lib::C2.id3] [@vm.inferred-type.metadata=!? (skip check)] c2.{self::C2::id3}(3.0){(core::Comparable<core::num*>*) →* dynamic};
- [@vm.call-site-attributes.metadata=receiverType:#lib::C2<dart.core::num*>*] [@vm.direct-call.metadata=#lib::C2.id4] [@vm.inferred-type.metadata=!? (skip check)] c2.{self::C2::id4}(new self::K::•<self::J*>()){(self::K<self::I<core::num*>*>*) →* dynamic};
+ core::print([@vm.direct-call.metadata=#lib::C.foo] [@vm.inferred-type.metadata=#lib::D<dart.core::int> (skip check)] new self::C::•<core::int>().{self::C::foo}(){() → dynamic});
+ core::print([@vm.direct-call.metadata=#lib::E.foo] [@vm.inferred-type.metadata=#lib::D<dart.core::String> (skip check)] new self::E::•<core::int, core::String>().{self::E::foo}(){() → dynamic});
+ core::print([@vm.direct-call.metadata=#lib::E.bar] [@vm.inferred-type.metadata=#lib::D<dart.core::int> (skip check)] new self::E::•<core::int, core::String>().{self::E::bar}(){() → dynamic});
+ core::print([@vm.direct-call.metadata=#lib::E.baz] [@vm.inferred-type.metadata=#lib::D<dart.core::String> (skip check)] new self::E::•<core::int, core::String>().{self::E::baz}(){() → dynamic});
+ self::C<self::X> c = new self::C::•<self::Y>();
+ [@vm.call-site-attributes.metadata=receiverType:#lib::C<#lib::X>] [@vm.direct-call.metadata=#lib::C.id1] [@vm.inferred-type.metadata=!? (skip check)] c.{self::C::id1}(new self::Y::•()){(self::X) → dynamic};
+ [@vm.call-site-attributes.metadata=receiverType:#lib::C<#lib::X>] [@vm.direct-call.metadata=#lib::C.id2] c.{self::C::id2}(new self::Z::•()){(self::X) → dynamic};
+ self::C2<core::num> c2 = new self::C2::•<core::num>();
+ [@vm.call-site-attributes.metadata=receiverType:#lib::C2<dart.core::num>] [@vm.direct-call.metadata=#lib::C2.id3] [@vm.inferred-type.metadata=!? (skip check)] c2.{self::C2::id3}(3.0){(core::Comparable<core::num>) → dynamic};
+ [@vm.call-site-attributes.metadata=receiverType:#lib::C2<dart.core::num>] [@vm.direct-call.metadata=#lib::C2.id4] [@vm.inferred-type.metadata=!? (skip check)] c2.{self::C2::id4}(new self::K::•<self::J>()){(self::K<self::I<core::num>>) → dynamic};
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/class_generics_case1.dart b/pkg/vm/testcases/transformations/type_flow/transformer/class_generics_case1.dart
index c211e10..b331cb8 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/class_generics_case1.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/class_generics_case1.dart
@@ -7,9 +7,9 @@
class Element {}
class InheritedElement extends Element {
- final Map<Element, Object> _dependents = <Element, Object>{};
+ final Map<Element, Object?> _dependents = <Element, Object?>{};
- void setDependencies(Element dependent, Object value) {
+ void setDependencies(Element dependent, Object? value) {
_dependents[dependent] = value;
}
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/class_generics_case1.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/class_generics_case1.dart.expect
index ca4d73c..4a919d4 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/class_generics_case1.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/class_generics_case1.dart.expect
@@ -1,25 +1,25 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
import "dart:collection";
class Element extends core::Object {
- synthetic constructor •() → self::Element*
+ synthetic constructor •() → self::Element
: super core::Object::•()
;
}
class InheritedElement extends self::Element {
-[@vm.inferred-type.metadata=dart.collection::_InternalLinkedHashMap<#lib::Element*, dart.core::Object*>] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] final field core::Map<self::Element*, core::Object*>* _dependents;
- synthetic constructor •() → self::InheritedElement*
- : self::InheritedElement::_dependents = <self::Element*, core::Object*>{}, super self::Element::•()
+[@vm.inferred-type.metadata=dart.collection::_InternalLinkedHashMap<#lib::Element, dart.core::Object?>] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] final field core::Map<self::Element, core::Object?> _dependents;
+ synthetic constructor •() → self::InheritedElement
+ : self::InheritedElement::_dependents = <self::Element, core::Object?>{}, super self::Element::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:2,getterSelectorId:3] method setDependencies([@vm.inferred-type.metadata=!] self::Element* dependent, [@vm.inferred-type.metadata=dart.core::_Smi?] core::Object* value) → void {
- [@vm.call-site-attributes.metadata=receiverType:dart.core::Map<#lib::Element*, dart.core::Object*>*] [@vm.direct-call.metadata=dart.collection::__InternalLinkedHashMap&_HashVMBase&MapMixin&_LinkedHashMapMixin.[]=] [@vm.inferred-type.metadata=!? (skip check)] [@vm.direct-call.metadata=#lib::InheritedElement._dependents] [@vm.inferred-type.metadata=dart.collection::_InternalLinkedHashMap<#lib::Element*, dart.core::Object*>] this.{self::InheritedElement::_dependents}{core::Map<self::Element*, core::Object*>*}.{core::Map::[]=}(dependent, value){(self::Element*, core::Object*) →* void};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:2,getterSelectorId:3] method setDependencies([@vm.inferred-type.metadata=!] self::Element dependent, [@vm.inferred-type.metadata=dart.core::_Smi?] core::Object? value) → void {
+ [@vm.call-site-attributes.metadata=receiverType:dart.core::Map<#lib::Element, dart.core::Object?>] [@vm.direct-call.metadata=dart.collection::__InternalLinkedHashMap&_HashVMBase&MapMixin&_LinkedHashMapMixin.[]=] [@vm.inferred-type.metadata=!? (skip check)] [@vm.direct-call.metadata=#lib::InheritedElement._dependents] [@vm.inferred-type.metadata=dart.collection::_InternalLinkedHashMap<#lib::Element, dart.core::Object?>] this.{self::InheritedElement::_dependents}{core::Map<self::Element, core::Object?>}.{core::Map::[]=}(dependent, value){(self::Element, core::Object?) → void};
}
}
static method main() → dynamic {
- self::InheritedElement* ie = new self::InheritedElement::•();
- [@vm.direct-call.metadata=#lib::InheritedElement.setDependencies] [@vm.inferred-type.metadata=!? (skip check)] ie.{self::InheritedElement::setDependencies}(ie, 0){(self::Element*, core::Object*) →* void};
- [@vm.direct-call.metadata=#lib::InheritedElement.setDependencies] [@vm.inferred-type.metadata=!? (skip check)] ie.{self::InheritedElement::setDependencies}(new self::Element::•(), null){(self::Element*, core::Object*) →* void};
+ self::InheritedElement ie = new self::InheritedElement::•();
+ [@vm.direct-call.metadata=#lib::InheritedElement.setDependencies] [@vm.inferred-type.metadata=!? (skip check)] ie.{self::InheritedElement::setDependencies}(ie, 0){(self::Element, core::Object?) → void};
+ [@vm.direct-call.metadata=#lib::InheritedElement.setDependencies] [@vm.inferred-type.metadata=!? (skip check)] ie.{self::InheritedElement::setDependencies}(new self::Element::•(), null){(self::Element, core::Object?) → void};
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/const_prop.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/const_prop.dart.expect
index 1a8dce9..685989f 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/const_prop.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/const_prop.dart.expect
@@ -1,21 +1,21 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
class A extends core::Object {
- synthetic constructor •() → self::A*
+ synthetic constructor •() → self::A
: super core::Object::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] get foo() → core::String*
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] get foo() → core::String
return "foo";
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:2,getterSelectorId:3] method getBar() → core::String*
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:2,getterSelectorId:3] method getBar() → core::String
return "bar";
}
class B extends core::Object implements core::Enum /*isEnum*/ {
-[@vm.inferred-type.metadata=dart.core::_Smi (value: 1)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:4] [@vm.unboxing-info.metadata=()->i] final field core::int* index;
-[@vm.inferred-type.metadata=dart.core::_OneByteString (value: "B.b2")] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:5] final field core::String* _name;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7] method toString() → core::String*
- return [@vm.direct-call.metadata=#lib::B._name] [@vm.inferred-type.metadata=dart.core::_OneByteString (value: "B.b2")] this.{self::B::_name}{core::String*};
+[@vm.inferred-type.metadata=dart.core::_Smi (value: 1)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:4] [@vm.unboxing-info.metadata=()->i] final field core::int index;
+[@vm.inferred-type.metadata=dart.core::_OneByteString (value: "B.b2")] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:5] final field core::String _name;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7] method toString() → core::String
+ return [@vm.direct-call.metadata=#lib::B._name] [@vm.inferred-type.metadata=dart.core::_OneByteString (value: "B.b2")] this.{self::B::_name}{core::String};
}
static method test0() → void {
core::print(#C1);
@@ -32,9 +32,9 @@
core::print(#C4);
core::print([@vm.inferred-type.metadata=dart.core::_Double (value: 100.0)] self::getD);
}
-static method testStrings([@vm.inferred-type.metadata=#lib::A] self::A* a0) → void {
- core::print([@vm.direct-call.metadata=#lib::A.foo] [@vm.inferred-type.metadata=dart.core::_OneByteString (value: "foo")] a0.{self::A::foo}{core::String*});
- core::print([@vm.direct-call.metadata=#lib::A.getBar] [@vm.inferred-type.metadata=dart.core::_OneByteString (skip check) (value: "bar")] a0.{self::A::getBar}(){() →* core::String*});
+static method testStrings([@vm.inferred-type.metadata=#lib::A] self::A a0) → void {
+ core::print([@vm.direct-call.metadata=#lib::A.foo] [@vm.inferred-type.metadata=dart.core::_OneByteString (value: "foo")] a0.{self::A::foo}{core::String});
+ core::print([@vm.direct-call.metadata=#lib::A.getBar] [@vm.inferred-type.metadata=dart.core::_OneByteString (skip check) (value: "bar")] a0.{self::A::getBar}(){() → core::String});
core::print(#C5);
}
static method testPassEnum() → void {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart b/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart
index 515824c..4025830 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart
@@ -28,7 +28,7 @@
aa.foo();
}
-void callerA3({A aa}) {
+void callerA3({required A aa}) {
aa.foo();
}
@@ -44,7 +44,7 @@
x.toString();
}
-A dd;
+late A dd;
E ee = new E();
main(List<String> args) {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart.expect
index ebf2078..67ffa52 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart.expect
@@ -1,65 +1,65 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
abstract class A extends core::Object {
- synthetic constructor •() → self::A*
+ synthetic constructor •() → self::A
: super core::Object::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i] abstract method foo() → core::int*;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i] abstract method foo() → core::int;
}
class B extends self::A {
- synthetic constructor •() → self::B*
+ synthetic constructor •() → self::B
: super self::A::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i] method foo() → core::int*
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i] method foo() → core::int
return 1;
}
class C extends core::Object implements self::A {
- synthetic constructor •() → self::C*
+ synthetic constructor •() → self::C
: super core::Object::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i] method foo() → core::int*
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i] method foo() → core::int
return 2;
}
class D extends self::C {
- synthetic constructor •() → self::D*
+ synthetic constructor •() → self::D
: super self::C::•()
;
}
class E extends core::Object {
- synthetic constructor •() → self::E*
+ synthetic constructor •() → self::E
: super core::Object::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] method toString() → core::String*
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] method toString() → core::String
return "D";
}
-[@vm.inferred-type.metadata=#lib::D?]static field self::A* dd;
-[@vm.inferred-type.metadata=#lib::E?]static field self::E* ee = new self::E::•();
-static method callerA1([@vm.inferred-type.metadata=!] self::A* aa) → void {
- [@vm.inferred-type.metadata=!? (skip check)] aa.{self::A::foo}(){() →* core::int*};
+[@vm.inferred-type.metadata=#lib::D]late static field self::A dd;
+[@vm.inferred-type.metadata=#lib::E?]static field self::E ee = new self::E::•();
+static method callerA1([@vm.inferred-type.metadata=!] self::A aa) → void {
+ [@vm.inferred-type.metadata=!? (skip check)] aa.{self::A::foo}(){() → core::int};
}
-static method callerA2([@vm.inferred-type.metadata=#lib::B] self::A* aa) → void {
- [@vm.direct-call.metadata=#lib::B.foo] [@vm.inferred-type.metadata=!? (skip check)] aa.{self::A::foo}(){() →* core::int*};
+static method callerA2([@vm.inferred-type.metadata=#lib::B] self::A aa) → void {
+ [@vm.direct-call.metadata=#lib::B.foo] [@vm.inferred-type.metadata=!? (skip check)] aa.{self::A::foo}(){() → core::int};
}
-static method callerA3([@vm.inferred-type.metadata=#lib::C] self::A* aa) → void {
- [@vm.direct-call.metadata=#lib::C.foo] [@vm.inferred-type.metadata=!? (skip check)] aa.{self::A::foo}(){() →* core::int*};
+static method callerA3([@vm.inferred-type.metadata=#lib::C] self::A aa) → void {
+ [@vm.direct-call.metadata=#lib::C.foo] [@vm.inferred-type.metadata=!? (skip check)] aa.{self::A::foo}(){() → core::int};
}
-static method callerA4([@vm.inferred-type.metadata=#lib::D?] self::A* aa) → void {
- [@vm.direct-call.metadata=#lib::C.foo??] [@vm.inferred-type.metadata=!? (skip check)] aa.{self::A::foo}(){() →* core::int*};
+static method callerA4([@vm.inferred-type.metadata=#lib::D] self::A aa) → void {
+ [@vm.direct-call.metadata=#lib::C.foo] [@vm.inferred-type.metadata=!? (skip check)] aa.{self::A::foo}(){() → core::int};
}
static method callerE1() → void {
- [@vm.direct-call.metadata=dart.core::_StringBase.toString] [@vm.inferred-type.metadata=!? (skip check) (receiver not int)](#C1).{core::Object::toString}(){() →* core::String*};
+ [@vm.direct-call.metadata=dart.core::_StringBase.toString] [@vm.inferred-type.metadata=!? (skip check) (receiver not int)](#C1).{core::Object::toString}(){() → core::String};
}
static method callerE2([@vm.inferred-type.metadata=#lib::E?] dynamic x) → void {
- [@vm.inferred-type.metadata=!? (receiver not int)] x.{core::Object::toString}(){() →* core::String*};
+ [@vm.inferred-type.metadata=!? (receiver not int)] x.{core::Object::toString}(){() → core::String};
}
-static method main(core::List<core::String*>* args) → dynamic {
+static method main(core::List<core::String> args) → dynamic {
self::callerA1(new self::B::•());
self::callerA1(new self::C::•());
self::callerA2(new self::B::•());
- let final self::C* #t1 = new self::C::•() in self::callerA3(#t1);
- self::callerA4([@vm.inferred-type.metadata=#lib::D?] self::dd);
+ let final self::C #t1 = new self::C::•() in self::callerA3(#t1);
+ self::callerA4([@vm.inferred-type.metadata=#lib::D] self::dd);
self::dd = new self::D::•();
self::callerE1();
self::callerE2([@vm.inferred-type.metadata=#lib::E?] self::ee);
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/dynamic_list_access.dart b/pkg/vm/testcases/transformations/type_flow/transformer/dynamic_list_access.dart
index 5f51fa3..5b75823 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/dynamic_list_access.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/dynamic_list_access.dart
@@ -1,4 +1,8 @@
+// Copyright (c) 2020, 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.
+
main() {
- dynamic x = List<int>.filled(10, null);
+ dynamic x = List<int?>.filled(10, null);
x[0] + 10;
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/dynamic_list_access.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/dynamic_list_access.dart.expect
index 17a558f..5fa7916 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/dynamic_list_access.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/dynamic_list_access.dart.expect
@@ -1,8 +1,8 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
static method main() → dynamic {
- dynamic x = [@vm.inferred-type.metadata=dart.core::_List<dart.core::int*>] core::_List::•<core::int*>(10);
+ dynamic x = [@vm.inferred-type.metadata=dart.core::_List<dart.core::int?>] core::_List::•<core::int?>(10);
[@vm.direct-call.metadata=dart.core::_IntegerImplementation.+??] [@vm.direct-call.metadata=dart.core::_List.[]] [@vm.inferred-type.metadata=int? (receiver not int)] x{dynamic}.[](0){dynamic}.+(10);
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/enum_used_as_type.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/enum_used_as_type.dart.expect
index ac4bbc2..34740ea 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/enum_used_as_type.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/enum_used_as_type.dart.expect
@@ -1,24 +1,21 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
import "dart:_internal" as _in;
abstract class Enum extends core::Object implements core::Enum {
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] abstract get index() → core::int*;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] abstract get /*isLegacy*/ index() → core::int;
}
class Class extends core::Object {
- synthetic constructor •() → self::Class*
+ synthetic constructor •() → self::Class
: super core::Object::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:2,getterSelectorId:3] method method() → core::int*
- return [@vm.inferred-type.metadata=!](#C1).{self::Enum::index}{core::int*};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:2,getterSelectorId:3] method method([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::Enum e) → core::int
+ return [@vm.inferred-type.metadata=!] e.{self::Enum::index}{core::int};
}
static method main() → dynamic {
- core::List<dynamic>* list = [@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic>] core::_GrowableList::•<dynamic>(0);
- if([@vm.direct-call.metadata=dart.core::_GrowableList.isNotEmpty] [@vm.inferred-type.metadata=dart.core::bool] list.{core::Iterable::isNotEmpty}{core::bool*}) {
- let final self::Class* #t1 = new self::Class::•() in let final self::Enum* #t2 = _in::unsafeCast<self::Enum*>(_in::unsafeCast<dynamic>(null)) in [@vm.direct-call.metadata=#lib::Class.method] [@vm.inferred-type.metadata=!? (skip check)] #t1.{self::Class::method}(){(self::Enum*) →* core::int*};
+ core::List<dynamic> list = [@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic>] core::_GrowableList::•<dynamic>(0);
+ if([@vm.direct-call.metadata=dart.core::_GrowableList.isNotEmpty] [@vm.inferred-type.metadata=dart.core::bool] list.{core::Iterable::isNotEmpty}{core::bool}) {
+ [@vm.direct-call.metadata=#lib::Class.method] [@vm.inferred-type.metadata=!? (skip check)] new self::Class::•().{self::Class::method}(_in::unsafeCast<self::Enum>(_in::unsafeCast<dynamic>(null))){(self::Enum) → core::int};
}
}
-constants {
- #C1 = null
-}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/ffi_struct_constructors.dart b/pkg/vm/testcases/transformations/type_flow/transformer/ffi_struct_constructors.dart
index fcdd2df..9cfd697 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/ffi_struct_constructors.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/ffi_struct_constructors.dart
@@ -6,65 +6,65 @@
/// Retained because of being by-value return type in FFI call.
class Struct1 extends Struct {
- Pointer notEmpty;
+ external Pointer notEmpty;
}
/// Retained because of being by-value return type in FFI call.
class Struct2 extends Struct {
- Pointer notEmpty;
+ external Pointer notEmpty;
}
/// Retained because of being by-value argument type in FFI callback.
class Struct3 extends Struct {
- Pointer notEmpty;
+ external Pointer notEmpty;
}
/// Class not retained, not referenced at all.
class Struct4 extends Struct {
- Pointer notEmpty;
+ external Pointer notEmpty;
}
/// Constructor not retained, only referenced as argument type in FFI
/// call but never instantiated in Dart code.
class Struct5 extends Struct {
- Pointer notEmpty;
+ external Pointer notEmpty;
}
/// Constructor not retained, only referenced as argument type in FFI
/// call but never instantiated in Dart code.
class Struct6 extends Struct {
- Pointer notEmpty;
+ external Pointer notEmpty;
}
/// Constructor not retained, only referenced as return value type in FFI
/// callback but never instantiated in Dart code.
class Struct7 extends Struct {
- Pointer notEmpty;
+ external Pointer notEmpty;
}
/// Not retained because of FFI call not being reachable.
class Struct8 extends Struct {
- Pointer notEmpty;
+ external Pointer notEmpty;
}
/// Not retained because of FFI call not being reachable.
class Struct9 extends Struct {
- Pointer notEmpty;
+ external Pointer notEmpty;
}
/// Not tetained because of FFI callback not being reachable.
class Struct10 extends Struct {
- Pointer notEmpty;
+ external Pointer notEmpty;
}
/// Retained by CFE rewrite of load from pointer.
class Struct11 extends Struct {
- Struct12 nested;
+ external Struct12 nested;
}
/// Retained by rewrite of load from surrounding struct.
class Struct12 extends Struct {
- Pointer notEmpty;
+ external Pointer notEmpty;
}
void main() {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/ffi_struct_constructors.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/ffi_struct_constructors.dart.expect
index f657ded..9086aa75 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/ffi_struct_constructors.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/ffi_struct_constructors.dart.expect
@@ -1,4 +1,4 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
import "dart:ffi" as ffi;
@@ -39,11 +39,11 @@
constructor #fromTypedDataBase([@vm.inferred-type.metadata=dart.ffi::Pointer] core::Object #typedDataBase) → self::Struct11
: super ffi::Struct::_fromTypedDataBase(#typedDataBase)
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] get nested() → self::Struct12*
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] get nested() → self::Struct12
return new self::Struct12::#fromTypedDataBase( block {
core::Object #typedDataBase = [@vm.direct-call.metadata=dart.ffi::_Compound._typedDataBase] this.{ffi::_Compound::_typedDataBase}{core::Object};
core::int #offset = (#C12).{core::List::[]}(ffi::_abi()){(core::int) → core::int*};
- } =>#typedDataBase is ffi::Pointer<dynamic> ?{core::Object} [@vm.inferred-type.metadata=dart.ffi::Pointer?] ffi::_fromAddress<self::Struct12*>([@vm.direct-call.metadata=dart.core::_IntegerImplementation.+??] [@vm.inferred-type.metadata=int (skip check)] [@vm.direct-call.metadata=dart.ffi::Pointer.address] [@vm.inferred-type.metadata=int?] #typedDataBase.{ffi::Pointer::address}{core::int}.{core::num::+}(#offset){(core::num) → core::num}) : let typ::TypedData #typedData = _in::unsafeCast<typ::TypedData>(#typedDataBase) in [@vm.direct-call.metadata=dart.typed_data::_ByteBuffer.asUint8List] [@vm.inferred-type.metadata=dart.typed_data::_Uint8ArrayView (skip check)] [@vm.inferred-type.metadata=dart.typed_data::_ByteBuffer] #typedData.{typ::TypedData::buffer}{typ::ByteBuffer}.{typ::ByteBuffer::asUint8List}([@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] [@vm.inferred-type.metadata=dart.core::_Smi] #typedData.{typ::TypedData::offsetInBytes}{core::int}.{core::num::+}(#offset){(core::num) → core::num}, (#C15).{core::List::[]}(ffi::_abi()){(core::int) → core::int*}){([core::int, core::int?]) → typ::Uint8List});
+ } =>#typedDataBase is ffi::Pointer<dynamic> ?{core::Object} [@vm.inferred-type.metadata=dart.ffi::Pointer?] ffi::_fromAddress<self::Struct12>([@vm.direct-call.metadata=dart.core::_IntegerImplementation.+??] [@vm.inferred-type.metadata=int (skip check)] [@vm.direct-call.metadata=dart.ffi::Pointer.address] [@vm.inferred-type.metadata=int?] #typedDataBase.{ffi::Pointer::address}{core::int}.{core::num::+}(#offset){(core::num) → core::num}) : let typ::TypedData #typedData = _in::unsafeCast<typ::TypedData>(#typedDataBase) in [@vm.direct-call.metadata=dart.typed_data::_ByteBuffer.asUint8List] [@vm.inferred-type.metadata=dart.typed_data::_Uint8ArrayView (skip check)] [@vm.inferred-type.metadata=dart.typed_data::_ByteBuffer] #typedData.{typ::TypedData::buffer}{typ::ByteBuffer}.{typ::ByteBuffer::asUint8List}([@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] [@vm.inferred-type.metadata=dart.core::_Smi] #typedData.{typ::TypedData::offsetInBytes}{core::int}.{core::num::+}(#offset){(core::num) → core::num}, (#C15).{core::List::[]}(ffi::_abi()){(core::int) → core::int*}){([core::int, core::int?]) → typ::Uint8List});
}
@#C6
class Struct12 extends ffi::Struct {
@@ -51,8 +51,8 @@
: super ffi::Struct::_fromTypedDataBase(#typedDataBase)
;
}
-[@vm.inferred-type.metadata=dart.ffi::Pointer?]static final field ffi::Pointer<ffi::NativeFunction<(self::Struct3*) →* ffi::Int32*>*>* _#ffiCallback0 = [@vm.inferred-type.metadata=dart.ffi::Pointer?] ffi::_pointerFromFunction<ffi::NativeFunction<(self::Struct3*) →* ffi::Int32*>*>(ffi::_nativeCallbackFunction<(self::Struct3*) →* ffi::Int32*>(#C16, 0));
-[@vm.inferred-type.metadata=dart.ffi::Pointer?]static final field ffi::Pointer<ffi::NativeFunction<() →* self::Struct7*>*>* _#ffiCallback1 = [@vm.inferred-type.metadata=dart.ffi::Pointer?] ffi::_pointerFromFunction<ffi::NativeFunction<() →* self::Struct7*>*>(ffi::_nativeCallbackFunction<() →* self::Struct7*>(#C17, null));
+[@vm.inferred-type.metadata=dart.ffi::Pointer?]static final field ffi::Pointer<ffi::NativeFunction<(self::Struct3) → ffi::Int32>*>* _#ffiCallback0 = [@vm.inferred-type.metadata=dart.ffi::Pointer?] ffi::_pointerFromFunction<ffi::NativeFunction<(self::Struct3) → ffi::Int32>*>(ffi::_nativeCallbackFunction<(self::Struct3) → ffi::Int32>(#C16, 0))/*isLegacy*/;
+[@vm.inferred-type.metadata=dart.ffi::Pointer?]static final field ffi::Pointer<ffi::NativeFunction<() → self::Struct7>*>* _#ffiCallback1 = [@vm.inferred-type.metadata=dart.ffi::Pointer?] ffi::_pointerFromFunction<ffi::NativeFunction<() → self::Struct7>*>(ffi::_nativeCallbackFunction<() → self::Struct7>(#C17, null))/*isLegacy*/;
static method main() → void {
self::testLookupFunctionReturn();
self::testLookupFunctionArgument();
@@ -64,56 +64,56 @@
self::testNestedLoad();
}
static method testLookupFunctionReturn() → void {
- final ffi::DynamicLibrary* dylib = [@vm.inferred-type.metadata=dart.ffi::DynamicLibrary?] ffi::DynamicLibrary::executable();
- final () →* self::Struct1* function1 = block {
+ final ffi::DynamicLibrary dylib = [@vm.inferred-type.metadata=dart.ffi::DynamicLibrary?] ffi::DynamicLibrary::executable();
+ final () → self::Struct1 function1 = block {
_in::_nativeEffect(new self::Struct1::#fromTypedDataBase([@vm.inferred-type.metadata=dart.typed_data::_Uint8List] typ::Uint8List::•(#C18)));
- } =>ffi::_asFunctionInternal<() →* self::Struct1*, () →* self::Struct1*>([@vm.direct-call.metadata=dart.ffi::DynamicLibrary.lookup??] [@vm.inferred-type.metadata=dart.ffi::Pointer? (skip check)] dylib.{ffi::DynamicLibrary::lookup}<ffi::NativeFunction<() →* self::Struct1*>*>("function1"){(core::String) → ffi::Pointer<ffi::NativeFunction<() →* self::Struct1*>*>}, false);
- final self::Struct1* struct1 = function1(){() →* self::Struct1*};
+ } =>ffi::_asFunctionInternal<() → self::Struct1, () → self::Struct1>([@vm.direct-call.metadata=dart.ffi::DynamicLibrary.lookup??] [@vm.inferred-type.metadata=dart.ffi::Pointer? (skip check)] dylib.{ffi::DynamicLibrary::lookup}<ffi::NativeFunction<() → self::Struct1>*>("function1"){(core::String) → ffi::Pointer<ffi::NativeFunction<() → self::Struct1>*>}, false);
+ final self::Struct1 struct1 = function1(){() → self::Struct1};
core::print(struct1);
}
static method testAsFunctionReturn() → void {
- final ffi::Pointer<ffi::NativeFunction<() →* self::Struct2*>*>* pointer = [@vm.inferred-type.metadata=dart.ffi::Pointer?] ffi::Pointer::fromAddress<ffi::NativeFunction<() →* self::Struct2*>*>(3735928559);
- final () →* self::Struct2* function2 = block {
+ final ffi::Pointer<ffi::NativeFunction<() → self::Struct2>> pointer = [@vm.inferred-type.metadata=dart.ffi::Pointer?] ffi::Pointer::fromAddress<ffi::NativeFunction<() → self::Struct2>>(3735928559);
+ final () → self::Struct2 function2 = block {
_in::_nativeEffect(new self::Struct2::#fromTypedDataBase([@vm.inferred-type.metadata=dart.typed_data::_Uint8List] typ::Uint8List::•(#C18)));
- } =>ffi::_asFunctionInternal<() →* self::Struct2*, () →* self::Struct2*>(pointer, false);
- final self::Struct2* struct2 = function2(){() →* self::Struct2*};
+ } =>ffi::_asFunctionInternal<() → self::Struct2, () → self::Struct2>(pointer, false);
+ final self::Struct2 struct2 = function2(){() → self::Struct2};
core::print(struct2);
}
-[@vm.unboxing-info.metadata=(b)->i]static method useStruct3(self::Struct3* struct3) → core::int* {
+[@vm.unboxing-info.metadata=(b)->i]static method useStruct3(self::Struct3 struct3) → core::int {
return 42;
}
static method testFromFunctionArgument() → void {
- final ffi::Pointer<ffi::NativeFunction<(self::Struct3*) →* ffi::Int32*>*>* pointer = block {
+ final ffi::Pointer<ffi::NativeFunction<(self::Struct3) → ffi::Int32>> pointer = block {
_in::_nativeEffect(new self::Struct3::#fromTypedDataBase([@vm.inferred-type.metadata=dart.typed_data::_Uint8List] typ::Uint8List::•(#C18)));
} =>[@vm.inferred-type.metadata=dart.ffi::Pointer?] self::_#ffiCallback0;
core::print(pointer);
}
static method testLookupFunctionArgument() → void {
- final ffi::DynamicLibrary* dylib = [@vm.inferred-type.metadata=dart.ffi::DynamicLibrary?] ffi::DynamicLibrary::executable();
- final (self::Struct5*) →* void function5 = [@vm.inferred-type.metadata=dart.core::_Closure?] ffi::_asFunctionInternal<(self::Struct5*) →* void, (self::Struct5*) →* ffi::Void*>([@vm.direct-call.metadata=dart.ffi::DynamicLibrary.lookup??] [@vm.inferred-type.metadata=dart.ffi::Pointer? (skip check)] dylib.{ffi::DynamicLibrary::lookup}<ffi::NativeFunction<(self::Struct5*) →* ffi::Void*>*>("function5"){(core::String) → ffi::Pointer<ffi::NativeFunction<(self::Struct5*) →* ffi::Void*>*>}, false);
+ final ffi::DynamicLibrary dylib = [@vm.inferred-type.metadata=dart.ffi::DynamicLibrary?] ffi::DynamicLibrary::executable();
+ final (self::Struct5) → void function5 = [@vm.inferred-type.metadata=dart.core::_Closure?] ffi::_asFunctionInternal<(self::Struct5) → void, (self::Struct5) → ffi::Void>([@vm.direct-call.metadata=dart.ffi::DynamicLibrary.lookup??] [@vm.inferred-type.metadata=dart.ffi::Pointer? (skip check)] dylib.{ffi::DynamicLibrary::lookup}<ffi::NativeFunction<(self::Struct5) → ffi::Void>*>("function5"){(core::String) → ffi::Pointer<ffi::NativeFunction<(self::Struct5) → ffi::Void>*>}, false);
core::print(function5);
}
static method testAsFunctionArgument() → void {
- final ffi::Pointer<ffi::NativeFunction<(self::Struct6*) →* ffi::Void*>*>* pointer = [@vm.inferred-type.metadata=dart.ffi::Pointer?] ffi::Pointer::fromAddress<ffi::NativeFunction<(self::Struct6*) →* ffi::Void*>*>(3735928559);
- final (self::Struct6*) →* void function6 = [@vm.inferred-type.metadata=dart.core::_Closure?] ffi::_asFunctionInternal<(self::Struct6*) →* void, (self::Struct6*) →* ffi::Void*>(pointer, false);
+ final ffi::Pointer<ffi::NativeFunction<(self::Struct6) → ffi::Void>> pointer = [@vm.inferred-type.metadata=dart.ffi::Pointer?] ffi::Pointer::fromAddress<ffi::NativeFunction<(self::Struct6) → ffi::Void>>(3735928559);
+ final (self::Struct6) → void function6 = [@vm.inferred-type.metadata=dart.core::_Closure?] ffi::_asFunctionInternal<(self::Struct6) → void, (self::Struct6) → ffi::Void>(pointer, false);
core::print(function6);
}
-static method returnStruct7() → self::Struct7* {
+static method returnStruct7() → self::Struct7 {
throw "I don't want to create a Struct7!";
}
static method testFromFunctionReturn() → void {
- final ffi::Pointer<ffi::NativeFunction<() →* self::Struct7*>*>* pointer = [@vm.inferred-type.metadata=dart.ffi::Pointer?] self::_#ffiCallback1;
+ final ffi::Pointer<ffi::NativeFunction<() → self::Struct7>> pointer = [@vm.inferred-type.metadata=dart.ffi::Pointer?] self::_#ffiCallback1;
core::print(pointer);
}
static method testPointerLoad() → void {
- final ffi::Pointer<self::Struct11*>* pointer = [@vm.inferred-type.metadata=dart.ffi::Pointer?] ffi::Pointer::fromAddress<self::Struct11*>(3735928559);
- final self::Struct11* struct11 = new self::Struct11::#fromTypedDataBase(pointer!);
+ final ffi::Pointer<self::Struct11> pointer = [@vm.inferred-type.metadata=dart.ffi::Pointer?] ffi::Pointer::fromAddress<self::Struct11>(3735928559);
+ final self::Struct11 struct11 = new self::Struct11::#fromTypedDataBase(pointer!);
core::print(struct11);
}
static method testNestedLoad() → void {
- final ffi::Pointer<self::Struct11*>* pointer = [@vm.inferred-type.metadata=dart.ffi::Pointer?] ffi::Pointer::fromAddress<self::Struct11*>(3735928559);
- final self::Struct11* struct11 = new self::Struct11::#fromTypedDataBase(pointer!);
- final self::Struct12* struct12 = [@vm.direct-call.metadata=#lib::Struct11.nested] [@vm.inferred-type.metadata=#lib::Struct12] struct11.{self::Struct11::nested}{self::Struct12*};
+ final ffi::Pointer<self::Struct11> pointer = [@vm.inferred-type.metadata=dart.ffi::Pointer?] ffi::Pointer::fromAddress<self::Struct11>(3735928559);
+ final self::Struct11 struct11 = new self::Struct11::#fromTypedDataBase(pointer!);
+ final self::Struct12 struct12 = [@vm.direct-call.metadata=#lib::Struct11.nested] [@vm.inferred-type.metadata=#lib::Struct12] struct11.{self::Struct11::nested}{self::Struct12};
core::print(struct12);
}
constants {
@@ -132,7 +132,7 @@
#C13 = 8
#C14 = 4
#C15 = <core::int*>[#C13, #C14, #C14]
- #C16 = tearoff self::useStruct3
- #C17 = tearoff self::returnStruct7
+ #C16 = static-tearoff self::useStruct3
+ #C17 = static-tearoff self::returnStruct7
#C18 = 1
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/future.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/future.dart.expect
index 8a43ab1..a0447e5 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/future.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/future.dart.expect
@@ -1,35 +1,35 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
import "dart:async" as asy;
import "dart:async";
-class C<T extends core::Object* = dynamic> extends core::Object {
- synthetic constructor •() → self::C<self::C::T*>*
+class C<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::C<self::C::T%>
: super core::Object::•()
;
-[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=(i)->b] method test2c([@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 3)] generic-covariant-impl FutureOr<self::C::T*>* x) → void {}
-[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] method test3c([@vm.inferred-type.metadata=dart.async::_Future<dart.core::int*> (skip check)] generic-covariant-impl asy::Future<self::C::T*>* x) → void {}
-[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] method test4c([@vm.inferred-type.metadata=dart.async::_Future<dart.core::int*> (skip check)] generic-covariant-impl FutureOr<self::C::T*>* x) → void {}
-[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] method test2r([@vm.inferred-type.metadata=#lib::C<dart.core::int*> (skip check)] generic-covariant-impl self::C<FutureOr<self::C::T*>*>* x) → void {}
-[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10] method test3r([@vm.inferred-type.metadata=#lib::C<dart.async::Future<dart.core::int*>*> (skip check)] generic-covariant-impl self::C<asy::Future<self::C::T*>*>* x) → void {}
-[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] method test4r([@vm.inferred-type.metadata=#lib::C<dart.async::Future<dart.core::int*>*> (skip check)] generic-covariant-impl self::C<FutureOr<self::C::T*>*>* x) → void {}
-[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14] method test5r([@vm.inferred-type.metadata=#lib::C<FutureOr<dart.core::int*>?>] generic-covariant-impl self::C<asy::Future<self::C::T*>*>* x) → void {}
-[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:15,getterSelectorId:16] method test6r([@vm.inferred-type.metadata=#lib::C<FutureOr<dart.core::int*>?> (skip check)] generic-covariant-impl self::C<FutureOr<self::C::T*>*>* x) → void {}
-[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:17,getterSelectorId:18] method test7r([@vm.inferred-type.metadata=#lib::C<FutureOr<dart.core::int*>?>] generic-covariant-impl self::C<self::C::T*>* x) → void {}
-[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:19,getterSelectorId:20] method test8r([@vm.inferred-type.metadata=#lib::C<dart.async::Future<dart.core::int*>*>] generic-covariant-impl self::C<self::C::T*>* x) → void {}
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=(i)->b] method test2c([@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 3)] generic-covariant-impl FutureOr<self::C::T%>x) → void {}
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] method test3c([@vm.inferred-type.metadata=dart.async::_Future<dart.core::int> (skip check)] generic-covariant-impl asy::Future<self::C::T%> x) → void {}
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] method test4c([@vm.inferred-type.metadata=dart.async::_Future<dart.core::int> (skip check)] generic-covariant-impl FutureOr<self::C::T%>x) → void {}
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] method test2r([@vm.inferred-type.metadata=#lib::C<dart.core::int> (skip check)] generic-covariant-impl self::C<FutureOr<self::C::T%>> x) → void {}
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10] method test3r([@vm.inferred-type.metadata=#lib::C<dart.async::Future<dart.core::int>> (skip check)] generic-covariant-impl self::C<asy::Future<self::C::T%>> x) → void {}
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] method test4r([@vm.inferred-type.metadata=#lib::C<dart.async::Future<dart.core::int>> (skip check)] generic-covariant-impl self::C<FutureOr<self::C::T%>> x) → void {}
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14] method test5r([@vm.inferred-type.metadata=#lib::C<FutureOr<dart.core::int>?>] generic-covariant-impl self::C<asy::Future<self::C::T%>> x) → void {}
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:15,getterSelectorId:16] method test6r([@vm.inferred-type.metadata=#lib::C<FutureOr<dart.core::int>?> (skip check)] generic-covariant-impl self::C<FutureOr<self::C::T%>> x) → void {}
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:17,getterSelectorId:18] method test7r([@vm.inferred-type.metadata=#lib::C<FutureOr<dart.core::int>?>] generic-covariant-impl self::C<self::C::T%> x) → void {}
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:19,getterSelectorId:20] method test8r([@vm.inferred-type.metadata=#lib::C<dart.async::Future<dart.core::int>>] generic-covariant-impl self::C<self::C::T%> x) → void {}
}
static method main() → dynamic {
- dynamic c = new self::C::•<core::int*>();
+ dynamic c = new self::C::•<core::int>();
[@vm.direct-call.metadata=#lib::C.test2c] [@vm.inferred-type.metadata=!? (receiver not int)] c{dynamic}.test2c(3);
- [@vm.direct-call.metadata=#lib::C.test3c] [@vm.inferred-type.metadata=!? (receiver not int)] c{dynamic}.test3c([@vm.inferred-type.metadata=dart.async::_Future<dart.core::int*>] asy::Future::value<core::int*>(3));
- [@vm.direct-call.metadata=#lib::C.test4c] [@vm.inferred-type.metadata=!? (receiver not int)] c{dynamic}.test4c([@vm.inferred-type.metadata=dart.async::_Future<dart.core::int*>] asy::Future::value<core::int*>(3));
- [@vm.direct-call.metadata=#lib::C.test2r] [@vm.inferred-type.metadata=!? (receiver not int)] c{dynamic}.test2r(new self::C::•<core::int*>());
- [@vm.direct-call.metadata=#lib::C.test3r] [@vm.inferred-type.metadata=!? (receiver not int)] c{dynamic}.test3r(new self::C::•<asy::Future<core::int*>*>());
- [@vm.direct-call.metadata=#lib::C.test4r] [@vm.inferred-type.metadata=!? (receiver not int)] c{dynamic}.test4r(new self::C::•<asy::Future<core::int*>*>());
- [@vm.direct-call.metadata=#lib::C.test5r] [@vm.inferred-type.metadata=!? (receiver not int)] c{dynamic}.test5r(new self::C::•<FutureOr<core::int*>*>());
- [@vm.direct-call.metadata=#lib::C.test6r] [@vm.inferred-type.metadata=!? (receiver not int)] c{dynamic}.test6r(new self::C::•<FutureOr<core::int*>*>());
- [@vm.direct-call.metadata=#lib::C.test7r] [@vm.inferred-type.metadata=!? (receiver not int)] c{dynamic}.test7r(new self::C::•<FutureOr<core::int*>*>());
- [@vm.direct-call.metadata=#lib::C.test8r] [@vm.inferred-type.metadata=!? (receiver not int)] c{dynamic}.test8r(new self::C::•<asy::Future<core::int*>*>());
+ [@vm.direct-call.metadata=#lib::C.test3c] [@vm.inferred-type.metadata=!? (receiver not int)] c{dynamic}.test3c([@vm.inferred-type.metadata=dart.async::_Future<dart.core::int>] asy::Future::value<core::int>(3));
+ [@vm.direct-call.metadata=#lib::C.test4c] [@vm.inferred-type.metadata=!? (receiver not int)] c{dynamic}.test4c([@vm.inferred-type.metadata=dart.async::_Future<dart.core::int>] asy::Future::value<core::int>(3));
+ [@vm.direct-call.metadata=#lib::C.test2r] [@vm.inferred-type.metadata=!? (receiver not int)] c{dynamic}.test2r(new self::C::•<core::int>());
+ [@vm.direct-call.metadata=#lib::C.test3r] [@vm.inferred-type.metadata=!? (receiver not int)] c{dynamic}.test3r(new self::C::•<asy::Future<core::int>>());
+ [@vm.direct-call.metadata=#lib::C.test4r] [@vm.inferred-type.metadata=!? (receiver not int)] c{dynamic}.test4r(new self::C::•<asy::Future<core::int>>());
+ [@vm.direct-call.metadata=#lib::C.test5r] [@vm.inferred-type.metadata=!? (receiver not int)] c{dynamic}.test5r(new self::C::•<FutureOr<core::int>>());
+ [@vm.direct-call.metadata=#lib::C.test6r] [@vm.inferred-type.metadata=!? (receiver not int)] c{dynamic}.test6r(new self::C::•<FutureOr<core::int>>());
+ [@vm.direct-call.metadata=#lib::C.test7r] [@vm.inferred-type.metadata=!? (receiver not int)] c{dynamic}.test7r(new self::C::•<FutureOr<core::int>>());
+ [@vm.direct-call.metadata=#lib::C.test8r] [@vm.inferred-type.metadata=!? (receiver not int)] c{dynamic}.test8r(new self::C::•<asy::Future<core::int>>());
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/future_or.dart b/pkg/vm/testcases/transformations/type_flow/transformer/future_or.dart
index f253547..f2136d5 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/future_or.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/future_or.dart
@@ -53,14 +53,14 @@
use(x);
}
-void foo2(Future<A> a1, A a2, FutureOr<A> a3, FutureOr<A> a4) {
+void foo2(Future<A>? a1, A? a2, FutureOr<A>? a3, FutureOr<A>? a4) {
foo2_a1(a1);
foo2_a2(a2);
foo2_a3(a3);
foo2_a4(a4);
}
-Function unknown;
+late Function unknown;
getDynamic() => unknown.call();
main(List<String> args) {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/future_or.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/future_or.dart.expect
index 4c9cbc4..c9b4c9f 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/future_or.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/future_or.dart.expect
@@ -1,4 +1,4 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
import "dart:async" as asy;
@@ -6,33 +6,33 @@
import "dart:async";
abstract class A extends core::Object {
- synthetic constructor •() → self::A*
+ synthetic constructor •() → self::A
: super core::Object::•()
;
}
class B extends self::A {
- synthetic constructor •() → self::B*
+ synthetic constructor •() → self::B
: super self::A::•()
;
}
static field dynamic usedObject;
-[@vm.inferred-type.metadata=dart.core::Null? (value: null)]static field core::Function* unknown;
+[@vm.inferred-type.metadata=!]late static field core::Function unknown;
static method use(dynamic object) → void {
self::usedObject == null ?{dynamic} self::usedObject = object : null;
}
-static method foo1_a1([@vm.inferred-type.metadata=dart.async::_Future<#lib::B*>] dynamic x) → void {
+static method foo1_a1([@vm.inferred-type.metadata=dart.async::_Future<#lib::B>] dynamic x) → void {
self::use(x);
}
static method foo1_a2([@vm.inferred-type.metadata=#lib::B] dynamic x) → void {
self::use(x);
}
-static method foo1_a3([@vm.inferred-type.metadata=dart.async::_Future<#lib::B*>] dynamic x) → void {
+static method foo1_a3([@vm.inferred-type.metadata=dart.async::_Future<#lib::B>] dynamic x) → void {
self::use(x);
}
static method foo1_a4([@vm.inferred-type.metadata=#lib::B] dynamic x) → void {
self::use(x);
}
-static method foo1([@vm.inferred-type.metadata=dart.async::_Future<#lib::B*>] asy::Future<self::A*>* a1, [@vm.inferred-type.metadata=#lib::B] self::A* a2, [@vm.inferred-type.metadata=dart.async::_Future<#lib::B*>] FutureOr<self::A*>* a3, [@vm.inferred-type.metadata=#lib::B] FutureOr<self::A*>* a4) → void {
+static method foo1([@vm.inferred-type.metadata=dart.async::_Future<#lib::B>] asy::Future<self::A> a1, [@vm.inferred-type.metadata=#lib::B] self::A a2, [@vm.inferred-type.metadata=dart.async::_Future<#lib::B>] FutureOr<self::A>a3, [@vm.inferred-type.metadata=#lib::B] FutureOr<self::A>a4) → void {
self::foo1_a1(a1);
self::foo1_a2(a2);
self::foo1_a3(a3);
@@ -50,7 +50,7 @@
static method foo2_a4(dynamic x) → void {
self::use(x);
}
-static method foo2([@vm.inferred-type.metadata=dart.async::_Future?] asy::Future<self::A*>* a1, [@vm.inferred-type.metadata=#lib::B?] self::A* a2, FutureOr<self::A*>* a3, FutureOr<self::A*>* a4) → void {
+static method foo2([@vm.inferred-type.metadata=dart.async::_Future?] asy::Future<self::A>? a1, [@vm.inferred-type.metadata=#lib::B?] self::A? a2, FutureOr<self::A>? a3, FutureOr<self::A>? a4) → void {
self::foo2_a1(a1);
self::foo2_a2(a2);
self::foo2_a3(a3);
@@ -58,7 +58,7 @@
}
static method getDynamic() → dynamic
return self::unknown();
-static method main(core::List<core::String*>* args) → dynamic {
- self::foo1([@vm.inferred-type.metadata=dart.async::_Future<#lib::B*>] asy::Future::value<self::B*>(new self::B::•()), new self::B::•(), [@vm.inferred-type.metadata=dart.async::_Future<#lib::B*>] asy::Future::value<self::B*>(new self::B::•()), new self::B::•());
- self::foo2(self::getDynamic() as{TypeError,ForDynamic} asy::Future<self::A*>*, self::getDynamic() as{TypeError,ForDynamic} self::A*, self::getDynamic() as{TypeError,ForDynamic} FutureOr<self::A*>*, self::getDynamic() as{TypeError,ForDynamic} FutureOr<self::A*>*);
+static method main(core::List<core::String> args) → dynamic {
+ self::foo1([@vm.inferred-type.metadata=dart.async::_Future<#lib::B>] asy::Future::value<self::B>(new self::B::•()), new self::B::•(), [@vm.inferred-type.metadata=dart.async::_Future<#lib::B>] asy::Future::value<self::B>(new self::B::•()), new self::B::•());
+ self::foo2(self::getDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<self::A>?, self::getDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} self::A?, self::getDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<self::A>?, self::getDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<self::A>?);
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/hello.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/hello.dart.expect
index 2296f5b..7b1f705 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/hello.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/hello.dart.expect
@@ -1,14 +1,14 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
class A extends core::Object {
- synthetic constructor •() → self::A*
+ synthetic constructor •() → self::A
: super core::Object::•()
;
}
-static method foo() → core::Object*
+static method foo() → core::Object
return new self::A::•();
-static method main(core::List<core::String*>* args) → dynamic {
+static method main(core::List<core::String> args) → dynamic {
core::print([@vm.inferred-type.metadata=#lib::A] self::foo());
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/instance_fields_with_initializers_nnbd.dart b/pkg/vm/testcases/transformations/type_flow/transformer/instance_fields_with_initializers_nnbd.dart
index bb66a2b..67c62c8 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/instance_fields_with_initializers_nnbd.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/instance_fields_with_initializers_nnbd.dart
@@ -4,8 +4,6 @@
// Test for tree shaking of instance fields with initializers.
-// @dart = 2.12
-
int sideEffect(int x) {
print(x);
return x;
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_cycle.dart b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_cycle.dart
index da1f458..fccae87 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_cycle.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_cycle.dart
@@ -18,11 +18,11 @@
class _BroadcastSubscription extends StreamSubscription {}
abstract class Stream {
- StreamSubscription foobar(void onData(event), {Function onError});
+ StreamSubscription foobar(void onData(event)?, {Function? onError});
}
abstract class _StreamImpl extends Stream {
- StreamSubscription foobar(void onData(data), {Function onError}) {
+ StreamSubscription foobar(void onData(data)?, {Function? onError}) {
return _createSubscription();
}
@@ -44,7 +44,7 @@
StreamView(Stream stream) : _stream = stream;
- StreamSubscription foobar(void onData(value), {Function onError}) {
+ StreamSubscription foobar(void onData(value)?, {Function? onError}) {
return _stream.foobar(onData, onError: onError);
}
}
@@ -52,15 +52,15 @@
class ByteStream extends StreamView {
ByteStream(Stream stream) : super(stream);
- super_foobar1(void onData(value)) {
+ super_foobar1(void onData(value)?) {
super.foobar(onData);
}
- super_foobar2(void onData(value)) {
+ super_foobar2(void onData(value)?) {
super.foobar(onData);
}
- super_foobar3({void onData(value), Function onError}) {
+ super_foobar3({void onData(value)?, Function? onError}) {
super.foobar(onData, onError: onError);
}
@@ -68,7 +68,7 @@
}
class _HandleErrorStream extends Stream {
- StreamSubscription foobar(void onData(event), {Function onError}) {
+ StreamSubscription foobar(void onData(event)?, {Function? onError}) {
return new _BufferingStreamSubscription();
}
}
@@ -77,26 +77,26 @@
new ByteStream(new ByteStream(new _GeneratedStreamImpl()));
}
-void round1({void onData(value)}) {
+void round1({void onData(value)?}) {
var x = new ByteStream(new ByteStream(new _GeneratedStreamImpl()));
x.super_foobar1(onData);
}
-void round2({void onData(value), Function onError}) {
+void round2({void onData(value)?, Function? onError}) {
new _ControllerStream();
Stream x = new _GeneratedStreamImpl();
x = new ByteStream(x);
x.foobar(onData, onError: onError);
}
-void round3({void onData(value), Function onError}) {
+void round3({void onData(value)?, Function? onError}) {
Stream x = new _GeneratedStreamImpl();
x = new ByteStream(x);
x = new _ControllerStream();
x.foobar(onData, onError: onError);
}
-void round4({void onData(value)}) {
+void round4({void onData(value)?}) {
var x = new ByteStream(new _ControllerStream());
var y = x.super_stream;
var z = x._stream;
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_cycle.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_cycle.dart.expect
index 4b18c73..4771de1 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_cycle.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_cycle.dart.expect
@@ -1,80 +1,79 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
abstract class StreamSubscription extends core::Object {
- synthetic constructor •() → self::StreamSubscription*
+ synthetic constructor •() → self::StreamSubscription
: super core::Object::•()
;
}
class _BufferingStreamSubscription extends self::StreamSubscription {
- synthetic constructor •() → self::_BufferingStreamSubscription*
+ synthetic constructor •() → self::_BufferingStreamSubscription
: super self::StreamSubscription::•()
;
}
class _BroadcastSubscription extends self::StreamSubscription {
- synthetic constructor •() → self::_BroadcastSubscription*
+ synthetic constructor •() → self::_BroadcastSubscription
: super self::StreamSubscription::•()
;
}
abstract class Stream extends core::Object {
- synthetic constructor •() → self::Stream*
+ synthetic constructor •() → self::Stream
: super core::Object::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] abstract method foobar() → self::StreamSubscription*;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3] abstract operator ==(dynamic other) → core::bool*;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] abstract method foobar() → self::StreamSubscription;
}
abstract class _StreamImpl extends self::Stream {
- synthetic constructor •() → self::_StreamImpl*
+ synthetic constructor •() → self::_StreamImpl
: super self::Stream::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method foobar() → self::StreamSubscription* {
- return [@vm.inferred-type.metadata=! (skip check)] this.{self::_StreamImpl::_createSubscription}(){() →* self::StreamSubscription*};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method foobar() → self::StreamSubscription {
+ return [@vm.inferred-type.metadata=! (skip check)] this.{self::_StreamImpl::_createSubscription}(){() → self::StreamSubscription};
}
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5] method _createSubscription() → self::StreamSubscription* {
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] method _createSubscription() → self::StreamSubscription {
return new self::_BufferingStreamSubscription::•();
}
}
class _ControllerStream extends self::_StreamImpl {
- synthetic constructor •() → self::_ControllerStream*
+ synthetic constructor •() → self::_ControllerStream
: super self::_StreamImpl::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5] method _createSubscription() → self::StreamSubscription* {
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] method _createSubscription() → self::StreamSubscription {
return new self::_BroadcastSubscription::•();
}
}
class _GeneratedStreamImpl extends self::_StreamImpl {
- synthetic constructor •() → self::_GeneratedStreamImpl*
+ synthetic constructor •() → self::_GeneratedStreamImpl
: super self::_StreamImpl::•()
;
}
abstract class StreamView extends self::Stream {
-[@vm.inferred-type.metadata=!] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:6] final field self::Stream* _stream;
- constructor •([@vm.inferred-type.metadata=!] self::Stream* stream) → self::StreamView*
+[@vm.inferred-type.metadata=!] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:5] final field self::Stream _stream;
+ constructor •([@vm.inferred-type.metadata=!] self::Stream stream) → self::StreamView
: self::StreamView::_stream = stream, super self::Stream::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method foobar() → self::StreamSubscription* {
- return [@vm.direct-call.metadata=#lib::StreamView._stream] [@vm.inferred-type.metadata=!] this.{self::StreamView::_stream}{self::Stream*}.{self::Stream::foobar}(){((dynamic) →* void, {onError: core::Function*}) →* self::StreamSubscription*};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method foobar() → self::StreamSubscription {
+ return [@vm.direct-call.metadata=#lib::StreamView._stream] [@vm.inferred-type.metadata=!] this.{self::StreamView::_stream}{self::Stream}.{self::Stream::foobar}(){((dynamic) →? void, {onError: core::Function?}) → self::StreamSubscription};
}
}
class ByteStream extends self::StreamView {
- constructor •([@vm.inferred-type.metadata=!] self::Stream* stream) → self::ByteStream*
+ constructor •([@vm.inferred-type.metadata=!] self::Stream stream) → self::ByteStream
: super self::StreamView::•(stream)
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] method super_foobar1() → dynamic {
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7] method super_foobar1() → dynamic {
super.{self::StreamView::foobar}();
}
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10] method super_foobar2() → dynamic {
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:8,getterSelectorId:9] method super_foobar2() → dynamic {
super.{self::StreamView::foobar}();
}
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] method super_foobar3() → dynamic {
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:10,getterSelectorId:11] method super_foobar3() → dynamic {
super.{self::StreamView::foobar}();
}
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:13] get super_stream() → self::Stream*
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:12] get super_stream() → self::Stream
return [@vm.inferred-type.metadata=!] super.{self::StreamView::_stream};
}
class _HandleErrorStream extends self::Stream {
- synthetic constructor •() → self::_HandleErrorStream*
+ synthetic constructor •() → self::_HandleErrorStream
: super self::Stream::•()
;
}
@@ -82,35 +81,35 @@
new self::ByteStream::•(new self::ByteStream::•(new self::_GeneratedStreamImpl::•()));
}
static method round1() → void {
- self::ByteStream* x = new self::ByteStream::•(new self::ByteStream::•(new self::_GeneratedStreamImpl::•()));
- [@vm.direct-call.metadata=#lib::ByteStream.super_foobar1] [@vm.inferred-type.metadata=!? (skip check)] x.{self::ByteStream::super_foobar1}(){((dynamic) →* void) →* dynamic};
+ self::ByteStream x = new self::ByteStream::•(new self::ByteStream::•(new self::_GeneratedStreamImpl::•()));
+ [@vm.direct-call.metadata=#lib::ByteStream.super_foobar1] [@vm.inferred-type.metadata=!? (skip check)] x.{self::ByteStream::super_foobar1}(){((dynamic) →? void) → dynamic};
}
static method round2() → void {
new self::_ControllerStream::•();
- self::Stream* x = new self::_GeneratedStreamImpl::•();
+ self::Stream x = new self::_GeneratedStreamImpl::•();
x = new self::ByteStream::•(x);
- [@vm.direct-call.metadata=#lib::StreamView.foobar] [@vm.inferred-type.metadata=!? (skip check)] x.{self::Stream::foobar}(){((dynamic) →* void, {onError: core::Function*}) →* self::StreamSubscription*};
+ [@vm.direct-call.metadata=#lib::StreamView.foobar] [@vm.inferred-type.metadata=!? (skip check)] x.{self::Stream::foobar}(){((dynamic) →? void, {onError: core::Function?}) → self::StreamSubscription};
}
static method round3() → void {
- self::Stream* x = new self::_GeneratedStreamImpl::•();
+ self::Stream x = new self::_GeneratedStreamImpl::•();
x = new self::ByteStream::•(x);
x = new self::_ControllerStream::•();
- [@vm.direct-call.metadata=#lib::_StreamImpl.foobar] [@vm.inferred-type.metadata=!? (skip check)] x.{self::Stream::foobar}(){((dynamic) →* void, {onError: core::Function*}) →* self::StreamSubscription*};
+ [@vm.direct-call.metadata=#lib::_StreamImpl.foobar] [@vm.inferred-type.metadata=!? (skip check)] x.{self::Stream::foobar}(){((dynamic) →? void, {onError: core::Function?}) → self::StreamSubscription};
}
static method round4() → void {
- self::ByteStream* x = new self::ByteStream::•(new self::_ControllerStream::•());
- self::Stream* y = [@vm.direct-call.metadata=#lib::ByteStream.super_stream] [@vm.inferred-type.metadata=!] x.{self::ByteStream::super_stream}{self::Stream*};
- self::Stream* z = [@vm.direct-call.metadata=#lib::StreamView._stream] [@vm.inferred-type.metadata=!] x.{self::StreamView::_stream}{self::Stream*};
- if([@vm.direct-call.metadata=dart.core::Object.==] [@vm.inferred-type.metadata=dart.core::bool (skip check) (receiver not int)] y =={self::Stream::==}{(dynamic) →* core::bool*} z) {
- [@vm.direct-call.metadata=#lib::ByteStream.super_foobar2] [@vm.inferred-type.metadata=!? (skip check)] x.{self::ByteStream::super_foobar2}(){((dynamic) →* void) →* dynamic};
+ self::ByteStream x = new self::ByteStream::•(new self::_ControllerStream::•());
+ self::Stream y = [@vm.direct-call.metadata=#lib::ByteStream.super_stream] [@vm.inferred-type.metadata=!] x.{self::ByteStream::super_stream}{self::Stream};
+ self::Stream z = [@vm.direct-call.metadata=#lib::StreamView._stream] [@vm.inferred-type.metadata=!] x.{self::StreamView::_stream}{self::Stream};
+ if([@vm.direct-call.metadata=dart.core::Object.==] [@vm.inferred-type.metadata=dart.core::bool (skip check) (receiver not int)] y =={core::Object::==}{(core::Object) → core::bool} z) {
+ [@vm.direct-call.metadata=#lib::ByteStream.super_foobar2] [@vm.inferred-type.metadata=!? (skip check)] x.{self::ByteStream::super_foobar2}(){((dynamic) →? void) → dynamic};
}
}
static method round5() → void {
- self::ByteStream* x = new self::ByteStream::•(new self::_GeneratedStreamImpl::•());
+ self::ByteStream x = new self::ByteStream::•(new self::_GeneratedStreamImpl::•());
new self::_HandleErrorStream::•();
- [@vm.direct-call.metadata=#lib::ByteStream.super_foobar3] [@vm.inferred-type.metadata=!? (skip check)] x.{self::ByteStream::super_foobar3}(){({onData: (dynamic) →* void, onError: core::Function*}) →* dynamic};
+ [@vm.direct-call.metadata=#lib::ByteStream.super_foobar3] [@vm.inferred-type.metadata=!? (skip check)] x.{self::ByteStream::super_foobar3}(){({onData: (dynamic) →? void, onError: core::Function?}) → dynamic};
}
-static method main(core::List<core::String*>* args) → dynamic {
+static method main(core::List<core::String> args) → dynamic {
new self::_GeneratedStreamImpl::•();
self::round0();
self::round1();
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_field_initializer.dart b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_field_initializer.dart
index c4e949c..01188a6 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_field_initializer.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_field_initializer.dart
@@ -18,7 +18,7 @@
Object foo() => new T2();
}
-Function unknown;
+late Function unknown;
getDynamic() => unknown.call();
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_field_initializer.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_field_initializer.dart.expect
index 43bee1f..1723808 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_field_initializer.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_field_initializer.dart.expect
@@ -1,82 +1,82 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
class T1 extends core::Object {
- synthetic constructor •() → self::T1*
+ synthetic constructor •() → self::T1
: super core::Object::•()
;
}
class T2 extends core::Object {
- synthetic constructor •() → self::T2*
+ synthetic constructor •() → self::T2
: super core::Object::•()
;
}
abstract class A extends core::Object {
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] abstract method foo() → core::Object*;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] abstract method foo() → core::Object;
}
class B extends core::Object implements self::A {
- synthetic constructor •() → self::B*
+ synthetic constructor •() → self::B
: super core::Object::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method foo() → core::Object*
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method foo() → core::Object
return new self::T1::•();
}
class C extends core::Object implements self::A {
- synthetic constructor •() → self::C*
+ synthetic constructor •() → self::C
: super core::Object::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method foo() → core::Object*
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method foo() → core::Object
return new self::T2::•();
}
class DeepCaller1 extends core::Object {
- synthetic constructor •() → self::DeepCaller1*
+ synthetic constructor •() → self::DeepCaller1
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] method barL1() → dynamic
- return [@vm.direct-call.metadata=#lib::DeepCaller1.barL2] [@vm.inferred-type.metadata=!? (skip check)] this.{self::DeepCaller1::barL2}(){() →* dynamic};
+ return [@vm.direct-call.metadata=#lib::DeepCaller1.barL2] [@vm.inferred-type.metadata=!? (skip check)] this.{self::DeepCaller1::barL2}(){() → dynamic};
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] method barL2() → dynamic
- return [@vm.direct-call.metadata=#lib::DeepCaller1.barL3] [@vm.inferred-type.metadata=!? (skip check)] this.{self::DeepCaller1::barL3}(){() →* dynamic};
+ return [@vm.direct-call.metadata=#lib::DeepCaller1.barL3] [@vm.inferred-type.metadata=!? (skip check)] this.{self::DeepCaller1::barL3}(){() → dynamic};
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] method barL3() → dynamic
- return [@vm.direct-call.metadata=#lib::DeepCaller1.barL4] [@vm.inferred-type.metadata=!? (skip check)] this.{self::DeepCaller1::barL4}(){() →* dynamic};
+ return [@vm.direct-call.metadata=#lib::DeepCaller1.barL4] [@vm.inferred-type.metadata=!? (skip check)] this.{self::DeepCaller1::barL4}(){() → dynamic};
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10] method barL4() → dynamic
return self::field1;
}
class D extends core::Object {
-[@vm.inferred-type.metadata=!] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] field core::Object* field2;
- synthetic constructor •() → self::D*
+[@vm.inferred-type.metadata=!] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] field core::Object field2;
+ synthetic constructor •() → self::D
: self::D::field2 = [@vm.inferred-type.metadata=!] self::getValue(), super core::Object::•()
;
}
class DeepCaller2 extends core::Object {
- synthetic constructor •() → self::DeepCaller2*
+ synthetic constructor •() → self::DeepCaller2
: super core::Object::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14] method barL1([@vm.inferred-type.metadata=#lib::D] self::D* dd) → dynamic
- return [@vm.direct-call.metadata=#lib::DeepCaller2.barL2] [@vm.inferred-type.metadata=! (skip check)] this.{self::DeepCaller2::barL2}(dd){(self::D*) →* dynamic};
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:15,getterSelectorId:16] method barL2([@vm.inferred-type.metadata=#lib::D] self::D* dd) → dynamic
- return [@vm.direct-call.metadata=#lib::DeepCaller2.barL3] [@vm.inferred-type.metadata=! (skip check)] this.{self::DeepCaller2::barL3}(dd){(self::D*) →* dynamic};
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:17,getterSelectorId:18] method barL3([@vm.inferred-type.metadata=#lib::D] self::D* dd) → dynamic
- return [@vm.direct-call.metadata=#lib::DeepCaller2.barL4] [@vm.inferred-type.metadata=! (skip check)] this.{self::DeepCaller2::barL4}(dd){(self::D*) →* dynamic};
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:19,getterSelectorId:20] method barL4([@vm.inferred-type.metadata=#lib::D] self::D* dd) → dynamic
- return [@vm.direct-call.metadata=#lib::D.field2] [@vm.inferred-type.metadata=!] dd.{self::D::field2}{core::Object*};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14] method barL1([@vm.inferred-type.metadata=#lib::D] self::D dd) → dynamic
+ return [@vm.direct-call.metadata=#lib::DeepCaller2.barL2] [@vm.inferred-type.metadata=! (skip check)] this.{self::DeepCaller2::barL2}(dd){(self::D) → dynamic};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:15,getterSelectorId:16] method barL2([@vm.inferred-type.metadata=#lib::D] self::D dd) → dynamic
+ return [@vm.direct-call.metadata=#lib::DeepCaller2.barL3] [@vm.inferred-type.metadata=! (skip check)] this.{self::DeepCaller2::barL3}(dd){(self::D) → dynamic};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:17,getterSelectorId:18] method barL3([@vm.inferred-type.metadata=#lib::D] self::D dd) → dynamic
+ return [@vm.direct-call.metadata=#lib::DeepCaller2.barL4] [@vm.inferred-type.metadata=! (skip check)] this.{self::DeepCaller2::barL4}(dd){(self::D) → dynamic};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:19,getterSelectorId:20] method barL4([@vm.inferred-type.metadata=#lib::D] self::D dd) → dynamic
+ return [@vm.direct-call.metadata=#lib::D.field2] [@vm.inferred-type.metadata=!] dd.{self::D::field2}{core::Object};
}
-[@vm.inferred-type.metadata=dart.core::Null? (value: null)]static field core::Function* unknown;
-static field core::Object* field1 = [@vm.inferred-type.metadata=!] self::getValue();
+[@vm.inferred-type.metadata=!]late static field core::Function unknown;
+static field core::Object field1 = [@vm.inferred-type.metadata=!] self::getValue();
static method getDynamic() → dynamic
return self::unknown();
-static method getValue() → core::Object* {
- self::A* aa = self::getDynamic() as{TypeError,ForDynamic} self::A*;
- return [@vm.inferred-type.metadata=!] aa.{self::A::foo}(){() →* core::Object*};
+static method getValue() → core::Object {
+ self::A aa = self::getDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} self::A;
+ return [@vm.inferred-type.metadata=!] aa.{self::A::foo}(){() → core::Object};
}
-static method use1([@vm.inferred-type.metadata=#lib::DeepCaller1] self::DeepCaller1* x) → dynamic
- return [@vm.direct-call.metadata=#lib::DeepCaller1.barL1] [@vm.inferred-type.metadata=!? (skip check)] x.{self::DeepCaller1::barL1}(){() →* dynamic};
-static method use2([@vm.inferred-type.metadata=#lib::DeepCaller2] self::DeepCaller2* x) → dynamic
- return [@vm.direct-call.metadata=#lib::DeepCaller2.barL1] [@vm.inferred-type.metadata=! (skip check)] x.{self::DeepCaller2::barL1}(new self::D::•()){(self::D*) →* dynamic};
+static method use1([@vm.inferred-type.metadata=#lib::DeepCaller1] self::DeepCaller1 x) → dynamic
+ return [@vm.direct-call.metadata=#lib::DeepCaller1.barL1] [@vm.inferred-type.metadata=!? (skip check)] x.{self::DeepCaller1::barL1}(){() → dynamic};
+static method use2([@vm.inferred-type.metadata=#lib::DeepCaller2] self::DeepCaller2 x) → dynamic
+ return [@vm.direct-call.metadata=#lib::DeepCaller2.barL1] [@vm.inferred-type.metadata=! (skip check)] x.{self::DeepCaller2::barL1}(new self::D::•()){(self::D) → dynamic};
static method createC() → dynamic {
new self::C::•();
}
-static method main(core::List<core::String*>* args) → dynamic {
+static method main(core::List<core::String> args) → dynamic {
new self::B::•();
self::use1(new self::DeepCaller1::•());
self::use2(new self::DeepCaller2::•());
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class1.dart b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class1.dart
index b70a6cf..0bc4332 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class1.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class1.dart
@@ -25,7 +25,7 @@
use1(Intermediate i, A aa) => i.bar(aa);
use2(Intermediate i, A aa) => i.bar(aa);
-Function unknown;
+late Function unknown;
getDynamic() => unknown.call();
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class1.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class1.dart.expect
index 750a33e..e916e0c 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class1.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class1.dart.expect
@@ -1,44 +1,44 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
class T1 extends core::Object {
- synthetic constructor •() → self::T1*
+ synthetic constructor •() → self::T1
: super core::Object::•()
;
}
abstract class A extends core::Object {
- synthetic constructor •() → self::A*
+ synthetic constructor •() → self::A
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] abstract method foo() → dynamic;
}
class B extends self::A {
- synthetic constructor •() → self::B*
+ synthetic constructor •() → self::B
: super self::A::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method foo() → dynamic
return new self::T1::•();
}
class Intermediate extends core::Object {
- synthetic constructor •() → self::Intermediate*
+ synthetic constructor •() → self::Intermediate
: super core::Object::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] method bar([@vm.inferred-type.metadata=#lib::B?] self::A* aa) → dynamic
- return [@vm.direct-call.metadata=#lib::B.foo??] [@vm.inferred-type.metadata=#lib::T1 (skip check)] aa.{self::A::foo}(){() →* dynamic};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] method bar([@vm.inferred-type.metadata=#lib::B?] self::A aa) → dynamic
+ return [@vm.direct-call.metadata=#lib::B.foo??] [@vm.inferred-type.metadata=#lib::T1 (skip check)] aa.{self::A::foo}(){() → dynamic};
}
-[@vm.inferred-type.metadata=dart.core::Null? (value: null)]static field core::Function* unknown;
-static method use1([@vm.inferred-type.metadata=#lib::Intermediate] self::Intermediate* i, [@vm.inferred-type.metadata=#lib::B?] self::A* aa) → dynamic
- return [@vm.direct-call.metadata=#lib::Intermediate.bar] [@vm.inferred-type.metadata=#lib::T1 (skip check)] i.{self::Intermediate::bar}(aa){(self::A*) →* dynamic};
-static method use2([@vm.inferred-type.metadata=#lib::Intermediate] self::Intermediate* i, [@vm.inferred-type.metadata=#lib::B?] self::A* aa) → dynamic
- return [@vm.direct-call.metadata=#lib::Intermediate.bar] [@vm.inferred-type.metadata=#lib::T1 (skip check)] i.{self::Intermediate::bar}(aa){(self::A*) →* dynamic};
+[@vm.inferred-type.metadata=!]late static field core::Function unknown;
+static method use1([@vm.inferred-type.metadata=#lib::Intermediate] self::Intermediate i, [@vm.inferred-type.metadata=#lib::B?] self::A aa) → dynamic
+ return [@vm.direct-call.metadata=#lib::Intermediate.bar] [@vm.inferred-type.metadata=#lib::T1 (skip check)] i.{self::Intermediate::bar}(aa){(self::A) → dynamic};
+static method use2([@vm.inferred-type.metadata=#lib::Intermediate] self::Intermediate i, [@vm.inferred-type.metadata=#lib::B?] self::A aa) → dynamic
+ return [@vm.direct-call.metadata=#lib::Intermediate.bar] [@vm.inferred-type.metadata=#lib::T1 (skip check)] i.{self::Intermediate::bar}(aa){(self::A) → dynamic};
static method getDynamic() → dynamic
return self::unknown();
static method allocateB() → dynamic {
new self::B::•();
}
-static method main(core::List<core::String*>* args) → dynamic {
- self::use1(new self::Intermediate::•(), self::getDynamic() as{TypeError,ForDynamic} self::A*);
+static method main(core::List<core::String> args) → dynamic {
+ self::use1(new self::Intermediate::•(), self::getDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} self::A);
self::allocateB();
- self::use2(new self::Intermediate::•(), self::getDynamic() as{TypeError,ForDynamic} self::A*);
+ self::use2(new self::Intermediate::•(), self::getDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} self::A);
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class2.dart b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class2.dart
index 5248ac9..ca439fa 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class2.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class2.dart
@@ -30,7 +30,7 @@
use2(Intermediate i, A aa) => i.bar(aa);
use3(Intermediate i, A aa) => i.bar(aa);
-Function unknown;
+late Function unknown;
getDynamic() => unknown.call();
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class2.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class2.dart.expect
index 50f57c2..dc456ee 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class2.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class2.dart.expect
@@ -1,25 +1,25 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
class T1 extends core::Object {
- synthetic constructor •() → self::T1*
+ synthetic constructor •() → self::T1
: super core::Object::•()
;
}
class T2 extends core::Object {
- synthetic constructor •() → self::T2*
+ synthetic constructor •() → self::T2
: super core::Object::•()
;
}
abstract class A extends core::Object {
- synthetic constructor •() → self::A*
+ synthetic constructor •() → self::A
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] abstract method foo() → dynamic;
}
class B extends self::A {
- synthetic constructor •() → self::B*
+ synthetic constructor •() → self::B
: super self::A::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method foo() → dynamic
@@ -28,36 +28,36 @@
abstract class C extends core::Object implements self::B {
}
abstract class D extends core::Object {
- synthetic constructor •() → self::D*
+ synthetic constructor •() → self::D
: super core::Object::•()
;
}
abstract class _E&D&C extends self::D implements self::C /*isAnonymousMixin,isEliminatedMixin*/ {
- synthetic constructor •() → self::_E&D&C*
+ synthetic constructor •() → self::_E&D&C
: super self::D::•()
;
}
class E extends self::_E&D&C {
- synthetic constructor •() → self::E*
+ synthetic constructor •() → self::E
: super self::_E&D&C::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method foo() → dynamic
return new self::T2::•();
}
class Intermediate extends core::Object {
- synthetic constructor •() → self::Intermediate*
+ synthetic constructor •() → self::Intermediate
: super core::Object::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] method bar(self::A* aa) → dynamic
- return [@vm.inferred-type.metadata=!] aa.{self::A::foo}(){() →* dynamic};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] method bar(self::A aa) → dynamic
+ return [@vm.inferred-type.metadata=!] aa.{self::A::foo}(){() → dynamic};
}
-[@vm.inferred-type.metadata=dart.core::Null? (value: null)]static field core::Function* unknown;
-static method use1([@vm.inferred-type.metadata=#lib::Intermediate] self::Intermediate* i, self::A* aa) → dynamic
- return [@vm.direct-call.metadata=#lib::Intermediate.bar] [@vm.inferred-type.metadata=! (skip check)] i.{self::Intermediate::bar}(aa){(self::A*) →* dynamic};
-static method use2([@vm.inferred-type.metadata=#lib::Intermediate] self::Intermediate* i, self::A* aa) → dynamic
- return [@vm.direct-call.metadata=#lib::Intermediate.bar] [@vm.inferred-type.metadata=! (skip check)] i.{self::Intermediate::bar}(aa){(self::A*) →* dynamic};
-static method use3([@vm.inferred-type.metadata=#lib::Intermediate] self::Intermediate* i, self::A* aa) → dynamic
- return [@vm.direct-call.metadata=#lib::Intermediate.bar] [@vm.inferred-type.metadata=! (skip check)] i.{self::Intermediate::bar}(aa){(self::A*) →* dynamic};
+[@vm.inferred-type.metadata=!]late static field core::Function unknown;
+static method use1([@vm.inferred-type.metadata=#lib::Intermediate] self::Intermediate i, self::A aa) → dynamic
+ return [@vm.direct-call.metadata=#lib::Intermediate.bar] [@vm.inferred-type.metadata=! (skip check)] i.{self::Intermediate::bar}(aa){(self::A) → dynamic};
+static method use2([@vm.inferred-type.metadata=#lib::Intermediate] self::Intermediate i, self::A aa) → dynamic
+ return [@vm.direct-call.metadata=#lib::Intermediate.bar] [@vm.inferred-type.metadata=! (skip check)] i.{self::Intermediate::bar}(aa){(self::A) → dynamic};
+static method use3([@vm.inferred-type.metadata=#lib::Intermediate] self::Intermediate i, self::A aa) → dynamic
+ return [@vm.direct-call.metadata=#lib::Intermediate.bar] [@vm.inferred-type.metadata=! (skip check)] i.{self::Intermediate::bar}(aa){(self::A) → dynamic};
static method getDynamic() → dynamic
return self::unknown();
static method allocateB() → dynamic {
@@ -66,10 +66,10 @@
static method allocateE() → dynamic {
new self::E::•();
}
-static method main(core::List<core::String*>* args) → dynamic {
- self::use1(new self::Intermediate::•(), self::getDynamic() as{TypeError,ForDynamic} self::A*);
+static method main(core::List<core::String> args) → dynamic {
+ self::use1(new self::Intermediate::•(), self::getDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} self::A);
self::allocateB();
- self::use2(new self::Intermediate::•(), self::getDynamic() as{TypeError,ForDynamic} self::A*);
+ self::use2(new self::Intermediate::•(), self::getDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} self::A);
self::allocateE();
- self::use3(new self::Intermediate::•(), self::getDynamic() as{TypeError,ForDynamic} self::A*);
+ self::use3(new self::Intermediate::•(), self::getDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} self::A);
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_dynamic_target.dart b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_dynamic_target.dart
index cd5d128..01417ef 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_dynamic_target.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_dynamic_target.dart
@@ -27,7 +27,7 @@
use_bazz(dynamic x) => x.bazz();
-Function unknown;
+late Function unknown;
getDynamic() => unknown.call();
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_dynamic_target.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_dynamic_target.dart.expect
index 13a7d78b..c049955 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_dynamic_target.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_dynamic_target.dart.expect
@@ -1,24 +1,24 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
class T1 extends core::Object {
- synthetic constructor •() → self::T1*
+ synthetic constructor •() → self::T1
: super core::Object::•()
;
}
class T2 extends core::Object {
- synthetic constructor •() → self::T2*
+ synthetic constructor •() → self::T2
: super core::Object::•()
;
}
class T3 extends core::Object {
- synthetic constructor •() → self::T3*
+ synthetic constructor •() → self::T3
: super core::Object::•()
;
}
class A extends core::Object {
- synthetic constructor •() → self::A*
+ synthetic constructor •() → self::A
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method foo() → dynamic
@@ -29,7 +29,7 @@
return new self::T3::•();
}
class B extends core::Object {
- synthetic constructor •() → self::B*
+ synthetic constructor •() → self::B
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] method foo() → dynamic
@@ -39,7 +39,7 @@
[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] method bazz() → dynamic
return new self::T3::•();
}
-[@vm.inferred-type.metadata=dart.core::Null? (value: null)]static field core::Function* unknown;
+[@vm.inferred-type.metadata=!]late static field core::Function unknown;
static method use_foo1(dynamic x) → dynamic
return [@vm.inferred-type.metadata=#lib::T1] x{dynamic}.foo();
static method use_foo2(dynamic x) → dynamic
@@ -56,7 +56,7 @@
static method allocateB() → dynamic {
new self::B::•();
}
-static method main(core::List<core::String*>* args) → dynamic {
+static method main(core::List<core::String> args) → dynamic {
self::use_foo1(self::getDynamic());
self::allocateA();
self::use_foo2(self::getDynamic());
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_set_field.dart b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_set_field.dart
index 7fb845e..5232b28 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_set_field.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_set_field.dart
@@ -30,7 +30,7 @@
use1(DeepCaller1 x, A aa) => x.barL1(aa);
use2(DeepCaller2 x, A aa) => x.barL1(aa);
-Function unknown;
+late Function unknown;
getDynamic() => unknown.call();
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_set_field.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_set_field.dart.expect
index 8a434a8..03a3204 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_set_field.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_set_field.dart.expect
@@ -1,65 +1,65 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
class T1 extends core::Object {
- synthetic constructor •() → self::T1*
+ synthetic constructor •() → self::T1
: super core::Object::•()
;
}
class T2 extends core::Object {
- synthetic constructor •() → self::T2*
+ synthetic constructor •() → self::T2
: super core::Object::•()
;
}
class A extends core::Object {
[@vm.inferred-type.metadata=#lib::T1] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] field dynamic field1;
[@vm.inferred-type.metadata=!] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] field dynamic field2;
- synthetic constructor •() → self::A*
+ synthetic constructor •() → self::A
: self::A::field1 = new self::T1::•(), self::A::field2 = new self::T1::•(), super core::Object::•()
;
}
class DeepCaller1 extends core::Object {
- synthetic constructor •() → self::DeepCaller1*
+ synthetic constructor •() → self::DeepCaller1
: super core::Object::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] method barL1([@vm.inferred-type.metadata=#lib::A?] self::A* aa) → dynamic
- return [@vm.direct-call.metadata=#lib::DeepCaller1.barL2] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::DeepCaller1::barL2}(aa){(self::A*) →* dynamic};
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] method barL2([@vm.inferred-type.metadata=#lib::A?] self::A* aa) → dynamic
- return [@vm.direct-call.metadata=#lib::DeepCaller1.barL3] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::DeepCaller1::barL3}(aa){(self::A*) →* dynamic};
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10] method barL3([@vm.inferred-type.metadata=#lib::A?] self::A* aa) → dynamic
- return [@vm.direct-call.metadata=#lib::DeepCaller1.barL4] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::DeepCaller1::barL4}(aa){(self::A*) →* dynamic};
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] method barL4([@vm.inferred-type.metadata=#lib::A?] self::A* aa) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] method barL1([@vm.inferred-type.metadata=#lib::A?] self::A aa) → dynamic
+ return [@vm.direct-call.metadata=#lib::DeepCaller1.barL2] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::DeepCaller1::barL2}(aa){(self::A) → dynamic};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] method barL2([@vm.inferred-type.metadata=#lib::A?] self::A aa) → dynamic
+ return [@vm.direct-call.metadata=#lib::DeepCaller1.barL3] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::DeepCaller1::barL3}(aa){(self::A) → dynamic};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10] method barL3([@vm.inferred-type.metadata=#lib::A?] self::A aa) → dynamic
+ return [@vm.direct-call.metadata=#lib::DeepCaller1.barL4] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::DeepCaller1::barL4}(aa){(self::A) → dynamic};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] method barL4([@vm.inferred-type.metadata=#lib::A?] self::A aa) → dynamic
return [@vm.direct-call.metadata=#lib::A.field1??] [@vm.inferred-type.metadata=#lib::T1] aa.{self::A::field1}{dynamic};
}
class DeepCaller2 extends core::Object {
- synthetic constructor •() → self::DeepCaller2*
+ synthetic constructor •() → self::DeepCaller2
: super core::Object::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14] method barL1([@vm.inferred-type.metadata=#lib::A?] self::A* aa) → dynamic
- return [@vm.direct-call.metadata=#lib::DeepCaller2.barL2] [@vm.inferred-type.metadata=! (skip check)] this.{self::DeepCaller2::barL2}(aa){(self::A*) →* dynamic};
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:15,getterSelectorId:16] method barL2([@vm.inferred-type.metadata=#lib::A?] self::A* aa) → dynamic
- return [@vm.direct-call.metadata=#lib::DeepCaller2.barL3] [@vm.inferred-type.metadata=! (skip check)] this.{self::DeepCaller2::barL3}(aa){(self::A*) →* dynamic};
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:17,getterSelectorId:18] method barL3([@vm.inferred-type.metadata=#lib::A?] self::A* aa) → dynamic
- return [@vm.direct-call.metadata=#lib::DeepCaller2.barL4] [@vm.inferred-type.metadata=! (skip check)] this.{self::DeepCaller2::barL4}(aa){(self::A*) →* dynamic};
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:19,getterSelectorId:20] method barL4([@vm.inferred-type.metadata=#lib::A?] self::A* aa) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14] method barL1([@vm.inferred-type.metadata=#lib::A?] self::A aa) → dynamic
+ return [@vm.direct-call.metadata=#lib::DeepCaller2.barL2] [@vm.inferred-type.metadata=! (skip check)] this.{self::DeepCaller2::barL2}(aa){(self::A) → dynamic};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:15,getterSelectorId:16] method barL2([@vm.inferred-type.metadata=#lib::A?] self::A aa) → dynamic
+ return [@vm.direct-call.metadata=#lib::DeepCaller2.barL3] [@vm.inferred-type.metadata=! (skip check)] this.{self::DeepCaller2::barL3}(aa){(self::A) → dynamic};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:17,getterSelectorId:18] method barL3([@vm.inferred-type.metadata=#lib::A?] self::A aa) → dynamic
+ return [@vm.direct-call.metadata=#lib::DeepCaller2.barL4] [@vm.inferred-type.metadata=! (skip check)] this.{self::DeepCaller2::barL4}(aa){(self::A) → dynamic};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:19,getterSelectorId:20] method barL4([@vm.inferred-type.metadata=#lib::A?] self::A aa) → dynamic
return [@vm.direct-call.metadata=#lib::A.field2??] [@vm.inferred-type.metadata=!] aa.{self::A::field2}{dynamic};
}
-[@vm.inferred-type.metadata=dart.core::Null? (value: null)]static field core::Function* unknown;
-static method use1([@vm.inferred-type.metadata=#lib::DeepCaller1] self::DeepCaller1* x, [@vm.inferred-type.metadata=#lib::A?] self::A* aa) → dynamic
- return [@vm.direct-call.metadata=#lib::DeepCaller1.barL1] [@vm.inferred-type.metadata=#lib::T1 (skip check)] x.{self::DeepCaller1::barL1}(aa){(self::A*) →* dynamic};
-static method use2([@vm.inferred-type.metadata=#lib::DeepCaller2] self::DeepCaller2* x, [@vm.inferred-type.metadata=#lib::A?] self::A* aa) → dynamic
- return [@vm.direct-call.metadata=#lib::DeepCaller2.barL1] [@vm.inferred-type.metadata=! (skip check)] x.{self::DeepCaller2::barL1}(aa){(self::A*) →* dynamic};
+[@vm.inferred-type.metadata=!]late static field core::Function unknown;
+static method use1([@vm.inferred-type.metadata=#lib::DeepCaller1] self::DeepCaller1 x, [@vm.inferred-type.metadata=#lib::A?] self::A aa) → dynamic
+ return [@vm.direct-call.metadata=#lib::DeepCaller1.barL1] [@vm.inferred-type.metadata=#lib::T1 (skip check)] x.{self::DeepCaller1::barL1}(aa){(self::A) → dynamic};
+static method use2([@vm.inferred-type.metadata=#lib::DeepCaller2] self::DeepCaller2 x, [@vm.inferred-type.metadata=#lib::A?] self::A aa) → dynamic
+ return [@vm.direct-call.metadata=#lib::DeepCaller2.barL1] [@vm.inferred-type.metadata=! (skip check)] x.{self::DeepCaller2::barL1}(aa){(self::A) → dynamic};
static method getDynamic() → dynamic
return self::unknown();
-static method setField2([@vm.inferred-type.metadata=#lib::A] self::A* aa, [@vm.inferred-type.metadata=#lib::T2] dynamic value) → void {
+static method setField2([@vm.inferred-type.metadata=#lib::A] self::A aa, [@vm.inferred-type.metadata=#lib::T2] dynamic value) → void {
[@vm.direct-call.metadata=#lib::A.field2] [@vm.inferred-type.metadata=!? (skip check)] aa.{self::A::field2} = value;
}
-static method main(core::List<core::String*>* args) → dynamic {
+static method main(core::List<core::String> args) → dynamic {
new self::A::•();
new self::T1::•();
new self::T2::•();
- self::use1(new self::DeepCaller1::•(), self::getDynamic() as{TypeError,ForDynamic} self::A*);
- self::use2(new self::DeepCaller2::•(), self::getDynamic() as{TypeError,ForDynamic} self::A*);
+ self::use1(new self::DeepCaller1::•(), self::getDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} self::A);
+ self::use2(new self::DeepCaller2::•(), self::getDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} self::A);
self::setField2(new self::A::•(), new self::T2::•());
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_set_field2.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_set_field2.dart.expect
index ffc08fe..918c5ae 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_set_field2.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_set_field2.dart.expect
@@ -1,43 +1,43 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
class T1 extends core::Object {
- synthetic constructor •() → self::T1*
+ synthetic constructor •() → self::T1
: super core::Object::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method go() → self::T3*
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method go() → self::T3
return new self::T3::•();
}
class T2 extends core::Object {
- synthetic constructor •() → self::T2*
+ synthetic constructor •() → self::T2
: super core::Object::•()
;
}
class T3 extends core::Object {
- synthetic constructor •() → self::T3*
+ synthetic constructor •() → self::T3
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] method run() → dynamic {
core::print("hi");
}
}
-class Q<T extends core::Object* = dynamic> extends core::Object {
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:5] final field self::Q::T* result;
- constructor •(self::Q::T* result) → self::Q<self::Q::T*>*
+class Q<T extends core::Object? = dynamic> extends core::Object {
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:5] final field self::Q::T% result;
+ constructor •(self::Q::T% result) → self::Q<self::Q::T%>
: self::Q::result = result, super core::Object::•()
;
}
-static method foo1([@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::T1*>] core::List<self::T1*>* list) → dynamic {
- [@vm.direct-call.metadata=#lib::T3.run] [@vm.inferred-type.metadata=!? (skip check)] [@vm.direct-call.metadata=#lib::T1.go??] [@vm.inferred-type.metadata=#lib::T3 (skip check)] [@vm.direct-call.metadata=#lib::Q.result??] [@vm.direct-call.metadata=dart._internal::ListIterable.first] [@vm.inferred-type.metadata=#lib::Q?] [@vm.direct-call.metadata=dart.collection::_ListBase&Object&ListMixin.map] [@vm.inferred-type.metadata=dart._internal::MappedListIterable<#lib::T1*, ?> (skip check)] list.{core::Iterable::map}<self::Q<self::T1*>*>((self::T1* t1) → self::Q<self::T1*>* => new self::Q::•<self::T1*>(t1)){((self::T1*) →* self::Q<self::T1*>*) →* core::Iterable<self::Q<self::T1*>*>*}.{core::Iterable::first}{self::Q<self::T1*>*}.{self::Q::result}{self::T1*}.{self::T1::go}(){() →* self::T3*}.{self::T3::run}(){() →* dynamic};
+static method foo1([@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::T1>] core::List<self::T1> list) → dynamic {
+ [@vm.direct-call.metadata=#lib::T3.run] [@vm.inferred-type.metadata=!? (skip check)] [@vm.direct-call.metadata=#lib::T1.go??] [@vm.inferred-type.metadata=#lib::T3 (skip check)] [@vm.direct-call.metadata=#lib::Q.result??] [@vm.direct-call.metadata=dart._internal::ListIterable.first] [@vm.inferred-type.metadata=#lib::Q?] [@vm.direct-call.metadata=dart.collection::_ListBase&Object&ListMixin.map] [@vm.inferred-type.metadata=dart._internal::MappedListIterable<#lib::T1, ?> (skip check)] list.{core::Iterable::map}<self::Q<self::T1>>((self::T1 t1) → self::Q<self::T1> => new self::Q::•<self::T1>(t1)){((self::T1) → self::Q<self::T1>) → core::Iterable<self::Q<self::T1>>}.{core::Iterable::first}{self::Q<self::T1>}.{self::Q::result}{self::T1}.{self::T1::go}(){() → self::T3}.{self::T3::run}(){() → dynamic};
}
-static method foo2NewValue() → self::Q<dynamic>*
- return new self::Q::•<self::T2*>(new self::T2::•());
+static method foo2NewValue() → self::Q<dynamic>
+ return new self::Q::•<self::T2>(new self::T2::•());
static method foo3NewT1() → dynamic {
new self::T1::•();
}
-static method main(core::List<core::String*>* args) → dynamic {
- self::foo1([@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::T1*>] core::_GrowableList::•<self::T1*>(0));
+static method main(core::List<core::String> args) → dynamic {
+ self::foo1([@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::T1>] core::_GrowableList::•<self::T1>(0));
self::foo2NewValue();
self::foo3NewT1();
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_while_processing.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_while_processing.dart.expect
index 74df479..84447db 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_while_processing.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_while_processing.dart.expect
@@ -1,4 +1,4 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
@@ -6,35 +6,35 @@
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] abstract method foo() → void;
}
class T1 extends core::Object implements self::I {
- synthetic constructor •() → self::T1*
+ synthetic constructor •() → self::T1
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method foo() → void {}
}
class T2 extends core::Object implements self::I {
- synthetic constructor •() → self::T2*
+ synthetic constructor •() → self::T2
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method foo() → void {}
}
class Point extends core::Object /*hasConstConstructor*/ {
-[@vm.inferred-type.metadata=!] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3] final field self::I* x;
- const constructor •([@vm.inferred-type.metadata=!] self::I* x) → self::Point*
+[@vm.inferred-type.metadata=!] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3] final field self::I x;
+ const constructor •([@vm.inferred-type.metadata=!] self::I x) → self::Point
: self::Point::x = x, super core::Object::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5] method newPoint1() → self::Point*
- return new self::Point::•([@vm.direct-call.metadata=#lib::Point.x] [@vm.inferred-type.metadata=!] this.{self::Point::x}{self::I*});
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7] method newPoint2() → self::Point*
- return new self::Point::•([@vm.direct-call.metadata=#lib::Point.x] [@vm.inferred-type.metadata=!] this.{self::Point::x}{self::I*});
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5] method newPoint1() → self::Point
+ return new self::Point::•([@vm.direct-call.metadata=#lib::Point.x] [@vm.inferred-type.metadata=!] this.{self::Point::x}{self::I});
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7] method newPoint2() → self::Point
+ return new self::Point::•([@vm.direct-call.metadata=#lib::Point.x] [@vm.inferred-type.metadata=!] this.{self::Point::x}{self::I});
}
static method getX([@vm.inferred-type.metadata=#lib::Point] dynamic point) → dynamic {
[@vm.direct-call.metadata=#lib::Point.x] [@vm.inferred-type.metadata=!? (receiver not int)] point{dynamic}.x;
}
static method main() → dynamic {
- self::Point* a = new self::Point::•(new self::T1::•());
- core::print([@vm.direct-call.metadata=#lib::Point.x] [@vm.inferred-type.metadata=!] a.{self::Point::x}{self::I*});
- self::Point* c = new self::Point::•(new self::T2::•());
- [@vm.direct-call.metadata=#lib::Point.x] [@vm.inferred-type.metadata=!] c.{self::Point::x}{self::I*}.{self::I::foo}(){() →* void};
- self::getX([@vm.direct-call.metadata=#lib::Point.newPoint1] [@vm.inferred-type.metadata=#lib::Point (skip check)] a.{self::Point::newPoint1}(){() →* self::Point*});
- self::getX([@vm.direct-call.metadata=#lib::Point.newPoint2] [@vm.inferred-type.metadata=#lib::Point (skip check)] a.{self::Point::newPoint2}(){() →* self::Point*});
+ self::Point a = new self::Point::•(new self::T1::•());
+ core::print([@vm.direct-call.metadata=#lib::Point.x] [@vm.inferred-type.metadata=!] a.{self::Point::x}{self::I});
+ self::Point c = new self::Point::•(new self::T2::•());
+ [@vm.direct-call.metadata=#lib::Point.x] [@vm.inferred-type.metadata=!] c.{self::Point::x}{self::I}.{self::I::foo}(){() → void};
+ self::getX([@vm.direct-call.metadata=#lib::Point.newPoint1] [@vm.inferred-type.metadata=#lib::Point (skip check)] a.{self::Point::newPoint1}(){() → self::Point});
+ self::getX([@vm.direct-call.metadata=#lib::Point.newPoint2] [@vm.inferred-type.metadata=#lib::Point (skip check)] a.{self::Point::newPoint2}(){() → self::Point});
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/is_test_elimination_nnbd.dart b/pkg/vm/testcases/transformations/type_flow/transformer/is_test_elimination_nnbd.dart
new file mode 100644
index 0000000..723c228
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/is_test_elimination_nnbd.dart
@@ -0,0 +1,49 @@
+// 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.
+
+// Tests elimination of 'is' tests.
+
+class A {}
+
+class B extends A {
+ void foo() {
+ print('foo');
+ }
+
+ bool get bar => int.parse('1') == 1;
+}
+
+class C implements A {}
+
+A obj = int.parse('2') == 2 ? C() : A();
+A getObj() => obj;
+
+void test1() {
+ var x = getObj();
+ if (x is B) {
+ x.foo();
+ }
+}
+
+void test2(x) {
+ if (x is B && x.bar) {
+ print('bye');
+ }
+}
+
+void test3(x) {
+ if (x is! B) {
+ return;
+ }
+ print('bye');
+}
+
+test4() => (getObj() is B) ? 3 : 4;
+
+void main() {
+ test1();
+ test2(obj);
+ test3(obj);
+ test4();
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/is_test_elimination_nnbd.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/is_test_elimination_nnbd.dart.expect
new file mode 100644
index 0000000..3af08e0
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/is_test_elimination_nnbd.dart.expect
@@ -0,0 +1,40 @@
+library #lib /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ synthetic constructor •() → self::A
+ : super core::Object::•()
+ ;
+}
+class C extends core::Object implements self::A {
+ synthetic constructor •() → self::C
+ : super core::Object::•()
+ ;
+}
+static field self::A obj = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("2") =={core::num::==}{(core::Object) → core::bool} 2 ?{self::A} new self::C::•() : new self::A::•();
+static method getObj() → self::A
+ return self::obj;
+static method test1() → void {
+ self::A x = self::getObj();
+ ;
+}
+static method test2() → void {
+ ;
+}
+static method test3() → void {
+ {
+ return;
+ }
+ core::print("bye");
+}
+[@vm.unboxing-info.metadata=()->i]static method test4() → dynamic
+ return block {
+ self::getObj();
+ } =>4;
+static method main() → void {
+ self::test1();
+ let final self::A #t1 = self::obj in self::test2();
+ let final self::A #t2 = self::obj in self::test3();
+ self::test4();
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/lists.dart b/pkg/vm/testcases/transformations/type_flow/transformer/lists_legacy.dart
similarity index 96%
rename from pkg/vm/testcases/transformations/type_flow/transformer/lists.dart
rename to pkg/vm/testcases/transformations/type_flow/transformer/lists_legacy.dart
index 62e1f09..dcd8253 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/lists.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/lists_legacy.dart
@@ -2,6 +2,9 @@
// 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 needs pre-null-safety semantics.
+// @dart=2.9
+
nonConstant() => int.parse('1') == 1;
class A {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/lists.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/lists_legacy.dart.expect
similarity index 100%
rename from pkg/vm/testcases/transformations/type_flow/transformer/lists.dart.expect
rename to pkg/vm/testcases/transformations/type_flow/transformer/lists_legacy.dart.expect
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/lists_nnbd.dart b/pkg/vm/testcases/transformations/type_flow/transformer/lists_nnbd.dart
index 76fafab..82f93e6 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/lists_nnbd.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/lists_nnbd.dart
@@ -2,9 +2,6 @@
// 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 requires non-nullable experiment.
-// @dart = 2.10
-
nonConstant() => int.parse('1') == 1;
class A {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/named_params_shaking_test.dart b/pkg/vm/testcases/transformations/type_flow/transformer/named_params_shaking_test.dart
index b941651..d2bc22a 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/named_params_shaking_test.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/named_params_shaking_test.dart
@@ -15,7 +15,7 @@
// When converting named parameters to positional parameters, we
// follow alphabetical order. Ensure that argument evaluation order
// is unchanged.
-void testNamedOrder(int w, {int z, int y, int x}) {
+void testNamedOrder(int w, {int? z, int? y, int? x}) {
Expect.equals(w, 1);
Expect.equals(z, 2);
Expect.equals(y, 3);
@@ -23,7 +23,7 @@
}
class TestNamedOrderBase {
- TestNamedOrderBase(w, {int z, int y, int x}) {
+ TestNamedOrderBase(w, {int? z, int? y, int? x}) {
testNamedOrder(w, z: z, y: y, x: x);
}
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/named_params_shaking_test.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/named_params_shaking_test.dart.expect
index fda4bf2..76840f2 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/named_params_shaking_test.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/named_params_shaking_test.dart.expect
@@ -1,4 +1,4 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
import "dart:_internal" as _in;
@@ -9,31 +9,31 @@
import "package:expect/expect.dart";
abstract class TestNamedOrderBase extends core::Object {
-[@vm.unboxing-info.metadata=(i,i,i,i)->b] constructor •([@vm.inferred-type.metadata=int] dynamic w, [@vm.inferred-type.metadata=int] core::int* x, [@vm.inferred-type.metadata=int] core::int* y, [@vm.inferred-type.metadata=int] core::int* z) → self::TestNamedOrderBase*
+[@vm.unboxing-info.metadata=(i,i,i,i)->b] constructor •([@vm.inferred-type.metadata=int] dynamic w, [@vm.inferred-type.metadata=int] core::int? x, [@vm.inferred-type.metadata=int] core::int? y, [@vm.inferred-type.metadata=int] core::int? z) → self::TestNamedOrderBase
: super core::Object::•() {
- self::testNamedOrder(_in::unsafeCast<core::int*>(w), x, y, z);
+ self::testNamedOrder(_in::unsafeCast<core::int>(w), x, y, z);
}
}
class TestNamedOrderSub extends self::TestNamedOrderBase {
-[@vm.inferred-type.metadata=int] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=(i)->i] field core::int* x;
- constructor •() → self::TestNamedOrderSub*
- : self::TestNamedOrderSub::x = [@vm.inferred-type.metadata=int] self::dec(), final core::int* #t1 = [@vm.inferred-type.metadata=int] self::inc(), final core::int* #t2 = [@vm.inferred-type.metadata=int] self::inc(), final core::int* #t3 = [@vm.inferred-type.metadata=int] self::inc(), final core::int* #t4 = [@vm.inferred-type.metadata=int] self::dec(), super self::TestNamedOrderBase::•(#t1, #t4, #t3, #t2) {
- exp::Expect::equals([@vm.direct-call.metadata=#lib::TestNamedOrderSub.x] [@vm.inferred-type.metadata=int] this.{self::TestNamedOrderSub::x}{core::int*}, 0);
+[@vm.inferred-type.metadata=int] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=(i)->i] field core::int x;
+ constructor •() → self::TestNamedOrderSub
+ : self::TestNamedOrderSub::x = [@vm.inferred-type.metadata=int] self::dec(), final core::int #t1 = [@vm.inferred-type.metadata=int] self::inc(), final core::int #t2 = [@vm.inferred-type.metadata=int] self::inc(), final core::int #t3 = [@vm.inferred-type.metadata=int] self::inc(), final core::int #t4 = [@vm.inferred-type.metadata=int] self::dec(), super self::TestNamedOrderBase::•(#t1, #t4, #t3, #t2) {
+ exp::Expect::equals([@vm.direct-call.metadata=#lib::TestNamedOrderSub.x] [@vm.inferred-type.metadata=int] this.{self::TestNamedOrderSub::x}{core::int}, 0);
}
}
-[@vm.inferred-type.metadata=int?]static field core::int* global = 0;
-[@vm.unboxing-info.metadata=()->i]static method inc() → core::int*
- return self::global = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+??] [@vm.inferred-type.metadata=int (skip check)] [@vm.inferred-type.metadata=int?] self::global.{core::num::+}(1){(core::num*) →* core::int*};
-[@vm.unboxing-info.metadata=()->i]static method dec() → core::int*
- return self::global = [@vm.inferred-type.metadata=int] math::max<core::int*>(0, self::global = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.-??] [@vm.inferred-type.metadata=int (skip check)] [@vm.inferred-type.metadata=int?] self::global.{core::num::-}(1){(core::num*) →* core::int*});
-[@vm.unboxing-info.metadata=(i,i,i,i)->b]static method testNamedOrder([@vm.inferred-type.metadata=int] core::int* w, [@vm.inferred-type.metadata=int] core::int* x, [@vm.inferred-type.metadata=int] core::int* y, [@vm.inferred-type.metadata=int] core::int* z) → void {
+[@vm.inferred-type.metadata=int?]static field core::int global = 0;
+[@vm.unboxing-info.metadata=()->i]static method inc() → core::int
+ return self::global = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+??] [@vm.inferred-type.metadata=int (skip check)] [@vm.inferred-type.metadata=int?] self::global.{core::num::+}(1){(core::num) → core::int};
+[@vm.unboxing-info.metadata=()->i]static method dec() → core::int
+ return self::global = [@vm.inferred-type.metadata=int] math::max<core::int>(0, self::global = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.-??] [@vm.inferred-type.metadata=int (skip check)] [@vm.inferred-type.metadata=int?] self::global.{core::num::-}(1){(core::num) → core::int});
+[@vm.unboxing-info.metadata=(i,i,i,i)->b]static method testNamedOrder([@vm.inferred-type.metadata=int] core::int w, [@vm.inferred-type.metadata=int] core::int? x, [@vm.inferred-type.metadata=int] core::int? y, [@vm.inferred-type.metadata=int] core::int? z) → void {
exp::Expect::equals(w, 1);
exp::Expect::equals(z, 2);
exp::Expect::equals(y, 3);
exp::Expect::equals(x, 2);
}
static method main() → dynamic {
- let final core::int* #t5 = [@vm.inferred-type.metadata=int] self::inc() in let final core::int* #t6 = [@vm.inferred-type.metadata=int] self::inc() in let final core::int* #t7 = [@vm.inferred-type.metadata=int] self::inc() in let final core::int* #t8 = [@vm.inferred-type.metadata=int] self::dec() in self::testNamedOrder(#t5, #t8, #t7, #t6);
+ let final core::int #t5 = [@vm.inferred-type.metadata=int] self::inc() in let final core::int #t6 = [@vm.inferred-type.metadata=int] self::inc() in let final core::int #t7 = [@vm.inferred-type.metadata=int] self::inc() in let final core::int #t8 = [@vm.inferred-type.metadata=int] self::dec() in self::testNamedOrder(#t5, #t8, #t7, #t6);
self::global = 1;
new self::TestNamedOrderSub::•();
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/no_such_method.dart b/pkg/vm/testcases/transformations/type_flow/transformer/no_such_method.dart
index a85118e..a3c4741 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/no_such_method.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/no_such_method.dart
@@ -69,7 +69,7 @@
A bb = new B();
A dd = new D();
-Function unknown;
+late Function unknown;
getDynamic() => unknown.call();
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 719f96e..657e7ba 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
@@ -1,40 +1,40 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
import "dart:_internal" as _in;
class T1 extends core::Object {
- synthetic constructor •() → self::T1*
+ synthetic constructor •() → self::T1
: super core::Object::•()
;
}
class T2 extends core::Object {
- synthetic constructor •() → self::T2*
+ synthetic constructor •() → self::T2
: super core::Object::•()
;
}
class T4 extends core::Object {
- synthetic constructor •() → self::T4*
+ synthetic constructor •() → self::T4
: super core::Object::•()
;
}
class T5 extends core::Object {
- synthetic constructor •() → self::T5*
+ synthetic constructor •() → self::T5
: super core::Object::•()
;
}
class T6 extends core::Object {
- synthetic constructor •() → self::T6*
+ synthetic constructor •() → self::T6
: super core::Object::•()
;
}
class T7 extends core::Object {
- synthetic constructor •() → self::T7*
+ synthetic constructor •() → self::T7
: super core::Object::•()
;
}
abstract class A extends core::Object {
- synthetic constructor •() → self::A*
+ synthetic constructor •() → self::A
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] abstract method foo() → dynamic;
@@ -42,88 +42,88 @@
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5] [@vm.unboxing-info.metadata=(i,i,i,i)->b] abstract method bazz(dynamic a1, dynamic a2, dynamic a3, dynamic a4) → dynamic;
}
class B extends self::A {
- synthetic constructor •() → self::B*
+ synthetic constructor •() → self::B
: super self::A::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7] method noSuchMethod(core::Invocation* invocation) → dynamic {
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7] method noSuchMethod(core::Invocation invocation) → dynamic {
return new self::T1::•();
}
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3] no-such-method-forwarder get bar() → dynamic
- return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::B.noSuchMethod] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation*) →* dynamic});
+ return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::B.noSuchMethod] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation) → dynamic});
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] no-such-method-forwarder method foo() → dynamic
- return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::B.noSuchMethod] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C2, #C3, [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation*) →* dynamic});
+ return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::B.noSuchMethod] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C2, #C3, [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation) → dynamic});
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5] [@vm.unboxing-info.metadata=(i,i,i,i)->b] no-such-method-forwarder method bazz([@vm.inferred-type.metadata=dart.core::_Smi (value: 1)] dynamic a1, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic a2, [@vm.inferred-type.metadata=dart.core::_Smi (value: 3)] dynamic a3, [@vm.inferred-type.metadata=dart.core::_Smi (value: 4)] dynamic a4) → dynamic
- return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::B.noSuchMethod] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C6, 0, #C2, core::List::unmodifiable<dynamic>([@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic>] core::_GrowableList::_literal5<dynamic>()), [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation*) →* dynamic});
+ return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::B.noSuchMethod] [@vm.inferred-type.metadata=#lib::T1 (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C6, 0, #C2, core::List::unmodifiable<dynamic>([@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic>] core::_GrowableList::_literal5<dynamic>()), [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation) → dynamic});
}
abstract class C extends core::Object {
- synthetic constructor •() → self::C*
+ synthetic constructor •() → self::C
: super core::Object::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7] method noSuchMethod(core::Invocation* invocation) → dynamic {
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7] method noSuchMethod(core::Invocation invocation) → dynamic {
return new self::T2::•();
}
}
class D extends self::C implements self::A {
- synthetic constructor •() → self::D*
+ synthetic constructor •() → self::D
: super self::C::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3] no-such-method-forwarder get bar() → dynamic
- return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::C.noSuchMethod] [@vm.inferred-type.metadata=#lib::T2 (skip check)] this.{self::C::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation*) →* dynamic});
+ return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::C.noSuchMethod] [@vm.inferred-type.metadata=#lib::T2 (skip check)] this.{self::C::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation) → dynamic});
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] no-such-method-forwarder method foo() → dynamic
- return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::C.noSuchMethod] [@vm.inferred-type.metadata=#lib::T2 (skip check)] this.{self::C::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C2, #C3, [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation*) →* dynamic});
+ return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::C.noSuchMethod] [@vm.inferred-type.metadata=#lib::T2 (skip check)] this.{self::C::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C2, #C3, [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation) → dynamic});
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5] [@vm.unboxing-info.metadata=(i,i,i,i)->b] no-such-method-forwarder method bazz([@vm.inferred-type.metadata=dart.core::_Smi (value: 1)] dynamic a1, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic a2, [@vm.inferred-type.metadata=dart.core::_Smi (value: 3)] dynamic a3, [@vm.inferred-type.metadata=dart.core::_Smi (value: 4)] dynamic a4) → dynamic
- return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::C.noSuchMethod] [@vm.inferred-type.metadata=#lib::T2 (skip check)] this.{self::C::noSuchMethod}(new core::_InvocationMirror::_withType(#C6, 0, #C2, core::List::unmodifiable<dynamic>([@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic>] core::_GrowableList::_literal5<dynamic>()), [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation*) →* dynamic});
+ return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::C.noSuchMethod] [@vm.inferred-type.metadata=#lib::T2 (skip check)] this.{self::C::noSuchMethod}(new core::_InvocationMirror::_withType(#C6, 0, #C2, core::List::unmodifiable<dynamic>([@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic>] core::_GrowableList::_literal5<dynamic>()), [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation) → dynamic});
}
class E extends core::Object implements self::A {
- synthetic constructor •() → self::E*
+ synthetic constructor •() → self::E
: super core::Object::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7] method noSuchMethod(core::Invocation* invocation) → dynamic {
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7] method noSuchMethod(core::Invocation invocation) → dynamic {
return new self::T4::•();
}
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3] no-such-method-forwarder get bar() → dynamic
- return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::E.noSuchMethod] [@vm.inferred-type.metadata=#lib::T4 (skip check)] this.{self::E::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation*) →* dynamic});
+ return _in::unsafeCast<dynamic>([@vm.direct-call.metadata=#lib::E.noSuchMethod] [@vm.inferred-type.metadata=#lib::T4 (skip check)] this.{self::E::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))){(core::Invocation) → dynamic});
}
class F extends core::Object {
- synthetic constructor •() → self::F*
+ synthetic constructor •() → self::F
: super core::Object::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7] method noSuchMethod(core::Invocation* invocation) → dynamic {
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7] method noSuchMethod(core::Invocation invocation) → dynamic {
return new self::T2::•();
}
}
class G extends core::Object {
- synthetic constructor •() → self::G*
+ synthetic constructor •() → self::G
: super core::Object::•()
;
-[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7] method noSuchMethod(core::Invocation* invocation) → dynamic {
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7] method noSuchMethod(core::Invocation invocation) → dynamic {
return new self::T5::•();
}
}
class H extends core::Object {
- synthetic constructor •() → self::H*
+ synthetic constructor •() → self::H
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:8,getterSelectorId:9] method foo({[@vm.inferred-type.metadata=dart.core::_Smi (value: 1)] dynamic left = #C7, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic right = #C7}) → dynamic
return new self::T6::•();
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7] method noSuchMethod(core::Invocation* invocation) → dynamic {
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7] method noSuchMethod(core::Invocation invocation) → dynamic {
return new self::T7::•();
}
}
-[@vm.inferred-type.metadata=#lib::B?]static field self::A* bb = new self::B::•();
-[@vm.inferred-type.metadata=#lib::D?]static field self::A* dd = new self::D::•();
-[@vm.inferred-type.metadata=dart.core::Null? (value: null)]static field core::Function* unknown;
+[@vm.inferred-type.metadata=#lib::B?]static field self::A bb = new self::B::•();
+[@vm.inferred-type.metadata=#lib::D?]static field self::A dd = new self::D::•();
+[@vm.inferred-type.metadata=!]late static field core::Function unknown;
static method getDynamic() → dynamic
return self::unknown();
-static method main(core::List<core::String*>* args) → dynamic {
- core::print([@vm.direct-call.metadata=#lib::B.foo??] [@vm.inferred-type.metadata=#lib::T1 (skip check)] [@vm.inferred-type.metadata=#lib::B?] self::bb.{self::A::foo}(){() →* dynamic});
+static method main(core::List<core::String> args) → dynamic {
+ core::print([@vm.direct-call.metadata=#lib::B.foo??] [@vm.inferred-type.metadata=#lib::T1 (skip check)] [@vm.inferred-type.metadata=#lib::B?] self::bb.{self::A::foo}(){() → dynamic});
core::print([@vm.direct-call.metadata=#lib::B.bar??] [@vm.inferred-type.metadata=#lib::T1] [@vm.inferred-type.metadata=#lib::B?] self::bb.{self::A::bar}{dynamic});
- core::print([@vm.direct-call.metadata=#lib::B.bazz??] [@vm.inferred-type.metadata=#lib::T1 (skip check)] [@vm.inferred-type.metadata=#lib::B?] self::bb.{self::A::bazz}(1, 2, 3, 4){(dynamic, dynamic, dynamic, [dynamic, dynamic]) →* dynamic});
- core::print([@vm.direct-call.metadata=#lib::D.foo??] [@vm.inferred-type.metadata=#lib::T2 (skip check)] [@vm.inferred-type.metadata=#lib::D?] self::dd.{self::A::foo}(){() →* dynamic});
+ core::print([@vm.direct-call.metadata=#lib::B.bazz??] [@vm.inferred-type.metadata=#lib::T1 (skip check)] [@vm.inferred-type.metadata=#lib::B?] self::bb.{self::A::bazz}(1, 2, 3, 4){(dynamic, dynamic, dynamic, [dynamic, dynamic]) → dynamic});
+ core::print([@vm.direct-call.metadata=#lib::D.foo??] [@vm.inferred-type.metadata=#lib::T2 (skip check)] [@vm.inferred-type.metadata=#lib::D?] self::dd.{self::A::foo}(){() → dynamic});
core::print([@vm.direct-call.metadata=#lib::D.bar??] [@vm.inferred-type.metadata=#lib::T2] [@vm.inferred-type.metadata=#lib::D?] self::dd.{self::A::bar}{dynamic});
- core::print([@vm.direct-call.metadata=#lib::D.bazz??] [@vm.inferred-type.metadata=#lib::T2 (skip check)] [@vm.inferred-type.metadata=#lib::D?] self::dd.{self::A::bazz}(1, 2, 3, 4){(dynamic, dynamic, dynamic, [dynamic, dynamic]) →* dynamic});
+ core::print([@vm.direct-call.metadata=#lib::D.bazz??] [@vm.inferred-type.metadata=#lib::T2 (skip check)] [@vm.inferred-type.metadata=#lib::D?] self::dd.{self::A::bazz}(1, 2, 3, 4){(dynamic, dynamic, dynamic, [dynamic, dynamic]) → dynamic});
new self::E::•();
- self::A* xx = self::getDynamic() as{TypeError,ForDynamic} self::A*;
+ self::A xx = self::getDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} self::A;
core::print([@vm.inferred-type.metadata=!] xx.{self::A::bar}{dynamic});
dynamic yy = self::getDynamic();
core::print([@vm.inferred-type.metadata=!] yy{dynamic}.twoArg(1, 2, 3));
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/null_check_elimination_nnbd.dart b/pkg/vm/testcases/transformations/type_flow/transformer/null_check_elimination_nnbd.dart
index b529e22..016fff5 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/null_check_elimination_nnbd.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/null_check_elimination_nnbd.dart
@@ -3,9 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
// Tests elimination of null checks.
-// This test requires non-nullable experiment.
-
-// @dart = 2.10
class A {
String? nonNullable;
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/null_test_elimination.dart b/pkg/vm/testcases/transformations/type_flow/transformer/null_test_elimination.dart
index 98488d3..e3f12b7 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/null_test_elimination.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/null_test_elimination.dart
@@ -5,9 +5,9 @@
// Tests elimination of null tests.
class A {
- String nonNullable;
- String nullable;
- String alwaysNull;
+ String? nonNullable;
+ String? nullable;
+ String? alwaysNull;
A({this.nonNullable, this.nullable, this.alwaysNull});
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/null_test_elimination.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/null_test_elimination.dart.expect
index 7e7de62..461ce24 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/null_test_elimination.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/null_test_elimination.dart.expect
@@ -1,61 +1,70 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
import "dart:_internal" as _in;
class A extends core::Object {
-[@vm.inferred-type.metadata=dart.core::_OneByteString] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] field core::String* nonNullable;
-[@vm.inferred-type.metadata=dart.core::_OneByteString?] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] field core::String* nullable;
-[@vm.inferred-type.metadata=dart.core::Null? (value: null)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] field core::String* alwaysNull;
- constructor •([@vm.inferred-type.metadata=dart.core::_OneByteString] core::String* nonNullable, [@vm.inferred-type.metadata=dart.core::_OneByteString?] core::String* nullable) → self::A*
+[@vm.inferred-type.metadata=dart.core::_OneByteString] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] field core::String? nonNullable;
+[@vm.inferred-type.metadata=dart.core::_OneByteString?] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] field core::String? nullable;
+[@vm.inferred-type.metadata=dart.core::Null? (value: null)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] field core::String? alwaysNull;
+ constructor •([@vm.inferred-type.metadata=dart.core::_OneByteString] core::String? nonNullable, [@vm.inferred-type.metadata=dart.core::_OneByteString?] core::String? nullable) → self::A
: self::A::nonNullable = nonNullable, self::A::nullable = nullable, self::A::alwaysNull = #C1, super core::Object::•()
;
}
-[@vm.inferred-type.metadata=#lib::A?]static field self::A* staticField = new self::A::•("hi", "bye");
-static method testNonNullableIf1([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic {
- if(let dynamic #t1 = [@vm.direct-call.metadata=#lib::A.nonNullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString] a.{self::A::nonNullable}{core::String*} in false) {
- core::print("null");
- }
-}
-static method testNullableIf1([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic {
- if([@vm.direct-call.metadata=#lib::A.nullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString?] a.{self::A::nullable}{core::String*} == null) {
- core::print("null");
- }
-}
-static method testAlwaysNullIf1([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic {
- if(let dynamic #t2 = [@vm.direct-call.metadata=#lib::A.alwaysNull??] [@vm.inferred-type.metadata=dart.core::Null? (value: null)] a.{self::A::alwaysNull}{core::String*} in true) {
- core::print("null");
- }
-}
-static method testNonNullableIf2([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic {
- if(!(let dynamic #t3 = [@vm.direct-call.metadata=#lib::A.nonNullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString] a.{self::A::nonNullable}{core::String*} in false) && _in::unsafeCast<core::bool*>([@vm.inferred-type.metadata=dart.core::bool] self::someCondition())) {
- core::print("not null");
- }
-}
-static method testNullableIf2([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic {
- if(!([@vm.direct-call.metadata=#lib::A.nullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString?] a.{self::A::nullable}{core::String*} == null) && _in::unsafeCast<core::bool*>([@vm.inferred-type.metadata=dart.core::bool] self::someCondition())) {
- core::print("not null");
- }
-}
-static method testAlwaysNullIf2([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic {
- if(!(let dynamic #t4 = [@vm.direct-call.metadata=#lib::A.alwaysNull??] [@vm.inferred-type.metadata=dart.core::Null? (value: null)] a.{self::A::alwaysNull}{core::String*} in true) && _in::unsafeCast<core::bool*>([@vm.inferred-type.metadata=dart.core::bool] self::someCondition())) {
- core::print("not null");
- }
-}
-static method testNonNullableCondExpr([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic
- return !(let dynamic #t5 = [@vm.direct-call.metadata=#lib::A.nonNullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString] a.{self::A::nonNullable}{core::String*} in false) ?{core::String*} "not null" : "null";
-static method testNullableCondExpr([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic
- return !([@vm.direct-call.metadata=#lib::A.nullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString?] a.{self::A::nullable}{core::String*} == null) ?{core::String*} "not null" : "null";
-static method testAlwaysNullCondExpr([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic
- return !(let dynamic #t6 = [@vm.direct-call.metadata=#lib::A.alwaysNull??] [@vm.inferred-type.metadata=dart.core::Null? (value: null)] a.{self::A::alwaysNull}{core::String*} in true) ?{core::String*} "not null" : "null";
-static method someCondition() → dynamic
- return [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object*) →* core::bool*} 1;
-static method main() → void {
- final core::List<self::A*>* list = [@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::A*>] core::_GrowableList::_literal2<self::A*>(new self::A::•("foo", null), [@vm.inferred-type.metadata=#lib::A?] self::staticField);
+[@vm.inferred-type.metadata=#lib::A?]static field self::A staticField = new self::A::•("hi", "bye");
+static method testNonNullableIf1([@vm.inferred-type.metadata=#lib::A?] self::A a) → dynamic {
{
- core::Iterator<self::A*>* :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::A*>] list.{core::Iterable::iterator}{core::Iterator<self::A*>*};
+ [@vm.direct-call.metadata=#lib::A.nonNullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString] a.{self::A::nonNullable}{core::String?};
+ }
+}
+static method testNullableIf1([@vm.inferred-type.metadata=#lib::A?] self::A a) → dynamic {
+ if([@vm.direct-call.metadata=#lib::A.nullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString?] a.{self::A::nullable}{core::String?} == null) {
+ core::print("null");
+ }
+}
+static method testAlwaysNullIf1([@vm.inferred-type.metadata=#lib::A?] self::A a) → dynamic {
+ {
+ [@vm.direct-call.metadata=#lib::A.alwaysNull??] [@vm.inferred-type.metadata=dart.core::Null? (value: null)] a.{self::A::alwaysNull}{core::String?};
+ {
+ core::print("null");
+ }
+ }
+}
+static method testNonNullableIf2([@vm.inferred-type.metadata=#lib::A?] self::A a) → dynamic {
+ if(( block {
+ [@vm.direct-call.metadata=#lib::A.nonNullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString] a.{self::A::nonNullable}{core::String?};
+ } =>true) && _in::unsafeCast<core::bool>([@vm.inferred-type.metadata=dart.core::bool] self::someCondition())) {
+ core::print("not null");
+ }
+}
+static method testNullableIf2([@vm.inferred-type.metadata=#lib::A?] self::A a) → dynamic {
+ if(!([@vm.direct-call.metadata=#lib::A.nullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString?] a.{self::A::nullable}{core::String?} == null) && _in::unsafeCast<core::bool>([@vm.inferred-type.metadata=dart.core::bool] self::someCondition())) {
+ core::print("not null");
+ }
+}
+static method testAlwaysNullIf2([@vm.inferred-type.metadata=#lib::A?] self::A a) → dynamic {
+ {
+ [@vm.direct-call.metadata=#lib::A.alwaysNull??] [@vm.inferred-type.metadata=dart.core::Null? (value: null)] a.{self::A::alwaysNull}{core::String?};
+ }
+}
+static method testNonNullableCondExpr([@vm.inferred-type.metadata=#lib::A?] self::A a) → dynamic
+ return block {
+ [@vm.direct-call.metadata=#lib::A.nonNullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString] a.{self::A::nonNullable}{core::String?};
+ } =>"not null";
+static method testNullableCondExpr([@vm.inferred-type.metadata=#lib::A?] self::A a) → dynamic
+ return !([@vm.direct-call.metadata=#lib::A.nullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString?] a.{self::A::nullable}{core::String?} == null) ?{core::String} "not null" : "null";
+static method testAlwaysNullCondExpr([@vm.inferred-type.metadata=#lib::A?] self::A a) → dynamic
+ return block {
+ [@vm.direct-call.metadata=#lib::A.alwaysNull??] [@vm.inferred-type.metadata=dart.core::Null? (value: null)] a.{self::A::alwaysNull}{core::String?};
+ } =>"null";
+static method someCondition() → dynamic
+ return [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object) → core::bool} 1;
+static method main() → void {
+ final core::List<self::A> list = [@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::A>] core::_GrowableList::_literal2<self::A>(new self::A::•("foo", null), [@vm.inferred-type.metadata=#lib::A?] self::staticField);
+ {
+ core::Iterator<self::A> :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::A>] list.{core::Iterable::iterator}{core::Iterator<self::A>};
for (; [@vm.direct-call.metadata=dart._internal::ListIterator.moveNext] [@vm.inferred-type.metadata=dart.core::bool (skip check)] :sync-for-iterator.{core::Iterator::moveNext}(){() → core::bool}; ) {
- self::A* a = [@vm.direct-call.metadata=dart._internal::ListIterator.current] [@vm.inferred-type.metadata=#lib::A?] :sync-for-iterator.{core::Iterator::current}{self::A*};
+ self::A a = [@vm.direct-call.metadata=dart._internal::ListIterator.current] [@vm.inferred-type.metadata=#lib::A?] :sync-for-iterator.{core::Iterator::current}{self::A};
{
self::testNonNullableIf1(a);
self::testNullableIf1(a);
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/param_types_before_strong_mode_checks.dart b/pkg/vm/testcases/transformations/type_flow/transformer/param_types_before_strong_mode_checks.dart
index b60d23b..1d07acd 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/param_types_before_strong_mode_checks.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/param_types_before_strong_mode_checks.dart
@@ -54,7 +54,7 @@
}
}
-Function unknown;
+late Function unknown;
getDynamic() => unknown.call();
use(x) => unknown.call(x);
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/param_types_before_strong_mode_checks.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/param_types_before_strong_mode_checks.dart.expect
index 90996865..57eda05 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/param_types_before_strong_mode_checks.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/param_types_before_strong_mode_checks.dart.expect
@@ -1,63 +1,63 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
abstract class T0 extends core::Object {
- synthetic constructor •() → self::T0*
+ synthetic constructor •() → self::T0
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] abstract method foo() → void;
}
class T2 extends self::T0 {
- synthetic constructor •() → self::T2*
+ synthetic constructor •() → self::T2
: super self::T0::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method foo() → void {}
}
class A extends core::Object {
- synthetic constructor •() → self::A*
+ synthetic constructor •() → self::A
: super core::Object::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] method method1(self::T0* t0) → void {
- [@vm.direct-call.metadata=#lib::T2.foo??] [@vm.inferred-type.metadata=!? (skip check)] t0.{self::T0::foo}(){() →* void};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] method method1(self::T0 t0) → void {
+ [@vm.direct-call.metadata=#lib::T2.foo??] [@vm.inferred-type.metadata=!? (skip check)] t0.{self::T0::foo}(){() → void};
}
}
abstract class B extends core::Object {
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] abstract method method2(covariant dynamic arg) → void;
}
class C extends core::Object implements self::B {
- synthetic constructor •() → self::C*
+ synthetic constructor •() → self::C
: super core::Object::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] method method2(covariant self::T0* t0) → void {
- [@vm.direct-call.metadata=#lib::T2.foo??] [@vm.inferred-type.metadata=!? (skip check)] t0.{self::T0::foo}(){() →* void};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] method method2(covariant self::T0 t0) → void {
+ [@vm.direct-call.metadata=#lib::T2.foo??] [@vm.inferred-type.metadata=!? (skip check)] t0.{self::T0::foo}(){() → void};
}
}
class D extends core::Object {
- synthetic constructor •() → self::D*
+ synthetic constructor •() → self::D
: super core::Object::•()
;
-[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] method method3(self::T0* t0) → void {
- [@vm.direct-call.metadata=#lib::T2.foo??] [@vm.inferred-type.metadata=!? (skip check)] t0.{self::T0::foo}(){() →* void};
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] method method3(self::T0 t0) → void {
+ [@vm.direct-call.metadata=#lib::T2.foo??] [@vm.inferred-type.metadata=!? (skip check)] t0.{self::T0::foo}(){() → void};
}
}
-[@vm.inferred-type.metadata=dart.core::Null? (value: null)]static field core::Function* unknown;
-static method func1([@vm.inferred-type.metadata=#lib::T2?] self::T0* t0) → void {
- [@vm.direct-call.metadata=#lib::T2.foo??] [@vm.inferred-type.metadata=!? (skip check)] t0.{self::T0::foo}(){() →* void};
+[@vm.inferred-type.metadata=!]late static field core::Function unknown;
+static method func1([@vm.inferred-type.metadata=#lib::T2?] self::T0 t0) → void {
+ [@vm.direct-call.metadata=#lib::T2.foo??] [@vm.inferred-type.metadata=!? (skip check)] t0.{self::T0::foo}(){() → void};
}
-static method func2(self::T0* t0) → void {
- [@vm.direct-call.metadata=#lib::T2.foo??] [@vm.inferred-type.metadata=!? (skip check)] t0.{self::T0::foo}(){() →* void};
+static method func2(self::T0 t0) → void {
+ [@vm.direct-call.metadata=#lib::T2.foo??] [@vm.inferred-type.metadata=!? (skip check)] t0.{self::T0::foo}(){() → void};
}
static method getDynamic() → dynamic
return self::unknown();
static method use(dynamic x) → dynamic
return self::unknown(x);
-static method main(core::List<core::String*>* args) → dynamic {
- self::func1(self::getDynamic() as{TypeError,ForDynamic} self::T0*);
+static method main(core::List<core::String> args) → dynamic {
+ self::func1(self::getDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} self::T0);
self::use(#C1);
- self::use(new self::A::•().{self::A::method1}{(self::T0*) →* void});
- self::B* bb = self::getDynamic() as{TypeError,ForDynamic} self::B*;
- [@vm.direct-call.metadata=#lib::C.method2??] [@vm.inferred-type.metadata=!? (skip check)] bb.{self::B::method2}(self::getDynamic()){(dynamic) →* void};
+ self::use(new self::A::•().{self::A::method1}{(self::T0) → void});
+ self::B bb = self::getDynamic() as{TypeError,ForDynamic,ForNonNullableByDefault} self::B;
+ [@vm.direct-call.metadata=#lib::C.method2??] [@vm.inferred-type.metadata=!? (skip check)] bb.{self::B::method2}(self::getDynamic()){(dynamic) → void};
self::getDynamic(){dynamic}.method3(self::getDynamic());
new self::T2::•();
new self::A::•();
@@ -65,5 +65,5 @@
new self::D::•();
}
constants {
- #C1 = tearoff self::func2
+ #C1 = static-tearoff self::func2
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/pragmas.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/pragmas.dart.expect
index b832065..9578649 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/pragmas.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/pragmas.dart.expect
@@ -1,30 +1,30 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
class A extends core::Object /*hasConstConstructor*/ {
-[@vm.inferred-type.metadata=dart.core::_Smi (value: 10)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] [@vm.unboxing-info.metadata=()->i] final field core::int* x;
+[@vm.inferred-type.metadata=dart.core::_Smi (value: 10)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] [@vm.unboxing-info.metadata=()->i] final field core::int x;
}
class B extends core::Object /*hasConstConstructor*/ {
-[@vm.inferred-type.metadata=dart.core::_Smi (value: 11)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i] final field core::int* y;
+[@vm.inferred-type.metadata=dart.core::_Smi (value: 11)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i] final field core::int y;
}
class C extends core::Object /*hasConstConstructor*/ {
-[@vm.inferred-type.metadata=dart.core::_Smi (value: 12)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3] [@vm.unboxing-info.metadata=()->i] final field core::int* z;
+[@vm.inferred-type.metadata=dart.core::_Smi (value: 12)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3] [@vm.unboxing-info.metadata=()->i] final field core::int z;
}
@#C4
class Foo extends core::Object {
- synthetic constructor •() → self::Foo*
+ synthetic constructor •() → self::Foo
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5] @#C13
method bar() → void {
@#C17
function bazz() → void {}
- bazz(){() →* void};
+ bazz(){() → void};
}
}
static method main() → dynamic {
- [@vm.direct-call.metadata=#lib::Foo.bar] [@vm.inferred-type.metadata=!? (skip check)] new self::Foo::•().{self::Foo::bar}(){() →* void};
+ [@vm.direct-call.metadata=#lib::Foo.bar] [@vm.inferred-type.metadata=!? (skip check)] new self::Foo::•().{self::Foo::bar}(){() → void};
}
constants {
#C1 = "test1"
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/create_test.dart b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/create_test.dart
index 1912459..929945f 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/create_test.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/create_test.dart
@@ -13,7 +13,7 @@
..aKeep = 43;
test('retrieving values', () {
expect(foo.barKeep.aKeep, 5);
- expect(foo.mapKeep['foo'].aKeep, 2);
+ expect(foo.mapKeep['foo']!.aKeep, 2);
expect(foo.hasHasKeep(), false);
expect(foo.aKeep, 43);
foo.clearClearKeep();
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/create_test.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/create_test.dart.expect
index 9dae16a..55a1b78 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/create_test.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/create_test.dart.expect
@@ -1,4 +1,4 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "generated/foo.pb.dart" as pb;
import "dart:core" as core;
@@ -9,21 +9,21 @@
import "file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart";
static method main() → dynamic {
- pb::FooKeep* foo = let final pb::FooKeep* #t1 = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep] pb::FooKeep::•() in block {
- [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.barKeep] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pb::FooKeep::barKeep} = let final pb::BarKeep* #t2 = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep] pb::BarKeep::•() in block {
+ pb::FooKeep foo = let final pb::FooKeep #t1 = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep] pb::FooKeep::•() in block {
+ [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.barKeep] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pb::FooKeep::barKeep} = let final pb::BarKeep #t2 = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep] pb::BarKeep::•() in block {
[@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep.aKeep] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pb::BarKeep::aKeep} = 5;
} =>#t2;
- [@vm.call-site-attributes.metadata=receiverType:dart.core::Map<dart.core::String*, library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep*>*] [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.mapKeep] [@vm.inferred-type.metadata=!] #t1.{pb::FooKeep::mapKeep}{core::Map<core::String*, pb::BarKeep*>*}.{core::Map::[]=}("foo", let final pb::BarKeep* #t3 = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep] pb::BarKeep::•() in block {
+ [@vm.call-site-attributes.metadata=receiverType:dart.core::Map<dart.core::String, library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep>] [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.mapKeep] [@vm.inferred-type.metadata=!] #t1.{pb::FooKeep::mapKeep}{core::Map<core::String, pb::BarKeep>}.{core::Map::[]=}("foo", let final pb::BarKeep #t3 = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep] pb::BarKeep::•() in block {
[@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep.aKeep] [@vm.inferred-type.metadata=!? (skip check)] #t3.{pb::BarKeep::aKeep} = 2;
- } =>#t3){(core::String*, pb::BarKeep*) →* void};
+ } =>#t3){(core::String, pb::BarKeep) → void};
[@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.aKeep] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pb::FooKeep::aKeep} = 43;
} =>#t1;
sca::test(() → Null {
- exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep.aKeep??] [@vm.inferred-type.metadata=int] [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.barKeep] [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep?] foo.{pb::FooKeep::barKeep}{pb::BarKeep*}.{pb::BarKeep::aKeep}{core::int*}, 5);
- exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep.aKeep??] [@vm.inferred-type.metadata=int] [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep?] [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.mapKeep] [@vm.inferred-type.metadata=!] foo.{pb::FooKeep::mapKeep}{core::Map<core::String*, pb::BarKeep*>*}.{core::Map::[]}("foo"){(core::Object*) →* pb::BarKeep*}.{pb::BarKeep::aKeep}{core::int*}, 2);
- exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.hasHasKeep] [@vm.inferred-type.metadata=dart.core::bool (skip check)] foo.{pb::FooKeep::hasHasKeep}(){() →* core::bool*}, false);
- exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.aKeep] [@vm.inferred-type.metadata=int] foo.{pb::FooKeep::aKeep}{core::int*}, 43);
- [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.clearClearKeep] [@vm.inferred-type.metadata=!? (skip check)] foo.{pb::FooKeep::clearClearKeep}(){() →* void};
+ exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep.aKeep??] [@vm.inferred-type.metadata=int] [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.barKeep] [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep?] foo.{pb::FooKeep::barKeep}{pb::BarKeep}.{pb::BarKeep::aKeep}{core::int}, 5);
+ exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep.aKeep] [@vm.inferred-type.metadata=int] [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep?] [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.mapKeep] [@vm.inferred-type.metadata=!] foo.{pb::FooKeep::mapKeep}{core::Map<core::String, pb::BarKeep>}.{core::Map::[]}("foo"){(core::Object?) → pb::BarKeep?}!.{pb::BarKeep::aKeep}{core::int}, 2);
+ exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.hasHasKeep] [@vm.inferred-type.metadata=dart.core::bool (skip check)] foo.{pb::FooKeep::hasHasKeep}(){() → core::bool}, false);
+ exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.aKeep] [@vm.inferred-type.metadata=int] foo.{pb::FooKeep::aKeep}{core::int}, 43);
+ [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.clearClearKeep] [@vm.inferred-type.metadata=!? (skip check)] foo.{pb::FooKeep::clearClearKeep}(){() → void};
});
}
library foo.pb.dart /*isNonNullableByDefault*/;
@@ -38,7 +38,7 @@
[@vm.inferred-type.metadata=protobuf::BuilderInfo?] static final field pro::BuilderInfo _i = let final pro::BuilderInfo #t1 = new pro::BuilderInfo::•((#C1) ?{core::String} "" : "FooKeep") in block {
[@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::BarKeep>(1, (#C1) ?{core::String} "" : "barKeep", "barKeep", #C2){(core::int, core::String, {protoName: core::String?, subBuilder: () →? self::BarKeep}) → void};
[@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::add}<Null>(0, null, null, null, null, null, null){(core::int, core::String, core::int?, dynamic, () →? pro::GeneratedMessage, (core::int) →? pro::ProtobufEnum?, core::List<pro::ProtobufEnum>?, {protoName: core::String?}) → void};
- [@vm.direct-call.metadata=protobuf::BuilderInfo.m] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::m}<core::String, self::BarKeep>((#C1) ?{core::String} "" : "mapKeep", #C2){(core::int, core::String, {entryClassName: core::String?, enumValues: core::List<pro::ProtobufEnum>?, keyFieldType: core::int?, packageName: pro::PackageName, protoName: core::String?, valueCreator: () →? pro::GeneratedMessage, valueFieldType: core::int?, valueOf: (core::int) →? pro::ProtobufEnum?}) → void};
+ [@vm.direct-call.metadata=protobuf::BuilderInfo.m] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::m}<core::String, self::BarKeep>((#C1) ?{core::String} "" : "mapKeep", #C2){(core::int, core::String, {defaultEnumValue: pro::ProtobufEnum?, entryClassName: core::String?, enumValues: core::List<pro::ProtobufEnum>?, keyFieldType: core::int?, packageName: pro::PackageName, protoName: core::String?, valueCreator: () →? pro::GeneratedMessage, valueFieldType: core::int?, valueOf: (core::int) →? pro::ProtobufEnum?}) → void};
[@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::add}<Null>(0, null, null, null, null, null, null){(core::int, core::String, core::int?, dynamic, () →? pro::GeneratedMessage, (core::int) →? pro::ProtobufEnum?, core::List<pro::ProtobufEnum>?, {protoName: core::String?}) → void};
[@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::a}<core::int>(5, (#C1) ?{core::String} "" : "aKeep"){(core::int, core::String, core::int, {defaultOrMaker: dynamic, enumValues: core::List<pro::ProtobufEnum>?, protoName: core::String?, subBuilder: () →? pro::GeneratedMessage, valueOf: (core::int) →? pro::ProtobufEnum?}) → void};
[@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::HasKeep>(6, (#C1) ?{core::String} "" : "hasKeep", "hasKeep", #C3){(core::int, core::String, {protoName: core::String?, subBuilder: () →? self::HasKeep}) → void};
@@ -133,9 +133,9 @@
}
constants {
#C1 = false
- #C2 = tearoff self::BarKeep::create
- #C3 = tearoff self::HasKeep::create
- #C4 = tearoff self::ClearKeep::create
+ #C2 = static-tearoff self::BarKeep::create
+ #C3 = static-tearoff self::HasKeep::create
+ #C4 = static-tearoff self::ClearKeep::create
#C5 = "dart2js:noInline"
#C6 = null
#C7 = core::pragma {name:#C5, options:#C6}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/decode_test.dart b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/decode_test.dart
index d33289f..7e96839 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/decode_test.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/decode_test.dart
@@ -19,7 +19,7 @@
main() {
FooKeep foo = FooKeep.fromBuffer(buffer);
test('Kept values are restored correctly', () {
- expect(foo.mapKeep['foo'].aKeep, 42);
+ expect(foo.mapKeep['foo']!.aKeep, 42);
expect(foo.barKeep.aKeep, 5);
expect(foo.aKeep, 43);
expect(foo.hasHasKeep(), true);
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/decode_test.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/decode_test.dart.expect
index 133c846..9dd85ff 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/decode_test.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/decode_test.dart.expect
@@ -1,4 +1,4 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "generated/foo.pb.dart" as pb;
import "package:test_core/scaffolding.dart" as sca;
@@ -8,15 +8,15 @@
import "package:test/test.dart";
import "file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart";
-[@vm.inferred-type.metadata=dart.core::_GrowableList?<dart.core::int*>]static field core::List<core::int*>* buffer = <core::int*>[10, 4, 8, 5, 16, 4, 26, 9, 10, 3, 102, 111, 111, 18, 2, 8, 42, 34, 9, 10, 3, 122, 111, 112, 18, 2, 8, 3, 40, 43, 50, 0, 58, 0];
+[@vm.inferred-type.metadata=dart.core::_GrowableList?<dart.core::int>]static field core::List<core::int> buffer = <core::int>[10, 4, 8, 5, 16, 4, 26, 9, 10, 3, 102, 111, 111, 18, 2, 8, 42, 34, 9, 10, 3, 122, 111, 112, 18, 2, 8, 3, 40, 43, 50, 0, 58, 0];
static method main() → dynamic {
- pb::FooKeep* foo = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep] pb::FooKeep::fromBuffer([@vm.inferred-type.metadata=dart.core::_GrowableList?<dart.core::int*>] self::buffer);
+ pb::FooKeep foo = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep] pb::FooKeep::fromBuffer([@vm.inferred-type.metadata=dart.core::_GrowableList?<dart.core::int>] self::buffer);
sca::test(() → Null {
- exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep.aKeep??] [@vm.inferred-type.metadata=int] [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep?] [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.mapKeep] [@vm.inferred-type.metadata=!] foo.{pb::FooKeep::mapKeep}{core::Map<core::String*, pb::BarKeep*>*}.{core::Map::[]}("foo"){(core::Object*) →* pb::BarKeep*}.{pb::BarKeep::aKeep}{core::int*}, 42);
- exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep.aKeep??] [@vm.inferred-type.metadata=int] [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.barKeep] [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep?] foo.{pb::FooKeep::barKeep}{pb::BarKeep*}.{pb::BarKeep::aKeep}{core::int*}, 5);
- exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.aKeep] [@vm.inferred-type.metadata=int] foo.{pb::FooKeep::aKeep}{core::int*}, 43);
- exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.hasHasKeep] [@vm.inferred-type.metadata=dart.core::bool (skip check)] foo.{pb::FooKeep::hasHasKeep}(){() →* core::bool*}, true);
- [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.clearClearKeep] [@vm.inferred-type.metadata=!? (skip check)] foo.{pb::FooKeep::clearClearKeep}(){() →* void};
+ exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep.aKeep] [@vm.inferred-type.metadata=int] [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep?] [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.mapKeep] [@vm.inferred-type.metadata=!] foo.{pb::FooKeep::mapKeep}{core::Map<core::String, pb::BarKeep>}.{core::Map::[]}("foo"){(core::Object?) → pb::BarKeep?}!.{pb::BarKeep::aKeep}{core::int}, 42);
+ exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep.aKeep??] [@vm.inferred-type.metadata=int] [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.barKeep] [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep?] foo.{pb::FooKeep::barKeep}{pb::BarKeep}.{pb::BarKeep::aKeep}{core::int}, 5);
+ exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.aKeep] [@vm.inferred-type.metadata=int] foo.{pb::FooKeep::aKeep}{core::int}, 43);
+ exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.hasHasKeep] [@vm.inferred-type.metadata=dart.core::bool (skip check)] foo.{pb::FooKeep::hasHasKeep}(){() → core::bool}, true);
+ [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.clearClearKeep] [@vm.inferred-type.metadata=!? (skip check)] foo.{pb::FooKeep::clearClearKeep}(){() → void};
});
}
library foo.pb.dart /*isNonNullableByDefault*/;
@@ -31,7 +31,7 @@
[@vm.inferred-type.metadata=protobuf::BuilderInfo?] static final field pro::BuilderInfo _i = let final pro::BuilderInfo #t1 = new pro::BuilderInfo::•((#C1) ?{core::String} "" : "FooKeep", createEmptyInstance: #C2) in block {
[@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::BarKeep>(1, (#C1) ?{core::String} "" : "barKeep", "barKeep", #C3){(core::int, core::String, {protoName: core::String?, subBuilder: () →? self::BarKeep}) → void};
[@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::add}<Null>(0, null, null, null, null, null, null){(core::int, core::String, core::int?, dynamic, () →? pro::GeneratedMessage, (core::int) →? pro::ProtobufEnum?, core::List<pro::ProtobufEnum>?, {protoName: core::String?}) → void};
- [@vm.direct-call.metadata=protobuf::BuilderInfo.m] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::m}<core::String, self::BarKeep>((#C1) ?{core::String} "" : "mapKeep", #C3){(core::int, core::String, {entryClassName: core::String?, enumValues: core::List<pro::ProtobufEnum>?, keyFieldType: core::int?, packageName: pro::PackageName, protoName: core::String?, valueCreator: () →? pro::GeneratedMessage, valueFieldType: core::int?, valueOf: (core::int) →? pro::ProtobufEnum?}) → void};
+ [@vm.direct-call.metadata=protobuf::BuilderInfo.m] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::m}<core::String, self::BarKeep>((#C1) ?{core::String} "" : "mapKeep", #C3){(core::int, core::String, {defaultEnumValue: pro::ProtobufEnum?, entryClassName: core::String?, enumValues: core::List<pro::ProtobufEnum>?, keyFieldType: core::int?, packageName: pro::PackageName, protoName: core::String?, valueCreator: () →? pro::GeneratedMessage, valueFieldType: core::int?, valueOf: (core::int) →? pro::ProtobufEnum?}) → void};
[@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::add}<Null>(0, null, null, null, null, null, null){(core::int, core::String, core::int?, dynamic, () →? pro::GeneratedMessage, (core::int) →? pro::ProtobufEnum?, core::List<pro::ProtobufEnum>?, {protoName: core::String?}) → void};
[@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::a}<core::int>(5, (#C1) ?{core::String} "" : "aKeep"){(core::int, core::String, core::int, {defaultOrMaker: dynamic, enumValues: core::List<pro::ProtobufEnum>?, protoName: core::String?, subBuilder: () →? pro::GeneratedMessage, valueOf: (core::int) →? pro::ProtobufEnum?}) → void};
[@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::HasKeep>(6, (#C1) ?{core::String} "" : "hasKeep", "hasKeep", #C4){(core::int, core::String, {protoName: core::String?, subBuilder: () →? self::HasKeep}) → void};
@@ -41,7 +41,7 @@
constructor _() → self::FooKeep
: super pro::GeneratedMessage::•()
;
- static factory fromBuffer([@vm.inferred-type.metadata=dart.core::_GrowableList?<dart.core::int*>] core::List<core::int> i) → self::FooKeep
+ static factory fromBuffer([@vm.inferred-type.metadata=dart.core::_GrowableList?<dart.core::int>] core::List<core::int> i) → self::FooKeep
return let final self::FooKeep #t2 = [@vm.inferred-type.metadata=foo.pb.dart::FooKeep] self::FooKeep::create() in block {
[@vm.direct-call.metadata=protobuf::GeneratedMessage.mergeFromBuffer] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pro::GeneratedMessage::mergeFromBuffer}(i){(core::List<core::int>, [pro::ExtensionRegistry]) → void};
} =>#t2;
@@ -114,10 +114,10 @@
}
constants {
#C1 = false
- #C2 = tearoff self::FooKeep::create
- #C3 = tearoff self::BarKeep::create
- #C4 = tearoff self::HasKeep::create
- #C5 = tearoff self::ClearKeep::create
+ #C2 = static-tearoff self::FooKeep::create
+ #C3 = static-tearoff self::BarKeep::create
+ #C4 = static-tearoff self::HasKeep::create
+ #C5 = static-tearoff self::ClearKeep::create
#C6 = "dart2js:noInline"
#C7 = null
#C8 = core::pragma {name:#C6, options:#C7}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/encode_all_fields.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/encode_all_fields.dart.expect
index f223e18..f925ae6 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/encode_all_fields.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/encode_all_fields.dart.expect
@@ -1,4 +1,4 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "generated/foo.pb.dart" as pb;
import "dart:core" as core;
@@ -10,26 +10,26 @@
import "file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart";
static method main() → dynamic {
- pb::FooKeep* foo = let final pb::FooKeep* #t1 = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep] pb::FooKeep::•() in block {
- [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.barKeep] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pb::FooKeep::barKeep} = let final pb::BarKeep* #t2 = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep] pb::BarKeep::•() in block {
+ pb::FooKeep foo = let final pb::FooKeep #t1 = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep] pb::FooKeep::•() in block {
+ [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.barKeep] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pb::FooKeep::barKeep} = let final pb::BarKeep #t2 = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep] pb::BarKeep::•() in block {
[@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep.aKeep] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pb::BarKeep::aKeep} = 5;
[@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep.bDrop] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pb::BarKeep::bDrop} = 4;
} =>#t2;
- [@vm.call-site-attributes.metadata=receiverType:dart.core::Map<dart.core::String*, library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep*>*] [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.mapKeep] [@vm.inferred-type.metadata=!] #t1.{pb::FooKeep::mapKeep}{core::Map<core::String*, pb::BarKeep*>*}.{core::Map::[]=}("foo", let final pb::BarKeep* #t3 = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep] pb::BarKeep::•() in block {
+ [@vm.call-site-attributes.metadata=receiverType:dart.core::Map<dart.core::String, library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep>] [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.mapKeep] [@vm.inferred-type.metadata=!] #t1.{pb::FooKeep::mapKeep}{core::Map<core::String, pb::BarKeep>}.{core::Map::[]=}("foo", let final pb::BarKeep #t3 = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep] pb::BarKeep::•() in block {
[@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep.aKeep] [@vm.inferred-type.metadata=!? (skip check)] #t3.{pb::BarKeep::aKeep} = 42;
- } =>#t3){(core::String*, pb::BarKeep*) →* void};
- [@vm.call-site-attributes.metadata=receiverType:dart.core::Map<dart.core::String*, library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::ZopDrop*>*] [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.mapDrop] [@vm.inferred-type.metadata=!] #t1.{pb::FooKeep::mapDrop}{core::Map<core::String*, pb::ZopDrop*>*}.{core::Map::[]=}("zop", let final pb::ZopDrop* #t4 = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::ZopDrop] pb::ZopDrop::•() in block {
+ } =>#t3){(core::String, pb::BarKeep) → void};
+ [@vm.call-site-attributes.metadata=receiverType:dart.core::Map<dart.core::String, library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::ZopDrop>] [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.mapDrop] [@vm.inferred-type.metadata=!] #t1.{pb::FooKeep::mapDrop}{core::Map<core::String, pb::ZopDrop>}.{core::Map::[]=}("zop", let final pb::ZopDrop #t4 = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::ZopDrop] pb::ZopDrop::•() in block {
[@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::ZopDrop.aDrop] [@vm.inferred-type.metadata=!? (skip check)] #t4.{pb::ZopDrop::aDrop} = 3;
- } =>#t4){(core::String*, pb::ZopDrop*) →* void};
+ } =>#t4){(core::String, pb::ZopDrop) → void};
[@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.aKeep] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pb::FooKeep::aKeep} = 43;
[@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.hasKeep] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pb::FooKeep::hasKeep} = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::HasKeep] pb::HasKeep::•();
[@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.clearKeep] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pb::FooKeep::clearKeep} = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::ClearKeep] pb::ClearKeep::•();
} =>#t1;
- final typ::Uint8List* buffer = [@vm.direct-call.metadata=protobuf::GeneratedMessage.writeToBuffer] [@vm.inferred-type.metadata=dart.typed_data::_Uint8List (skip check)] foo.{pro::GeneratedMessage::writeToBuffer}(){() →* typ::Uint8List*};
+ final typ::Uint8List buffer = [@vm.direct-call.metadata=protobuf::GeneratedMessage.writeToBuffer] [@vm.inferred-type.metadata=dart.typed_data::_Uint8List (skip check)] foo.{pro::GeneratedMessage::writeToBuffer}(){() → typ::Uint8List};
core::print("List<int> buffer = <int>[");
- for (core::int* i = 0; [@vm.direct-call.metadata=dart.core::_IntegerImplementation.<] [@vm.inferred-type.metadata=dart.core::bool (skip check)] i.{core::num::<}([@vm.direct-call.metadata=dart.typed_data::_TypedListBase.length] [@vm.inferred-type.metadata=dart.core::_Smi] buffer.{core::List::length}{core::int*}){(core::num*) →* core::bool*}; i = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(5){(core::num*) →* core::int*}) {
- final core::String* numbers = [@vm.direct-call.metadata=dart.typed_data::_TypedListBase.join] [@vm.inferred-type.metadata=!? (skip check)] [@vm.direct-call.metadata=dart.typed_data::__Uint8List&_TypedList&_IntListMixin&_TypedIntListMixin.sublist] [@vm.inferred-type.metadata=dart.typed_data::_Uint8List (skip check)] buffer.{typ::Uint8List::sublist}(i, [@vm.inferred-type.metadata=int] math::min<core::int*>([@vm.direct-call.metadata=dart.typed_data::_TypedListBase.length] [@vm.inferred-type.metadata=dart.core::_Smi] buffer.{core::List::length}{core::int*}, [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(5){(core::num*) →* core::int*})){(core::int*, [core::int*]) →* typ::Uint8List*}.{core::Iterable::join}(", "){([core::String*]) →* core::String*};
- core::print(" ${numbers},${[@vm.direct-call.metadata=dart.core::_IntegerImplementation.==] [@vm.inferred-type.metadata=dart.core::bool (skip check)] i =={core::num::==}{(core::Object*) →* core::bool*} 0 ?{core::String*} " //" : ""}");
+ for (core::int i = 0; [@vm.direct-call.metadata=dart.core::_IntegerImplementation.<] [@vm.inferred-type.metadata=dart.core::bool (skip check)] i.{core::num::<}([@vm.direct-call.metadata=dart.typed_data::_TypedListBase.length] [@vm.inferred-type.metadata=dart.core::_Smi] buffer.{core::List::length}{core::int}){(core::num) → core::bool}; i = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(5){(core::num) → core::int}) {
+ final core::String numbers = [@vm.direct-call.metadata=dart.typed_data::_TypedListBase.join] [@vm.inferred-type.metadata=!? (skip check)] [@vm.direct-call.metadata=dart.typed_data::__Uint8List&_TypedList&_IntListMixin&_TypedIntListMixin.sublist] [@vm.inferred-type.metadata=dart.typed_data::_Uint8List (skip check)] buffer.{typ::Uint8List::sublist}(i, [@vm.inferred-type.metadata=int] math::min<core::int>([@vm.direct-call.metadata=dart.typed_data::_TypedListBase.length] [@vm.inferred-type.metadata=dart.core::_Smi] buffer.{core::List::length}{core::int}, [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(5){(core::num) → core::int})){(core::int, [core::int?]) → typ::Uint8List}.{core::Iterable::join}(", "){([core::String]) → core::String};
+ core::print(" ${numbers},${[@vm.direct-call.metadata=dart.core::_IntegerImplementation.==] [@vm.inferred-type.metadata=dart.core::bool (skip check)] i =={core::num::==}{(core::Object) → core::bool} 0 ?{core::String} " //" : ""}");
}
core::print("];");
}
@@ -45,8 +45,8 @@
[@vm.inferred-type.metadata=protobuf::BuilderInfo?] static final field pro::BuilderInfo _i = let final pro::BuilderInfo #t1 = new pro::BuilderInfo::•((#C1) ?{core::String} "" : "FooKeep") in block {
[@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::BarKeep>(1, (#C1) ?{core::String} "" : "barKeep", "barKeep", #C2){(core::int, core::String, {protoName: core::String?, subBuilder: () →? self::BarKeep}) → void};
[@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::add}<Null>(0, null, null, null, null, null, null){(core::int, core::String, core::int?, dynamic, () →? pro::GeneratedMessage, (core::int) →? pro::ProtobufEnum?, core::List<pro::ProtobufEnum>?, {protoName: core::String?}) → void};
- [@vm.direct-call.metadata=protobuf::BuilderInfo.m] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::m}<core::String, self::BarKeep>(3, (#C1) ?{core::String} "" : "mapKeep", "FooKeep.MapKeepEntry", "mapKeep", #C2){(core::int, core::String, {entryClassName: core::String?, enumValues: core::List<pro::ProtobufEnum>?, keyFieldType: core::int?, packageName: pro::PackageName, protoName: core::String?, valueCreator: () →? pro::GeneratedMessage, valueFieldType: core::int?, valueOf: (core::int) →? pro::ProtobufEnum?}) → void};
- [@vm.direct-call.metadata=protobuf::BuilderInfo.m] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::m}<core::String, self::ZopDrop>(4, (#C1) ?{core::String} "" : "mapDrop", "FooKeep.MapDropEntry", "mapDrop", #C3){(core::int, core::String, {entryClassName: core::String?, enumValues: core::List<pro::ProtobufEnum>?, keyFieldType: core::int?, packageName: pro::PackageName, protoName: core::String?, valueCreator: () →? pro::GeneratedMessage, valueFieldType: core::int?, valueOf: (core::int) →? pro::ProtobufEnum?}) → void};
+ [@vm.direct-call.metadata=protobuf::BuilderInfo.m] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::m}<core::String, self::BarKeep>(3, (#C1) ?{core::String} "" : "mapKeep", "FooKeep.MapKeepEntry", "mapKeep", #C2){(core::int, core::String, {defaultEnumValue: pro::ProtobufEnum?, entryClassName: core::String?, enumValues: core::List<pro::ProtobufEnum>?, keyFieldType: core::int?, packageName: pro::PackageName, protoName: core::String?, valueCreator: () →? pro::GeneratedMessage, valueFieldType: core::int?, valueOf: (core::int) →? pro::ProtobufEnum?}) → void};
+ [@vm.direct-call.metadata=protobuf::BuilderInfo.m] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::m}<core::String, self::ZopDrop>(4, (#C1) ?{core::String} "" : "mapDrop", "FooKeep.MapDropEntry", "mapDrop", #C3){(core::int, core::String, {defaultEnumValue: pro::ProtobufEnum?, entryClassName: core::String?, enumValues: core::List<pro::ProtobufEnum>?, keyFieldType: core::int?, packageName: pro::PackageName, protoName: core::String?, valueCreator: () →? pro::GeneratedMessage, valueFieldType: core::int?, valueOf: (core::int) →? pro::ProtobufEnum?}) → void};
[@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::a}<core::int>(5, (#C1) ?{core::String} "" : "aKeep", "aKeep"){(core::int, core::String, core::int, {defaultOrMaker: dynamic, enumValues: core::List<pro::ProtobufEnum>?, protoName: core::String?, subBuilder: () →? pro::GeneratedMessage, valueOf: (core::int) →? pro::ProtobufEnum?}) → void};
[@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::HasKeep>(6, (#C1) ?{core::String} "" : "hasKeep", "hasKeep", #C4){(core::int, core::String, {protoName: core::String?, subBuilder: () →? self::HasKeep}) → void};
[@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::ClearKeep>(7, (#C1) ?{core::String} "" : "clearKeep", "clearKeep", #C5){(core::int, core::String, {protoName: core::String?, subBuilder: () →? self::ClearKeep}) → void};
@@ -164,10 +164,10 @@
}
constants {
#C1 = false
- #C2 = tearoff self::BarKeep::create
- #C3 = tearoff self::ZopDrop::create
- #C4 = tearoff self::HasKeep::create
- #C5 = tearoff self::ClearKeep::create
+ #C2 = static-tearoff self::BarKeep::create
+ #C3 = static-tearoff self::ZopDrop::create
+ #C4 = static-tearoff self::HasKeep::create
+ #C5 = static-tearoff self::ClearKeep::create
#C6 = "dart2js:noInline"
#C7 = null
#C8 = core::pragma {name:#C6, options:#C7}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/freeze_test.dart b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/freeze_test.dart
index 0529e4a..8d7567e 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/freeze_test.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/freeze_test.dart
@@ -14,7 +14,7 @@
test('Freezing a message works', () {
foo.freeze();
expect(foo.barKeep.aKeep, 5);
- expect(foo.mapKeep['foo'].aKeep, 2);
+ expect(foo.mapKeep['foo']!.aKeep, 2);
expect(foo.hasHasKeep(), false);
expect(foo.aKeep, 43);
expect(() => foo.clearClearKeep(),
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/freeze_test.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/freeze_test.dart.expect
index ee0cdfc..0071356 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/freeze_test.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/freeze_test.dart.expect
@@ -1,4 +1,4 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "generated/foo.pb.dart" as pb;
import "dart:core" as core;
@@ -11,22 +11,22 @@
import "file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart";
static method main() → dynamic {
- pb::FooKeep* foo = let final pb::FooKeep* #t1 = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep] pb::FooKeep::•() in block {
- [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.barKeep] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pb::FooKeep::barKeep} = let final pb::BarKeep* #t2 = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep] pb::BarKeep::•() in block {
+ pb::FooKeep foo = let final pb::FooKeep #t1 = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep] pb::FooKeep::•() in block {
+ [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.barKeep] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pb::FooKeep::barKeep} = let final pb::BarKeep #t2 = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep] pb::BarKeep::•() in block {
[@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep.aKeep] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pb::BarKeep::aKeep} = 5;
} =>#t2;
- [@vm.call-site-attributes.metadata=receiverType:dart.core::Map<dart.core::String*, library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep*>*] [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.mapKeep] [@vm.inferred-type.metadata=!] #t1.{pb::FooKeep::mapKeep}{core::Map<core::String*, pb::BarKeep*>*}.{core::Map::[]=}("foo", let final pb::BarKeep* #t3 = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep] pb::BarKeep::•() in block {
+ [@vm.call-site-attributes.metadata=receiverType:dart.core::Map<dart.core::String, library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep>] [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.mapKeep] [@vm.inferred-type.metadata=!] #t1.{pb::FooKeep::mapKeep}{core::Map<core::String, pb::BarKeep>}.{core::Map::[]=}("foo", let final pb::BarKeep #t3 = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep] pb::BarKeep::•() in block {
[@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep.aKeep] [@vm.inferred-type.metadata=!? (skip check)] #t3.{pb::BarKeep::aKeep} = 2;
- } =>#t3){(core::String*, pb::BarKeep*) →* void};
+ } =>#t3){(core::String, pb::BarKeep) → void};
[@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.aKeep] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pb::FooKeep::aKeep} = 43;
} =>#t1;
sca::test(() → Null {
- [@vm.direct-call.metadata=protobuf::GeneratedMessage.freeze] [@vm.inferred-type.metadata=!? (skip check)] foo.{pro::GeneratedMessage::freeze}(){() →* pro::GeneratedMessage*};
- exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep.aKeep??] [@vm.inferred-type.metadata=int] [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.barKeep] [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep?] foo.{pb::FooKeep::barKeep}{pb::BarKeep*}.{pb::BarKeep::aKeep}{core::int*}, 5);
- exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep.aKeep??] [@vm.inferred-type.metadata=int] [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep?] [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.mapKeep] [@vm.inferred-type.metadata=!] foo.{pb::FooKeep::mapKeep}{core::Map<core::String*, pb::BarKeep*>*}.{core::Map::[]}("foo"){(core::Object*) →* pb::BarKeep*}.{pb::BarKeep::aKeep}{core::int*}, 2);
- exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.hasHasKeep] [@vm.inferred-type.metadata=dart.core::bool (skip check)] foo.{pb::FooKeep::hasHasKeep}(){() →* core::bool*}, false);
- exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.aKeep] [@vm.inferred-type.metadata=int] foo.{pb::FooKeep::aKeep}{core::int*}, 43);
- exp::expect(() → void => [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.clearClearKeep] [@vm.inferred-type.metadata=!? (skip check)] foo.{pb::FooKeep::clearClearKeep}(){() →* void}, [@vm.inferred-type.metadata=library package:test_api/src/expect/throws_matcher.dart::Throws] thr::throwsA());
+ [@vm.direct-call.metadata=protobuf::GeneratedMessage.freeze] [@vm.inferred-type.metadata=!? (skip check)] foo.{pro::GeneratedMessage::freeze}(){() → pro::GeneratedMessage};
+ exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep.aKeep??] [@vm.inferred-type.metadata=int] [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.barKeep] [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep?] foo.{pb::FooKeep::barKeep}{pb::BarKeep}.{pb::BarKeep::aKeep}{core::int}, 5);
+ exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep.aKeep] [@vm.inferred-type.metadata=int] [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep?] [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.mapKeep] [@vm.inferred-type.metadata=!] foo.{pb::FooKeep::mapKeep}{core::Map<core::String, pb::BarKeep>}.{core::Map::[]}("foo"){(core::Object?) → pb::BarKeep?}!.{pb::BarKeep::aKeep}{core::int}, 2);
+ exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.hasHasKeep] [@vm.inferred-type.metadata=dart.core::bool (skip check)] foo.{pb::FooKeep::hasHasKeep}(){() → core::bool}, false);
+ exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.aKeep] [@vm.inferred-type.metadata=int] foo.{pb::FooKeep::aKeep}{core::int}, 43);
+ exp::expect(() → void => [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.clearClearKeep] [@vm.inferred-type.metadata=!? (skip check)] foo.{pb::FooKeep::clearClearKeep}(){() → void}, [@vm.inferred-type.metadata=library package:test_api/src/expect/throws_matcher.dart::Throws] thr::throwsA());
});
}
library foo.pb.dart /*isNonNullableByDefault*/;
@@ -41,7 +41,7 @@
[@vm.inferred-type.metadata=protobuf::BuilderInfo?] static final field pro::BuilderInfo _i = let final pro::BuilderInfo #t1 = new pro::BuilderInfo::•((#C1) ?{core::String} "" : "FooKeep") in block {
[@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::BarKeep>(1, (#C1) ?{core::String} "" : "barKeep", "barKeep", #C2){(core::int, core::String, {protoName: core::String?, subBuilder: () →? self::BarKeep}) → void};
[@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::add}<Null>(0, null, null, null, null, null, null){(core::int, core::String, core::int?, dynamic, () →? pro::GeneratedMessage, (core::int) →? pro::ProtobufEnum?, core::List<pro::ProtobufEnum>?, {protoName: core::String?}) → void};
- [@vm.direct-call.metadata=protobuf::BuilderInfo.m] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::m}<core::String, self::BarKeep>((#C1) ?{core::String} "" : "mapKeep", #C2){(core::int, core::String, {entryClassName: core::String?, enumValues: core::List<pro::ProtobufEnum>?, keyFieldType: core::int?, packageName: pro::PackageName, protoName: core::String?, valueCreator: () →? pro::GeneratedMessage, valueFieldType: core::int?, valueOf: (core::int) →? pro::ProtobufEnum?}) → void};
+ [@vm.direct-call.metadata=protobuf::BuilderInfo.m] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::m}<core::String, self::BarKeep>((#C1) ?{core::String} "" : "mapKeep", #C2){(core::int, core::String, {defaultEnumValue: pro::ProtobufEnum?, entryClassName: core::String?, enumValues: core::List<pro::ProtobufEnum>?, keyFieldType: core::int?, packageName: pro::PackageName, protoName: core::String?, valueCreator: () →? pro::GeneratedMessage, valueFieldType: core::int?, valueOf: (core::int) →? pro::ProtobufEnum?}) → void};
[@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::add}<Null>(0, null, null, null, null, null, null){(core::int, core::String, core::int?, dynamic, () →? pro::GeneratedMessage, (core::int) →? pro::ProtobufEnum?, core::List<pro::ProtobufEnum>?, {protoName: core::String?}) → void};
[@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::a}<core::int>(5, (#C1) ?{core::String} "" : "aKeep"){(core::int, core::String, core::int, {defaultOrMaker: dynamic, enumValues: core::List<pro::ProtobufEnum>?, protoName: core::String?, subBuilder: () →? pro::GeneratedMessage, valueOf: (core::int) →? pro::ProtobufEnum?}) → void};
[@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::HasKeep>(6, (#C1) ?{core::String} "" : "hasKeep", "hasKeep", #C3){(core::int, core::String, {protoName: core::String?, subBuilder: () →? self::HasKeep}) → void};
@@ -136,9 +136,9 @@
}
constants {
#C1 = false
- #C2 = tearoff self::BarKeep::create
- #C3 = tearoff self::HasKeep::create
- #C4 = tearoff self::ClearKeep::create
+ #C2 = static-tearoff self::BarKeep::create
+ #C3 = static-tearoff self::HasKeep::create
+ #C4 = static-tearoff self::ClearKeep::create
#C5 = "dart2js:noInline"
#C6 = null
#C7 = core::pragma {name:#C5, options:#C6}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/name_mangling_test.dart b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/name_mangling_test.dart
index b52c5dc..c5b7bf4 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/name_mangling_test.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/name_mangling_test.dart
@@ -2,8 +2,6 @@
// 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.
-import 'package:test/test.dart';
-
import 'generated/name_mangling.pb.dart';
main() {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/name_mangling_test.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/name_mangling_test.dart.expect
index 7489bcb..63e55db 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/name_mangling_test.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/name_mangling_test.dart.expect
@@ -1,14 +1,13 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "generated/name_mangling.pb.dart" as pb;
import "dart:core" as core;
-import "package:test/test.dart";
import "file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/name_mangling.pb.dart";
static method main() → dynamic {
- pb::NameManglingKeep* n = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/name_mangling.pb.dart::NameManglingKeep] pb::NameManglingKeep::fromBuffer([@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int*>] core::_GrowableList::•<core::int*>(0));
- if([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/name_mangling.pb.dart::NameManglingKeep.hasClone_10] [@vm.inferred-type.metadata=dart.core::bool (skip check)] n.{pb::NameManglingKeep::hasClone_10}(){() →* core::bool*}) {
+ pb::NameManglingKeep n = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/name_mangling.pb.dart::NameManglingKeep] pb::NameManglingKeep::fromBuffer([@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int>] core::_GrowableList::•<core::int>(0));
+ if([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/name_mangling.pb.dart::NameManglingKeep.hasClone_10] [@vm.inferred-type.metadata=dart.core::bool (skip check)] n.{pb::NameManglingKeep::hasClone_10}(){() → core::bool}) {
core::print("Has clone field");
}
}
@@ -41,7 +40,7 @@
constructor _() → self::NameManglingKeep
: super pro::GeneratedMessage::•()
;
- static factory fromBuffer([@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int*>] core::List<core::int> i) → self::NameManglingKeep
+ static factory fromBuffer([@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int>] core::List<core::int> i) → self::NameManglingKeep
return let final self::NameManglingKeep #t3 = [@vm.inferred-type.metadata=name_mangling.pb.dart::NameManglingKeep] self::NameManglingKeep::create() in block {
[@vm.direct-call.metadata=protobuf::GeneratedMessage.mergeFromBuffer] [@vm.inferred-type.metadata=!? (skip check)] #t3.{pro::GeneratedMessage::mergeFromBuffer}(i){(core::List<core::int>, [pro::ExtensionRegistry]) → void};
} =>#t3;
@@ -56,11 +55,11 @@
}
constants {
#C1 = false
- #C2 = tearoff self::AKeep::create
+ #C2 = static-tearoff self::AKeep::create
#C3 = "dart2js:noInline"
#C4 = null
#C5 = core::pragma {name:#C3, options:#C4}
- #C6 = tearoff self::NameManglingKeep::create
+ #C6 = static-tearoff self::NameManglingKeep::create
#C7 = 10
#C8 = pro::TagNumber {tagNumber:#C7}
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/nop_test.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/nop_test.dart.expect
index 7512991..0762979 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/nop_test.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/nop_test.dart.expect
@@ -1,4 +1,4 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_37455.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/regress_37455.dart.expect
index 2d0f29f..7de8f83 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/regress_37455.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_37455.dart.expect
@@ -1,31 +1,31 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
class A extends core::Object {
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] final field core::List<dynamic>* afield;
- constructor •(core::List<dynamic>* afield) → self::A*
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] final field core::List<dynamic> afield;
+ constructor •(core::List<dynamic> afield) → self::A
: self::A::afield = afield, super core::Object::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:2,getterSelectorId:3] method toString() → core::String*
- return [@vm.inferred-type.metadata=!? (receiver not int)] [@vm.direct-call.metadata=#lib::A.afield] this.{self::A::afield}{core::List<dynamic>*}.{core::Object::toString}(){() →* core::String*};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:2,getterSelectorId:3] method toString() → core::String
+ return [@vm.inferred-type.metadata=!? (receiver not int)] [@vm.direct-call.metadata=#lib::A.afield] this.{self::A::afield}{core::List<dynamic>}.{core::Object::toString}(){() → core::String};
}
class B extends core::Object {
- synthetic constructor •() → self::B*
+ synthetic constructor •() → self::B
: super core::Object::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5] method _foo([@vm.inferred-type.metadata=dart._internal::ListIterator<dart.core::int*>] core::Iterator<core::int*>* iter) → core::List<dynamic>* {
- core::List<dynamic>* result = [@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic>] core::_GrowableList::•<dynamic>(0);
- while ([@vm.direct-call.metadata=dart._internal::ListIterator.moveNext] [@vm.inferred-type.metadata=dart.core::bool (skip check)] iter.{core::Iterator::moveNext}(){() →* core::bool*}) {
- if([@vm.direct-call.metadata=dart.core::_IntegerImplementation.<??] [@vm.inferred-type.metadata=dart.core::bool (skip check)] [@vm.direct-call.metadata=dart._internal::ListIterator.current] [@vm.inferred-type.metadata=int?] iter.{core::Iterator::current}{core::int*}.{core::num::<}(0){(core::num*) →* core::bool*}) {
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5] method _foo([@vm.inferred-type.metadata=dart._internal::ListIterator<dart.core::int>] core::Iterator<core::int> iter) → core::List<dynamic> {
+ core::List<dynamic> result = [@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic>] core::_GrowableList::•<dynamic>(0);
+ while ([@vm.direct-call.metadata=dart._internal::ListIterator.moveNext] [@vm.inferred-type.metadata=dart.core::bool (skip check)] iter.{core::Iterator::moveNext}(){() → core::bool}) {
+ if([@vm.direct-call.metadata=dart.core::_IntegerImplementation.<??] [@vm.inferred-type.metadata=dart.core::bool (skip check)] [@vm.direct-call.metadata=dart._internal::ListIterator.current] [@vm.inferred-type.metadata=int?] iter.{core::Iterator::current}{core::int}.{core::num::<}(0){(core::num) → core::bool}) {
return result;
}
- [@vm.call-site-attributes.metadata=receiverType:dart.core::List<dynamic>*] [@vm.direct-call.metadata=dart.core::_GrowableList.add] [@vm.inferred-type.metadata=!? (skip check)] result.{core::List::add}(new self::A::•([@vm.direct-call.metadata=#lib::B._foo] [@vm.inferred-type.metadata=!? (skip check)] this.{self::B::_foo}(iter){(core::Iterator<core::int*>*) →* core::List<dynamic>*})){(dynamic) →* void};
+ [@vm.call-site-attributes.metadata=receiverType:dart.core::List<dynamic>] [@vm.direct-call.metadata=dart.core::_GrowableList.add] [@vm.inferred-type.metadata=!? (skip check)] result.{core::List::add}(new self::A::•([@vm.direct-call.metadata=#lib::B._foo] [@vm.inferred-type.metadata=!? (skip check)] this.{self::B::_foo}(iter){(core::Iterator<core::int>) → core::List<dynamic>})){(dynamic) → void};
}
return result;
}
}
static method main() → void {
- core::List<dynamic>* list = [@vm.direct-call.metadata=#lib::B._foo] [@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic> (skip check)] new self::B::•().{self::B::_foo}([@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<dart.core::int*>] [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int*>] core::_GrowableList::_literal3<core::int*>(1, 2, 3).{core::Iterable::iterator}{core::Iterator<core::int*>*}){(core::Iterator<core::int*>*) →* core::List<dynamic>*};
+ core::List<dynamic> list = [@vm.direct-call.metadata=#lib::B._foo] [@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic> (skip check)] new self::B::•().{self::B::_foo}([@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<dart.core::int>] [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int>] core::_GrowableList::_literal3<core::int>(1, 2, 3).{core::Iterable::iterator}{core::Iterator<core::int>}){(core::Iterator<core::int>) → core::List<dynamic>};
core::print(list);
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_37719.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/regress_37719.dart.expect
index 577315f..35c9ce8 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/regress_37719.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_37719.dart.expect
@@ -1,8 +1,8 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
-[@vm.unboxing-info.metadata=(b)->i]static method foo([@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int*>] core::List<core::int*>* x) → dynamic
- return [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] 1.{core::num::+}([@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=int? (skip check)] x.{core::List::[]}(0){(core::int*) →* core::int*}){(core::num*) →* core::int*};
+[@vm.unboxing-info.metadata=(b)->i]static method foo([@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int>] core::List<core::int> x) → dynamic
+ return [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] 1.{core::num::+}([@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=int? (skip check)] x.{core::List::[]}(0){(core::int) → core::int}){(core::num) → core::int};
static method main() → dynamic
- return [@vm.inferred-type.metadata=dart.core::Null? (value: null)] core::print([@vm.inferred-type.metadata=int] self::foo([@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int*>] core::_GrowableList::_literal1<core::int*>(1)));
+ return [@vm.inferred-type.metadata=dart.core::Null? (value: null)] core::print([@vm.inferred-type.metadata=int] self::foo([@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int>] core::_GrowableList::_literal1<core::int>(1)));
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_41452_nnbd_strong.dart b/pkg/vm/testcases/transformations/type_flow/transformer/regress_41452_nnbd_strong.dart
index bc79497..03ba604 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/regress_41452_nnbd_strong.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_41452_nnbd_strong.dart
@@ -4,9 +4,7 @@
// Regression test for https://github.com/dart-lang/sdk/issues/41452.
// Tests handling of null initializer of covariant field.
-// This test requires non-nullable experiment and NNBD strong mode.
-
-// @dart = 2.10
+// This test requires sound null safety.
class _SplayTreeNode<Node extends _SplayTreeNode<Node>> {
Node? left;
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_41452_nnbd_strong.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/regress_41452_nnbd_strong.dart.expect
index 89b2f4f..162174d 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/regress_41452_nnbd_strong.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_41452_nnbd_strong.dart.expect
@@ -19,8 +19,7 @@
;
[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] method add(generic-covariant-impl self::_SplayTree::Node n) → dynamic {
self::_SplayTree::Node? root = [@vm.direct-call.metadata=#lib::SplayTreeMap._root] [@vm.inferred-type.metadata=#lib::_SplayTreeMapNode<dynamic>] this.{self::_SplayTree::_root}{self::_SplayTree::Node?};
- if(false)
- return;
+ ;
core::print([@vm.direct-call.metadata=#lib::_SplayTreeNode.left] [@vm.inferred-type.metadata=dart.core::Null? (value: null)] root{self::_SplayTree::Node}.{self::_SplayTreeNode::left}{self::_SplayTree::Node?});
}
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:5] abstract get /*isLegacy*/ _root() → self::_SplayTree::Node?;
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_42413.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/regress_42413.dart.expect
index b0bcba0..e29a055 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/regress_42413.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_42413.dart.expect
@@ -1,25 +1,25 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
import "dart:_internal" as _in;
class B extends core::Object {
- synthetic constructor •() → self::B*
+ synthetic constructor •() → self::B
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] [@vm.unboxing-info.metadata=()->i] get x() → dynamic
return 0;
}
class A extends core::Object {
-[@vm.inferred-type.metadata=dart.core::_GrowableList?<#lib::B*>] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:2,getterSelectorId:3] field dynamic list = null;
- constructor •() → self::A*
+[@vm.inferred-type.metadata=dart.core::_GrowableList?<#lib::B>] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:2,getterSelectorId:3] field dynamic list = null;
+ constructor •() → self::A
: super core::Object::•() {
- [@vm.direct-call.metadata=#lib::A.list] [@vm.inferred-type.metadata=!? (skip check)] this.{self::A::list} = [@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::B*>] core::_GrowableList::_literal1<self::B*>(new self::B::•());
+ [@vm.direct-call.metadata=#lib::A.list] [@vm.inferred-type.metadata=!? (skip check)] this.{self::A::list} = [@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::B>] core::_GrowableList::_literal1<self::B>(new self::B::•());
}
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5] @#C3
method forIn() → void {
{
- core::Iterator<dynamic>* :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator??] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::B*>] _in::unsafeCast<core::Iterable<dynamic>*>([@vm.direct-call.metadata=#lib::A.list] [@vm.inferred-type.metadata=dart.core::_GrowableList?<#lib::B*>] this.{self::A::list}{dynamic}).{core::Iterable::iterator}{core::Iterator<dynamic>*};
+ core::Iterator<dynamic> :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator??] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::B>] _in::unsafeCast<core::Iterable<dynamic>>([@vm.direct-call.metadata=#lib::A.list] [@vm.inferred-type.metadata=dart.core::_GrowableList?<#lib::B>] this.{self::A::list}{dynamic}).{core::Iterable::iterator}{core::Iterator<dynamic>};
for (; [@vm.direct-call.metadata=dart._internal::ListIterator.moveNext] [@vm.inferred-type.metadata=dart.core::bool (skip check)] :sync-for-iterator.{core::Iterator::moveNext}(){() → core::bool}; ) {
dynamic e = [@vm.direct-call.metadata=dart._internal::ListIterator.current] [@vm.inferred-type.metadata=#lib::B?] :sync-for-iterator.{core::Iterator::current}{dynamic};
core::print([@vm.direct-call.metadata=#lib::B.x??] [@vm.inferred-type.metadata=dart.core::_Smi (value: 0) (receiver not int)] e{dynamic}.x);
@@ -28,15 +28,15 @@
}
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7] @#C3
method cLoop() → void {
- for (core::int* i = 0; [@vm.direct-call.metadata=dart.core::_IntegerImplementation.<] [@vm.inferred-type.metadata=dart.core::bool (skip check)] i.{core::num::<}(_in::unsafeCast<core::num*>([@vm.direct-call.metadata=dart.core::_GrowableList.length??] [@vm.inferred-type.metadata=dart.core::_Smi (receiver not int)] [@vm.direct-call.metadata=#lib::A.list] [@vm.inferred-type.metadata=dart.core::_GrowableList?<#lib::B*>] this.{self::A::list}{dynamic}{dynamic}.length)){(core::num*) →* core::bool*}; i = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(1){(core::num*) →* core::int*}) {
- final dynamic e = [@vm.direct-call.metadata=dart.core::_GrowableList.[]??] [@vm.inferred-type.metadata=#lib::B? (receiver not int)] [@vm.direct-call.metadata=#lib::A.list] [@vm.inferred-type.metadata=dart.core::_GrowableList?<#lib::B*>] this.{self::A::list}{dynamic}{dynamic}.[](i);
+ for (core::int i = 0; [@vm.direct-call.metadata=dart.core::_IntegerImplementation.<] [@vm.inferred-type.metadata=dart.core::bool (skip check)] i.{core::num::<}(_in::unsafeCast<core::num>([@vm.direct-call.metadata=dart.core::_GrowableList.length??] [@vm.inferred-type.metadata=dart.core::_Smi (receiver not int)] [@vm.direct-call.metadata=#lib::A.list] [@vm.inferred-type.metadata=dart.core::_GrowableList?<#lib::B>] this.{self::A::list}{dynamic}{dynamic}.length)){(core::num) → core::bool}; i = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(1){(core::num) → core::int}) {
+ final dynamic e = [@vm.direct-call.metadata=dart.core::_GrowableList.[]??] [@vm.inferred-type.metadata=#lib::B? (receiver not int)] [@vm.direct-call.metadata=#lib::A.list] [@vm.inferred-type.metadata=dart.core::_GrowableList?<#lib::B>] this.{self::A::list}{dynamic}{dynamic}.[](i);
core::print([@vm.direct-call.metadata=#lib::B.x??] [@vm.inferred-type.metadata=dart.core::_Smi (value: 0) (receiver not int)] e{dynamic}.x);
}
}
}
static method main() → void {
- [@vm.direct-call.metadata=#lib::A.forIn] [@vm.inferred-type.metadata=!? (skip check)] new self::A::•().{self::A::forIn}(){() →* void};
- [@vm.direct-call.metadata=#lib::A.cLoop] [@vm.inferred-type.metadata=!? (skip check)] new self::A::•().{self::A::cLoop}(){() →* void};
+ [@vm.direct-call.metadata=#lib::A.forIn] [@vm.inferred-type.metadata=!? (skip check)] new self::A::•().{self::A::forIn}(){() → void};
+ [@vm.direct-call.metadata=#lib::A.cLoop] [@vm.inferred-type.metadata=!? (skip check)] new self::A::•().{self::A::cLoop}(){() → void};
}
constants {
#C1 = "vm:never-inline"
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_1_test.dart b/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_1_test.dart
index 65d7485..add07b4 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_1_test.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_1_test.dart
@@ -10,12 +10,12 @@
class A {
@pragma("vm:never-inline")
- void foo(/* boxed */ int x) => Expect.isTrue(x.isOdd);
+ void foo(/* boxed */ int? x) => Expect.isTrue(x!.isOdd);
}
class B {
@pragma("vm:never-inline")
- void foo(/* unboxed */ int x) => Expect.isTrue(x.isOdd);
+ void foo(/* unboxed */ int? x) => Expect.isTrue(x!.isOdd);
}
class C extends A implements B {}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_1_test.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_1_test.dart.expect
index 16d4a2a..9d24274 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_1_test.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_1_test.dart.expect
@@ -1,48 +1,49 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
import "package:expect/expect.dart" as exp;
+import "dart:_internal" as _in;
import "dart:math" as math;
import "dart:math";
import "package:expect/expect.dart";
class A extends core::Object {
- synthetic constructor •() → self::A*
+ synthetic constructor •() → self::A
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] @#C3
- method foo([@vm.inferred-type.metadata=int?] core::int* x) → void
- return [@vm.inferred-type.metadata=dart.core::Null? (value: null)] exp::Expect::isTrue([@vm.direct-call.metadata=dart.core::_IntegerImplementation.isOdd??] [@vm.inferred-type.metadata=dart.core::bool] x.{core::int::isOdd}{core::bool*});
+ method foo([@vm.inferred-type.metadata=int?] core::int? x) → void
+ return [@vm.inferred-type.metadata=dart.core::Null? (value: null)] exp::Expect::isTrue([@vm.direct-call.metadata=dart.core::_IntegerImplementation.isOdd] [@vm.inferred-type.metadata=dart.core::bool] x!.{core::int::isOdd}{core::bool});
}
class B extends core::Object {
- synthetic constructor •() → self::B*
+ synthetic constructor •() → self::B
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] @#C3
- method foo([@vm.inferred-type.metadata=int] core::int* x) → void
- return [@vm.inferred-type.metadata=dart.core::Null? (value: null)] exp::Expect::isTrue([@vm.direct-call.metadata=dart.core::_IntegerImplementation.isOdd] [@vm.inferred-type.metadata=dart.core::bool] x.{core::int::isOdd}{core::bool*});
+ method foo([@vm.inferred-type.metadata=int] core::int? x) → void
+ return [@vm.inferred-type.metadata=dart.core::Null? (value: null)] exp::Expect::isTrue([@vm.direct-call.metadata=dart.core::_IntegerImplementation.isOdd] [@vm.inferred-type.metadata=dart.core::bool] _in::unsafeCast<core::int>(x).{core::int::isOdd}{core::bool});
}
class C extends self::A implements self::B {
- synthetic constructor •() → self::C*
+ synthetic constructor •() → self::C
: super self::A::•()
;
}
-[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool* alwaysFalse = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object*) →* core::bool*} 2;
+[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool alwaysFalse = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object) → core::bool} 2;
static method main() → dynamic {
- final math::Random* r = [@vm.inferred-type.metadata=dart.math::_Random] math::Random::•();
+ final math::Random r = [@vm.inferred-type.metadata=dart.math::_Random] math::Random::•();
if([@vm.inferred-type.metadata=dart.core::bool?] self::alwaysFalse) {
- [@vm.direct-call.metadata=#lib::A.foo] [@vm.inferred-type.metadata=!? (skip check)] new self::A::•().{self::A::foo}([@vm.direct-call.metadata=dart.math::_Random.nextInt] [@vm.inferred-type.metadata=int (skip check)] r.{math::Random::nextInt}(10){(core::int*) →* core::int*}){(core::int*) →* void};
- [@vm.direct-call.metadata=#lib::B.foo] [@vm.inferred-type.metadata=!? (skip check)] new self::B::•().{self::B::foo}([@vm.direct-call.metadata=dart.math::_Random.nextInt] [@vm.inferred-type.metadata=int (skip check)] r.{math::Random::nextInt}(10){(core::int*) →* core::int*}){(core::int*) →* void};
- [@vm.direct-call.metadata=#lib::A.foo] [@vm.inferred-type.metadata=!? (skip check)] new self::A::•().{self::A::foo}(null){(core::int*) →* void};
+ [@vm.direct-call.metadata=#lib::A.foo] [@vm.inferred-type.metadata=!? (skip check)] new self::A::•().{self::A::foo}([@vm.direct-call.metadata=dart.math::_Random.nextInt] [@vm.inferred-type.metadata=int (skip check)] r.{math::Random::nextInt}(10){(core::int) → core::int}){(core::int?) → void};
+ [@vm.direct-call.metadata=#lib::B.foo] [@vm.inferred-type.metadata=!? (skip check)] new self::B::•().{self::B::foo}([@vm.direct-call.metadata=dart.math::_Random.nextInt] [@vm.inferred-type.metadata=int (skip check)] r.{math::Random::nextInt}(10){(core::int) → core::int}){(core::int?) → void};
+ [@vm.direct-call.metadata=#lib::A.foo] [@vm.inferred-type.metadata=!? (skip check)] new self::A::•().{self::A::foo}(null){(core::int?) → void};
}
- final core::List<self::B*>* l = [@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::B*>] core::_GrowableList::_literal2<self::B*>(new self::B::•(), new self::C::•());
+ final core::List<self::B> l = [@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::B>] core::_GrowableList::_literal2<self::B>(new self::B::•(), new self::C::•());
{
- core::Iterator<self::B*>* :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::B*>] l.{core::Iterable::iterator}{core::Iterator<self::B*>*};
+ core::Iterator<self::B> :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::B>] l.{core::Iterable::iterator}{core::Iterator<self::B>};
for (; [@vm.direct-call.metadata=dart._internal::ListIterator.moveNext] [@vm.inferred-type.metadata=dart.core::bool (skip check)] :sync-for-iterator.{core::Iterator::moveNext}(){() → core::bool}; ) {
- self::B* b = [@vm.direct-call.metadata=dart._internal::ListIterator.current] :sync-for-iterator.{core::Iterator::current}{self::B*};
+ self::B b = [@vm.direct-call.metadata=dart._internal::ListIterator.current] :sync-for-iterator.{core::Iterator::current}{self::B};
{
- b.{self::B::foo}(13){(core::int*) →* void};
+ b.{self::B::foo}(13){(core::int?) → void};
}
}
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_2_test.dart b/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_2_test.dart
index 824ac78..01bede8 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_2_test.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_2_test.dart
@@ -10,12 +10,12 @@
class A {
@pragma("vm:never-inline")
- void bar(/* unboxed */ int x) => Expect.isTrue(x.isOdd);
+ void bar(/* unboxed */ int? x) => Expect.isTrue(x!.isOdd);
}
class B {
@pragma("vm:never-inline")
- void bar(/* boxed */ int x) => Expect.isTrue(x.isOdd);
+ void bar(/* boxed */ int? x) => Expect.isTrue(x!.isOdd);
}
class C extends A implements B {}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_2_test.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_2_test.dart.expect
index dff8e38..ae6258b 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_2_test.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_2_test.dart.expect
@@ -1,48 +1,49 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
import "package:expect/expect.dart" as exp;
+import "dart:_internal" as _in;
import "dart:math" as math;
import "dart:math";
import "package:expect/expect.dart";
class A extends core::Object {
- synthetic constructor •() → self::A*
+ synthetic constructor •() → self::A
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] @#C3
- method bar([@vm.inferred-type.metadata=int] core::int* x) → void
- return [@vm.inferred-type.metadata=dart.core::Null? (value: null)] exp::Expect::isTrue([@vm.direct-call.metadata=dart.core::_IntegerImplementation.isOdd] [@vm.inferred-type.metadata=dart.core::bool] x.{core::int::isOdd}{core::bool*});
+ method bar([@vm.inferred-type.metadata=int] core::int? x) → void
+ return [@vm.inferred-type.metadata=dart.core::Null? (value: null)] exp::Expect::isTrue([@vm.direct-call.metadata=dart.core::_IntegerImplementation.isOdd] [@vm.inferred-type.metadata=dart.core::bool] _in::unsafeCast<core::int>(x).{core::int::isOdd}{core::bool});
}
class B extends core::Object {
- synthetic constructor •() → self::B*
+ synthetic constructor •() → self::B
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] @#C3
- method bar([@vm.inferred-type.metadata=int?] core::int* x) → void
- return [@vm.inferred-type.metadata=dart.core::Null? (value: null)] exp::Expect::isTrue([@vm.direct-call.metadata=dart.core::_IntegerImplementation.isOdd??] [@vm.inferred-type.metadata=dart.core::bool] x.{core::int::isOdd}{core::bool*});
+ method bar([@vm.inferred-type.metadata=int?] core::int? x) → void
+ return [@vm.inferred-type.metadata=dart.core::Null? (value: null)] exp::Expect::isTrue([@vm.direct-call.metadata=dart.core::_IntegerImplementation.isOdd] [@vm.inferred-type.metadata=dart.core::bool] x!.{core::int::isOdd}{core::bool});
}
class C extends self::A implements self::B {
- synthetic constructor •() → self::C*
+ synthetic constructor •() → self::C
: super self::A::•()
;
}
-[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool* alwaysFalse = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object*) →* core::bool*} 2;
+[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool alwaysFalse = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object) → core::bool} 2;
static method main() → dynamic {
- final math::Random* r = [@vm.inferred-type.metadata=dart.math::_Random] math::Random::•();
+ final math::Random r = [@vm.inferred-type.metadata=dart.math::_Random] math::Random::•();
if([@vm.inferred-type.metadata=dart.core::bool?] self::alwaysFalse) {
- [@vm.direct-call.metadata=#lib::A.bar] [@vm.inferred-type.metadata=!? (skip check)] new self::A::•().{self::A::bar}([@vm.direct-call.metadata=dart.math::_Random.nextInt] [@vm.inferred-type.metadata=int (skip check)] r.{math::Random::nextInt}(10){(core::int*) →* core::int*}){(core::int*) →* void};
- [@vm.direct-call.metadata=#lib::B.bar] [@vm.inferred-type.metadata=!? (skip check)] new self::B::•().{self::B::bar}([@vm.direct-call.metadata=dart.math::_Random.nextInt] [@vm.inferred-type.metadata=int (skip check)] r.{math::Random::nextInt}(10){(core::int*) →* core::int*}){(core::int*) →* void};
- [@vm.direct-call.metadata=#lib::B.bar] [@vm.inferred-type.metadata=!? (skip check)] new self::B::•().{self::B::bar}(null){(core::int*) →* void};
+ [@vm.direct-call.metadata=#lib::A.bar] [@vm.inferred-type.metadata=!? (skip check)] new self::A::•().{self::A::bar}([@vm.direct-call.metadata=dart.math::_Random.nextInt] [@vm.inferred-type.metadata=int (skip check)] r.{math::Random::nextInt}(10){(core::int) → core::int}){(core::int?) → void};
+ [@vm.direct-call.metadata=#lib::B.bar] [@vm.inferred-type.metadata=!? (skip check)] new self::B::•().{self::B::bar}([@vm.direct-call.metadata=dart.math::_Random.nextInt] [@vm.inferred-type.metadata=int (skip check)] r.{math::Random::nextInt}(10){(core::int) → core::int}){(core::int?) → void};
+ [@vm.direct-call.metadata=#lib::B.bar] [@vm.inferred-type.metadata=!? (skip check)] new self::B::•().{self::B::bar}(null){(core::int?) → void};
}
- final core::List<self::B*>* l = [@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::B*>] core::_GrowableList::_literal2<self::B*>(new self::B::•(), new self::C::•());
+ final core::List<self::B> l = [@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::B>] core::_GrowableList::_literal2<self::B>(new self::B::•(), new self::C::•());
{
- core::Iterator<self::B*>* :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::B*>] l.{core::Iterable::iterator}{core::Iterator<self::B*>*};
+ core::Iterator<self::B> :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::B>] l.{core::Iterable::iterator}{core::Iterator<self::B>};
for (; [@vm.direct-call.metadata=dart._internal::ListIterator.moveNext] [@vm.inferred-type.metadata=dart.core::bool (skip check)] :sync-for-iterator.{core::Iterator::moveNext}(){() → core::bool}; ) {
- self::B* b = [@vm.direct-call.metadata=dart._internal::ListIterator.current] :sync-for-iterator.{core::Iterator::current}{self::B*};
+ self::B b = [@vm.direct-call.metadata=dart._internal::ListIterator.current] :sync-for-iterator.{core::Iterator::current}{self::B};
{
- b.{self::B::bar}(13){(core::int*) →* void};
+ b.{self::B::bar}(13){(core::int?) → void};
}
}
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_45324.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/regress_45324.dart.expect
index f097822..a7e00ed 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/regress_45324.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_45324.dart.expect
@@ -1,20 +1,20 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
class A extends core::Object /*hasConstConstructor*/ {
-[@vm.inferred-type.metadata=dart.core::_Smi (value: 1)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] [@vm.unboxing-info.metadata=()->i] final field core::int* targetPlatform;
+[@vm.inferred-type.metadata=dart.core::_Smi (value: 1)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] [@vm.unboxing-info.metadata=()->i] final field core::int targetPlatform;
}
class X extends core::Object implements self::A {
- synthetic constructor •() → self::X*
+ synthetic constructor •() → self::X
: super core::Object::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] [@vm.unboxing-info.metadata=()->i] get targetPlatform() → core::int*
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] [@vm.unboxing-info.metadata=()->i] get targetPlatform() → core::int
return 2;
}
-[@vm.inferred-type.metadata=#lib::X?]static field self::A* a = new self::X::•();
+[@vm.inferred-type.metadata=#lib::X?]static field self::A a = new self::X::•();
static method main() → void {
- core::print([@vm.direct-call.metadata=#lib::X.targetPlatform??] [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] [@vm.inferred-type.metadata=#lib::X?] self::a.{self::A::targetPlatform}{core::int*});
+ core::print([@vm.direct-call.metadata=#lib::X.targetPlatform??] [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] [@vm.inferred-type.metadata=#lib::X?] self::a.{self::A::targetPlatform}{core::int});
core::print(#C2);
}
constants {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_45324_2.dart b/pkg/vm/testcases/transformations/type_flow/transformer/regress_45324_2.dart
index 6c4d972..a655aa5 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/regress_45324_2.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_45324_2.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.12
-
class A {
void doTest(Z a) {
print(a.appName);
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_46461.dart b/pkg/vm/testcases/transformations/type_flow/transformer/regress_46461.dart
index d50e669..4b25bd4 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/regress_46461.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_46461.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart=2.12
-
enum A { a1, a2 }
class B {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter16182.dart b/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter16182.dart
index 81c386e..f565760 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter16182.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter16182.dart
@@ -7,7 +7,7 @@
import "package:expect/expect.dart";
-bool ok;
+bool? ok;
class T1 {
// Should be reachable.
@@ -17,7 +17,7 @@
}
class A1 {
- T1 foo;
+ T1? foo;
void call([a1, a2, a3, a4, a5]) {
foo = a5;
@@ -33,7 +33,7 @@
bb.aa1(1, 2, 3, 4, new T1());
ok = false;
- bb.aa1.foo.doTest1();
+ bb.aa1.foo!.doTest1();
Expect.isTrue(ok);
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter16182.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter16182.dart.expect
index 15a6a84..fa24c7a 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter16182.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter16182.dart.expect
@@ -1,4 +1,4 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
import "dart:_internal" as _in;
@@ -7,7 +7,7 @@
import "package:expect/expect.dart";
class T1 extends core::Object {
- synthetic constructor •() → self::T1*
+ synthetic constructor •() → self::T1
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method doTest1() → void {
@@ -15,22 +15,22 @@
}
}
class A1 extends core::Object {
-[@vm.inferred-type.metadata=#lib::T1?] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] field self::T1* foo = null;
- synthetic constructor •() → self::A1*
+[@vm.inferred-type.metadata=#lib::T1?] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] field self::T1? foo = null;
+ synthetic constructor •() → self::A1
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] method call([dynamic a1 = #C1, dynamic a2 = #C1, dynamic a3 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a4 = #C1, [@vm.inferred-type.metadata=#lib::T1?] dynamic a5 = #C1]) → void {
- [@vm.direct-call.metadata=#lib::A1.foo] [@vm.inferred-type.metadata=!? (skip check)] this.{self::A1::foo} = _in::unsafeCast<self::T1*>(a5);
+ [@vm.direct-call.metadata=#lib::A1.foo] [@vm.inferred-type.metadata=!? (skip check)] this.{self::A1::foo} = _in::unsafeCast<self::T1?>(a5);
}
}
class B1 extends core::Object {
-[@vm.inferred-type.metadata=#lib::A1] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] field self::A1* aa1;
- synthetic constructor •() → self::B1*
+[@vm.inferred-type.metadata=#lib::A1] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] field self::A1 aa1;
+ synthetic constructor •() → self::B1
: self::B1::aa1 = new self::A1::•(), super core::Object::•()
;
}
class T2 extends core::Object {
- synthetic constructor •() → self::T2*
+ synthetic constructor •() → self::T2
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10] method doTest2() → void {
@@ -39,7 +39,7 @@
}
class A2 extends core::Object {
[@vm.inferred-type.metadata=#lib::T2?] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] field dynamic foo = null;
- synthetic constructor •() → self::A2*
+ synthetic constructor •() → self::A2
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14] method call([dynamic a1 = #C1, dynamic a2 = #C1, dynamic a3 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a4 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a5 = #C1, [@vm.inferred-type.metadata=#lib::T2?] dynamic a6 = #C1]) → void {
@@ -48,14 +48,14 @@
}
abstract class B2Base extends core::Object {
[@vm.inferred-type.metadata=#lib::A2] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:15,getterSelectorId:16] field dynamic _aa;
- synthetic constructor •() → self::B2Base*
+ synthetic constructor •() → self::B2Base
: self::B2Base::_aa = new self::A2::•(), super core::Object::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:17] get aa2() → dynamic
return [@vm.direct-call.metadata=#lib::B2Base._aa] [@vm.inferred-type.metadata=#lib::A2] this.{self::B2Base::_aa}{dynamic};
}
class B2 extends self::B2Base {
- synthetic constructor •() → self::B2*
+ synthetic constructor •() → self::B2
: super self::B2Base::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:18,getterSelectorId:19] method doSuperCall() → void {
@@ -63,7 +63,7 @@
}
}
class T3 extends core::Object {
- synthetic constructor •() → self::T3*
+ synthetic constructor •() → self::T3
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:20,getterSelectorId:21] method doTest3() → void {
@@ -72,7 +72,7 @@
}
class A3 extends core::Object {
[@vm.inferred-type.metadata=#lib::T3?] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:22,getterSelectorId:23] field dynamic foo = null;
- synthetic constructor •() → self::A3*
+ synthetic constructor •() → self::A3
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:24,getterSelectorId:25] method call([dynamic a1 = #C1, dynamic a2 = #C1, dynamic a3 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a4 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a5 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a6 = #C1, [@vm.inferred-type.metadata=#lib::T3?] dynamic a7 = #C1]) → void {
@@ -80,13 +80,13 @@
}
}
class B3 extends core::Object {
-[@vm.inferred-type.metadata=#lib::A3] [@vm.procedure-attributes.metadata=hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:26,getterSelectorId:27] field self::A3* aa3;
- synthetic constructor •() → self::B3*
+[@vm.inferred-type.metadata=#lib::A3] [@vm.procedure-attributes.metadata=hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:26,getterSelectorId:27] field self::A3 aa3;
+ synthetic constructor •() → self::B3
: self::B3::aa3 = new self::A3::•(), super core::Object::•()
;
}
class T4 extends core::Object {
- synthetic constructor •() → self::T4*
+ synthetic constructor •() → self::T4
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:28,getterSelectorId:29] method doTest4() → void {
@@ -95,7 +95,7 @@
}
class A4 extends core::Object {
[@vm.inferred-type.metadata=#lib::T4?] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:30,getterSelectorId:31] field dynamic foo = null;
- synthetic constructor •() → self::A4*
+ synthetic constructor •() → self::A4
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:32,getterSelectorId:33] method call([dynamic a1 = #C1, dynamic a2 = #C1, dynamic a3 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a4 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a5 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a6 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a7 = #C1, [@vm.inferred-type.metadata=#lib::T4?] dynamic a8 = #C1]) → void {
@@ -104,27 +104,27 @@
}
class B4 extends core::Object {
[@vm.inferred-type.metadata=#lib::A4] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:34,getterSelectorId:35] field dynamic _aa;
- synthetic constructor •() → self::B4*
+ synthetic constructor •() → self::B4
: self::B4::_aa = new self::A4::•(), super core::Object::•()
;
[@vm.procedure-attributes.metadata=hasThisUses:false,hasTearOffUses:false,getterSelectorId:36] get aa4() → dynamic
return [@vm.direct-call.metadata=#lib::B4._aa] [@vm.inferred-type.metadata=#lib::A4] this.{self::B4::_aa}{dynamic};
}
-[@vm.inferred-type.metadata=dart.core::bool?]static field core::bool* ok;
+[@vm.inferred-type.metadata=dart.core::bool?]static field core::bool? ok;
[@vm.inferred-type.metadata=#lib::B3?]static field dynamic bb3 = new self::B3::•();
-[@vm.inferred-type.metadata=dart.core::_Closure?]static field core::Function* unknown3 = () → dynamic => self::bb3;
+[@vm.inferred-type.metadata=dart.core::_Closure?]static field core::Function unknown3 = () → dynamic => self::bb3;
[@vm.inferred-type.metadata=#lib::B4?]static field dynamic bb4 = new self::B4::•();
-[@vm.inferred-type.metadata=dart.core::_Closure?]static field core::Function* unknown4 = () → dynamic => self::bb4;
+[@vm.inferred-type.metadata=dart.core::_Closure?]static field core::Function unknown4 = () → dynamic => self::bb4;
static method test1() → void {
- self::B1* bb = new self::B1::•();
- let final self::B1* #t1 = bb in let final core::int* #t2 = 1 in let final core::int* #t3 = 2 in let final core::int* #t4 = 3 in let final core::int* #t5 = 4 in let final self::T1* #t6 = new self::T1::•() in [@vm.direct-call.metadata=#lib::A1.call] [@vm.inferred-type.metadata=!? (skip check)] [@vm.direct-call.metadata=#lib::B1.aa1] [@vm.inferred-type.metadata=#lib::A1] #t1.{self::B1::aa1}{self::A1*}.{self::A1::call}(#t2, #t3, #t4, #t5, #t6){([dynamic, dynamic, dynamic, dynamic, dynamic]) →* void};
+ self::B1 bb = new self::B1::•();
+ let final self::B1 #t1 = bb in let final core::int #t2 = 1 in let final core::int #t3 = 2 in let final core::int #t4 = 3 in let final core::int #t5 = 4 in let final self::T1 #t6 = new self::T1::•() in [@vm.direct-call.metadata=#lib::A1.call] [@vm.inferred-type.metadata=!? (skip check)] [@vm.direct-call.metadata=#lib::B1.aa1] [@vm.inferred-type.metadata=#lib::A1] #t1.{self::B1::aa1}{self::A1}.{self::A1::call}(#t2, #t3, #t4, #t5, #t6){([dynamic, dynamic, dynamic, dynamic, dynamic]) → void};
self::ok = false;
- [@vm.direct-call.metadata=#lib::T1.doTest1??] [@vm.inferred-type.metadata=!? (skip check)] [@vm.direct-call.metadata=#lib::A1.foo] [@vm.inferred-type.metadata=#lib::T1?] [@vm.direct-call.metadata=#lib::B1.aa1] [@vm.inferred-type.metadata=#lib::A1] bb.{self::B1::aa1}{self::A1*}.{self::A1::foo}{self::T1*}.{self::T1::doTest1}(){() →* void};
+ [@vm.direct-call.metadata=#lib::T1.doTest1] [@vm.inferred-type.metadata=!? (skip check)] [@vm.direct-call.metadata=#lib::A1.foo] [@vm.inferred-type.metadata=#lib::T1?] [@vm.direct-call.metadata=#lib::B1.aa1] [@vm.inferred-type.metadata=#lib::A1] bb.{self::B1::aa1}{self::A1}.{self::A1::foo}{self::T1?}!.{self::T1::doTest1}(){() → void};
exp::Expect::isTrue([@vm.inferred-type.metadata=dart.core::bool?] self::ok);
}
static method test2() → void {
- self::B2* bb = new self::B2::•();
- [@vm.direct-call.metadata=#lib::B2.doSuperCall] [@vm.inferred-type.metadata=!? (skip check)] bb.{self::B2::doSuperCall}(){() →* void};
+ self::B2 bb = new self::B2::•();
+ [@vm.direct-call.metadata=#lib::B2.doSuperCall] [@vm.inferred-type.metadata=!? (skip check)] bb.{self::B2::doSuperCall}(){() → void};
self::ok = false;
[@vm.direct-call.metadata=#lib::T2.doTest2??] [@vm.inferred-type.metadata=!? (receiver not int)] [@vm.direct-call.metadata=#lib::A2.foo] [@vm.inferred-type.metadata=#lib::T2? (receiver not int)] [@vm.direct-call.metadata=#lib::B2Base.aa2] [@vm.inferred-type.metadata=#lib::A2] bb.{self::B2Base::aa2}{dynamic}{dynamic}.foo{dynamic}.doTest2();
exp::Expect::isTrue([@vm.inferred-type.metadata=dart.core::bool?] self::ok);
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter57213.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter57213.dart.expect
index 4e27a60..a079cbe 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter57213.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter57213.dart.expect
@@ -1,30 +1,30 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
@#C3
class A extends core::Object {
- constructor •() → self::A*
+ constructor •() → self::A
: super core::Object::•()
;
}
class B extends self::A {
- constructor •() → self::B*
+ constructor •() → self::B
: super self::A::•()
;
}
abstract class C extends core::Object {
- constructor •() → self::C*
+ constructor •() → self::C
: super core::Object::•()
;
}
abstract class D extends self::C {
- constructor •() → self::D*
+ constructor •() → self::D
: super self::C::•()
;
}
class E extends self::D {
- constructor •() → self::E*
+ constructor •() → self::E
: super self::D::•()
;
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter81068.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter81068.dart.expect
index a63904b..37b6a68 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter81068.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter81068.dart.expect
@@ -1,41 +1,41 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
import "dart:async" as asy;
import "dart:async";
-abstract class A<T extends core::Object* = dynamic> extends core::Object {
- synthetic constructor •() → self::A<self::A::T*>*
+abstract class A<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::A<self::A::T%>
: super core::Object::•()
;
}
-class B<T extends core::Object* = dynamic> extends self::A<core::String*> implements asy::Future<self::B::T*> {
- synthetic constructor •() → self::B<self::B::T*>*
+class B<T extends core::Object? = dynamic> extends self::A<core::String> implements asy::Future<self::B::T%> {
+ synthetic constructor •() → self::B<self::B::T%>
: super self::A::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method noSuchMethod(core::Invocation* i) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method noSuchMethod(core::Invocation i) → dynamic
return throw "Not implemented";
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] no-such-method-forwarder method then<R extends core::Object* = dynamic>((self::B::T*) →* FutureOr<self::B::then::R*>* onValue, {core::Function* onError = #C1}) → asy::Future<self::B::then::R*>*
- return [@vm.direct-call.metadata=#lib::B.noSuchMethod] [@vm.inferred-type.metadata=! (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 0, core::List::unmodifiable<core::Type*>([@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::Type*>] core::_GrowableList::_literal1<core::Type*>(self::B::then::R*)), core::List::unmodifiable<dynamic>([@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic>] core::_GrowableList::_literal1<dynamic>(onValue)), [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C3: onError}))){(core::Invocation*) →* dynamic} as{TypeError,ForDynamic} asy::Future<self::B::then::R*>*;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] no-such-method-forwarder method catchError(core::Function* onError, {[@vm.inferred-type.metadata=dart.core::Null? (value: null)] (core::Object*) →* core::bool* test = #C1}) → asy::Future<self::B::T*>*
- return [@vm.direct-call.metadata=#lib::B.noSuchMethod] [@vm.inferred-type.metadata=! (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C4, 0, #C5, core::List::unmodifiable<dynamic>([@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic>] core::_GrowableList::_literal1<dynamic>(onError)), [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C6: test}))){(core::Invocation*) →* dynamic} as{TypeError,ForDynamic} asy::Future<self::B::T*>*;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] no-such-method-forwarder method whenComplete(() →* FutureOr<void>* action) → asy::Future<self::B::T*>*
- return [@vm.direct-call.metadata=#lib::B.noSuchMethod] [@vm.inferred-type.metadata=! (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C7, 0, #C5, core::List::unmodifiable<dynamic>([@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic>] core::_GrowableList::_literal1<dynamic>(action)), [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C9))){(core::Invocation*) →* dynamic} as{TypeError,ForDynamic} asy::Future<self::B::T*>*;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] no-such-method-forwarder method /* from org-dartlang-sdk:///sdk/lib/async/future.dart */ catchError(core::Function onError) → asy::Future<self::B::T%>
+ return [@vm.direct-call.metadata=#lib::B.noSuchMethod] [@vm.inferred-type.metadata=! (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 0, #C2, core::List::unmodifiable<dynamic>([@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic>] core::_GrowableList::_literal1<dynamic>(onError)), [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C3: #C4}))){(core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<self::B::T%>;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] no-such-method-forwarder method /* from org-dartlang-sdk:///sdk/lib/async/future.dart */ whenComplete(() → FutureOr<void>action) → asy::Future<self::B::T%>
+ return [@vm.direct-call.metadata=#lib::B.noSuchMethod] [@vm.inferred-type.metadata=! (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C2, core::List::unmodifiable<dynamic>([@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic>] core::_GrowableList::_literal1<dynamic>(action)), [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))){(core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<self::B::T%>;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] no-such-method-forwarder method /* from org-dartlang-sdk:///sdk/lib/async/future.dart */ then<R extends core::Object? = dynamic>((self::B::T%) → FutureOr<self::B::then::R%>onValue, {core::Function? onError = #C4}) → asy::Future<self::B::then::R%>
+ return [@vm.direct-call.metadata=#lib::B.noSuchMethod] [@vm.inferred-type.metadata=! (skip check)] this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, core::List::unmodifiable<core::Type*>([@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::Type*>] core::_GrowableList::_literal1<core::Type*>(self::B::then::R%)), core::List::unmodifiable<dynamic>([@vm.inferred-type.metadata=dart.core::_GrowableList<dynamic>] core::_GrowableList::_literal1<dynamic>(onValue)), [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dart.core::Symbol*, dynamic>] core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C9: onError}))){(core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} asy::Future<self::B::then::R%>;
}
-static method createB<T extends core::Object* = dynamic>() → self::B<dynamic>*
- return new self::B::•<self::createB::T*>();
+static method createB<T extends core::Object? = dynamic>() → self::B<dynamic>
+ return new self::B::•<self::createB::T%>();
static method main() → void {
- core::print([@vm.inferred-type.metadata=#lib::B<?>] self::createB<core::int*>() as FutureOr<core::double*>*);
+ core::print([@vm.inferred-type.metadata=#lib::B<?>] self::createB<core::int>() as{ForNonNullableByDefault} FutureOr<core::double>);
}
constants {
- #C1 = null
- #C2 = #then
- #C3 = #onError
- #C4 = #catchError
- #C5 = <core::Type*>[]
- #C6 = #test
- #C7 = #whenComplete
- #C8 = <dynamic>[]
- #C9 = core::_ImmutableMap<core::Symbol*, dynamic> {_kvPairs:#C8}
+ #C1 = #catchError
+ #C2 = <core::Type*>[]
+ #C3 = #test
+ #C4 = null
+ #C5 = #whenComplete
+ #C6 = <dynamic>[]
+ #C7 = core::_ImmutableMap<core::Symbol*, dynamic> {_kvPairs:#C6}
+ #C8 = #then
+ #C9 = #onError
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/selector_id_assignments.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/selector_id_assignments.dart.expect
index 39043c5..bba93d0 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/selector_id_assignments.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/selector_id_assignments.dart.expect
@@ -1,11 +1,11 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
abstract class X extends core::Object {
}
class A1 extends core::Object {
- synthetic constructor •() → self::A1*
+ synthetic constructor •() → self::A1
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method foo() → void {
@@ -13,12 +13,12 @@
}
}
class B1 extends self::A1 {
- synthetic constructor •() → self::B1*
+ synthetic constructor •() → self::B1
: super self::A1::•()
;
}
class C1 extends self::B1 {
- synthetic constructor •() → self::C1*
+ synthetic constructor •() → self::C1
: super self::B1::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method foo() → void {
@@ -26,7 +26,7 @@
}
}
class A2 extends core::Object {
- synthetic constructor •() → self::A2*
+ synthetic constructor •() → self::A2
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] method foo() → void {
@@ -34,7 +34,7 @@
}
}
class B2 extends self::A2 implements self::X {
- synthetic constructor •() → self::B2*
+ synthetic constructor •() → self::B2
: super self::A2::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] method foo() → void {
@@ -42,13 +42,13 @@
}
}
abstract class A3 extends core::Object {
- synthetic constructor •() → self::A3*
+ synthetic constructor •() → self::A3
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] abstract method foo() → void;
}
class B3 extends self::A3 implements self::X {
- synthetic constructor •() → self::B3*
+ synthetic constructor •() → self::B3
: super self::A3::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] method foo() → void {
@@ -56,7 +56,7 @@
}
}
class C3 extends core::Object implements self::A3 {
- synthetic constructor •() → self::C3*
+ synthetic constructor •() → self::C3
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] method foo() → void {
@@ -64,7 +64,7 @@
}
}
class A4 extends core::Object {
- synthetic constructor •() → self::A4*
+ synthetic constructor •() → self::A4
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] method foo() → void {
@@ -72,7 +72,7 @@
}
}
class B4 extends core::Object {
- synthetic constructor •() → self::B4*
+ synthetic constructor •() → self::B4
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] method foo() → void {
@@ -80,7 +80,7 @@
}
}
class C4 extends core::Object {
- synthetic constructor •() → self::C4*
+ synthetic constructor •() → self::C4
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] method foo() → void {
@@ -88,7 +88,7 @@
}
}
class D4 extends self::A4 implements self::B4 {
- synthetic constructor •() → self::D4*
+ synthetic constructor •() → self::D4
: super self::A4::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] method foo() → void {
@@ -96,57 +96,57 @@
}
}
class E4 extends self::C4 implements self::B4 {
- synthetic constructor •() → self::E4*
+ synthetic constructor •() → self::E4
: super self::C4::•()
;
}
static method main() → dynamic {
- core::List<self::A1*>* x1 = [@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::A1*>] core::_GrowableList::_literal3<self::A1*>(new self::A1::•(), new self::B1::•(), new self::C1::•());
+ core::List<self::A1> x1 = [@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::A1>] core::_GrowableList::_literal3<self::A1>(new self::A1::•(), new self::B1::•(), new self::C1::•());
{
- core::Iterator<self::A1*>* :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::A1*>] x1.{core::Iterable::iterator}{core::Iterator<self::A1*>*};
+ core::Iterator<self::A1> :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::A1>] x1.{core::Iterable::iterator}{core::Iterator<self::A1>};
for (; [@vm.direct-call.metadata=dart._internal::ListIterator.moveNext] [@vm.inferred-type.metadata=dart.core::bool (skip check)] :sync-for-iterator.{core::Iterator::moveNext}(){() → core::bool}; ) {
- self::A1* o = [@vm.direct-call.metadata=dart._internal::ListIterator.current] :sync-for-iterator.{core::Iterator::current}{self::A1*};
- o.{self::A1::foo}(){() →* void};
+ self::A1 o = [@vm.direct-call.metadata=dart._internal::ListIterator.current] :sync-for-iterator.{core::Iterator::current}{self::A1};
+ o.{self::A1::foo}(){() → void};
}
}
- core::List<self::A2*>* x2 = [@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::A2*>] core::_GrowableList::_literal2<self::A2*>(new self::A2::•(), new self::B2::•());
+ core::List<self::A2> x2 = [@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::A2>] core::_GrowableList::_literal2<self::A2>(new self::A2::•(), new self::B2::•());
{
- core::Iterator<self::A2*>* :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::A2*>] x2.{core::Iterable::iterator}{core::Iterator<self::A2*>*};
+ core::Iterator<self::A2> :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::A2>] x2.{core::Iterable::iterator}{core::Iterator<self::A2>};
for (; [@vm.direct-call.metadata=dart._internal::ListIterator.moveNext] [@vm.inferred-type.metadata=dart.core::bool (skip check)] :sync-for-iterator.{core::Iterator::moveNext}(){() → core::bool}; ) {
- self::A2* o = [@vm.direct-call.metadata=dart._internal::ListIterator.current] :sync-for-iterator.{core::Iterator::current}{self::A2*};
- o.{self::A2::foo}(){() →* void};
+ self::A2 o = [@vm.direct-call.metadata=dart._internal::ListIterator.current] :sync-for-iterator.{core::Iterator::current}{self::A2};
+ o.{self::A2::foo}(){() → void};
}
}
- core::List<self::A3*>* x3 = [@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::A3*>] core::_GrowableList::_literal2<self::A3*>(new self::B3::•(), new self::C3::•());
+ core::List<self::A3> x3 = [@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::A3>] core::_GrowableList::_literal2<self::A3>(new self::B3::•(), new self::C3::•());
{
- core::Iterator<self::A3*>* :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::A3*>] x3.{core::Iterable::iterator}{core::Iterator<self::A3*>*};
+ core::Iterator<self::A3> :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::A3>] x3.{core::Iterable::iterator}{core::Iterator<self::A3>};
for (; [@vm.direct-call.metadata=dart._internal::ListIterator.moveNext] [@vm.inferred-type.metadata=dart.core::bool (skip check)] :sync-for-iterator.{core::Iterator::moveNext}(){() → core::bool}; ) {
- self::A3* o = [@vm.direct-call.metadata=dart._internal::ListIterator.current] :sync-for-iterator.{core::Iterator::current}{self::A3*};
- o.{self::A3::foo}(){() →* void};
+ self::A3 o = [@vm.direct-call.metadata=dart._internal::ListIterator.current] :sync-for-iterator.{core::Iterator::current}{self::A3};
+ o.{self::A3::foo}(){() → void};
}
}
- core::List<self::A4*>* x4 = [@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::A4*>] core::_GrowableList::_literal2<self::A4*>(new self::A4::•(), new self::D4::•());
+ core::List<self::A4> x4 = [@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::A4>] core::_GrowableList::_literal2<self::A4>(new self::A4::•(), new self::D4::•());
{
- core::Iterator<self::A4*>* :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::A4*>] x4.{core::Iterable::iterator}{core::Iterator<self::A4*>*};
+ core::Iterator<self::A4> :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::A4>] x4.{core::Iterable::iterator}{core::Iterator<self::A4>};
for (; [@vm.direct-call.metadata=dart._internal::ListIterator.moveNext] [@vm.inferred-type.metadata=dart.core::bool (skip check)] :sync-for-iterator.{core::Iterator::moveNext}(){() → core::bool}; ) {
- self::A4* o = [@vm.direct-call.metadata=dart._internal::ListIterator.current] :sync-for-iterator.{core::Iterator::current}{self::A4*};
- o.{self::A4::foo}(){() →* void};
+ self::A4 o = [@vm.direct-call.metadata=dart._internal::ListIterator.current] :sync-for-iterator.{core::Iterator::current}{self::A4};
+ o.{self::A4::foo}(){() → void};
}
}
- core::List<self::B4*>* y4 = [@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::B4*>] core::_GrowableList::_literal3<self::B4*>(new self::B4::•(), new self::D4::•(), new self::E4::•());
+ core::List<self::B4> y4 = [@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::B4>] core::_GrowableList::_literal3<self::B4>(new self::B4::•(), new self::D4::•(), new self::E4::•());
{
- core::Iterator<self::B4*>* :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::B4*>] y4.{core::Iterable::iterator}{core::Iterator<self::B4*>*};
+ core::Iterator<self::B4> :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::B4>] y4.{core::Iterable::iterator}{core::Iterator<self::B4>};
for (; [@vm.direct-call.metadata=dart._internal::ListIterator.moveNext] [@vm.inferred-type.metadata=dart.core::bool (skip check)] :sync-for-iterator.{core::Iterator::moveNext}(){() → core::bool}; ) {
- self::B4* o = [@vm.direct-call.metadata=dart._internal::ListIterator.current] :sync-for-iterator.{core::Iterator::current}{self::B4*};
- o.{self::B4::foo}(){() →* void};
+ self::B4 o = [@vm.direct-call.metadata=dart._internal::ListIterator.current] :sync-for-iterator.{core::Iterator::current}{self::B4};
+ o.{self::B4::foo}(){() → void};
}
}
- core::List<self::C4*>* z4 = [@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::C4*>] core::_GrowableList::_literal2<self::C4*>(new self::C4::•(), new self::E4::•());
+ core::List<self::C4> z4 = [@vm.inferred-type.metadata=dart.core::_GrowableList<#lib::C4>] core::_GrowableList::_literal2<self::C4>(new self::C4::•(), new self::E4::•());
{
- core::Iterator<self::C4*>* :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::C4*>] z4.{core::Iterable::iterator}{core::Iterator<self::C4*>*};
+ core::Iterator<self::C4> :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::C4>] z4.{core::Iterable::iterator}{core::Iterator<self::C4>};
for (; [@vm.direct-call.metadata=dart._internal::ListIterator.moveNext] [@vm.inferred-type.metadata=dart.core::bool (skip check)] :sync-for-iterator.{core::Iterator::moveNext}(){() → core::bool}; ) {
- self::C4* o = [@vm.direct-call.metadata=dart._internal::ListIterator.current] :sync-for-iterator.{core::Iterator::current}{self::C4*};
- [@vm.direct-call.metadata=#lib::C4.foo??] [@vm.inferred-type.metadata=!? (skip check)] o.{self::C4::foo}(){() →* void};
+ self::C4 o = [@vm.direct-call.metadata=dart._internal::ListIterator.current] :sync-for-iterator.{core::Iterator::current}{self::C4};
+ [@vm.direct-call.metadata=#lib::C4.foo??] [@vm.inferred-type.metadata=!? (skip check)] o.{self::C4::foo}(){() → void};
}
}
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/set_map_constructor_concrete.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/set_map_constructor_concrete.dart.expect
index 76714d7..cffe9fc 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/set_map_constructor_concrete.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/set_map_constructor_concrete.dart.expect
@@ -1,4 +1,4 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
import "dart:collection" as col;
@@ -6,33 +6,33 @@
import "dart:collection";
import "dart:core";
-[@vm.inferred-type.metadata=dart.collection::_CompactLinkedHashSet?<dynamic>]static field core::Set<dynamic>* globalSet = new col::_CompactLinkedHashSet::•<dynamic>();
-[@vm.inferred-type.metadata=dart.collection::_CompactLinkedIdentityHashSet?<dynamic>]static field core::Set<dynamic>* identitySet = [@vm.inferred-type.metadata=dart.collection::_CompactLinkedIdentityHashSet<dynamic>] col::LinkedHashSet::identity<dynamic>();
-[@vm.inferred-type.metadata=dart.collection::_CompactLinkedHashSet?<dart.core::String*>]static field core::Set<core::String*>* linkedSet = new col::_CompactLinkedHashSet::•<core::String*>();
-static field core::Set<core::String*>* linkedIdentitySet = [@vm.inferred-type.metadata=!] col::LinkedHashSet::•<core::String*>(#C1, #C2);
-static field core::Set<core::String*>* linkedCustomSet = let final (core::String*, core::String*) →* core::bool* #t1 = (core::String* a, core::String* b) → core::bool* => [@vm.inferred-type.metadata=!? (receiver not int)] a =={core::String::==}{(core::Object*) →* core::bool*} b in let final (core::String*) →* core::int* #t2 = (core::String* o) → core::int* => o.{core::String::hashCode}{core::int*} in let final (dynamic) →* core::bool* #t3 = (dynamic o) → core::bool* => true in [@vm.inferred-type.metadata=!] col::LinkedHashSet::•<core::String*>(#t1, #t2, isValidKey: #t3);
-[@vm.inferred-type.metadata=dart.collection::_InternalLinkedHashMap?<dynamic, dynamic>]static field core::Map<dynamic, dynamic>* globalMap = [@vm.inferred-type.metadata=dart.collection::_InternalLinkedHashMap<dynamic, dynamic>] core::Map::•<dynamic, dynamic>();
-[@vm.inferred-type.metadata=dart.collection::_CompactLinkedIdentityHashMap?<dynamic, dynamic>]static field core::Map<dynamic, dynamic>* identityMap = [@vm.inferred-type.metadata=dart.collection::_CompactLinkedIdentityHashMap<dynamic, dynamic>] col::LinkedHashMap::identity<dynamic, dynamic>();
-[@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView?<dynamic, dynamic>]static field core::Map<dynamic, dynamic>* unmodifiableMap = [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dynamic, dynamic>] core::Map::unmodifiable<dynamic, dynamic>([@vm.inferred-type.metadata=dart.collection::_CompactLinkedIdentityHashMap?<dynamic, dynamic>] self::identityMap);
-[@vm.inferred-type.metadata=dart.collection::_InternalLinkedHashMap?<dynamic, dynamic>]static field core::Map<dynamic, dynamic>* globalMapLiteral = <dynamic, dynamic>{};
-[@vm.inferred-type.metadata=dart.collection::_InternalLinkedHashMap?<dart.core::String*, dart.core::String*>]static field core::Map<core::String*, core::String*>* linkedMap = new col::_InternalLinkedHashMap::•<core::String*, core::String*>();
-static field core::Map<core::String*, core::String*>* linkedIdentityMap = [@vm.inferred-type.metadata=!] col::LinkedHashMap::•<core::String*, core::String*>(#C1, #C2);
-static field core::Map<core::String*, core::String*>* linkedCustomMap = let final (core::String*, core::String*) →* core::bool* #t4 = (core::String* a, core::String* b) → core::bool* => [@vm.inferred-type.metadata=!? (receiver not int)] a =={core::String::==}{(core::Object*) →* core::bool*} b in let final (core::String*) →* core::int* #t5 = (core::String* o) → core::int* => o.{core::String::hashCode}{core::int*} in let final (dynamic) →* core::bool* #t6 = (dynamic o) → core::bool* => true in [@vm.inferred-type.metadata=!] col::LinkedHashMap::•<core::String*, core::String*>(#t4, #t5, isValidKey: #t6);
+[@vm.inferred-type.metadata=dart.collection::_CompactLinkedHashSet?<dynamic>]static field core::Set<dynamic> globalSet = new col::_CompactLinkedHashSet::•<dynamic>();
+[@vm.inferred-type.metadata=dart.collection::_CompactLinkedIdentityHashSet?<dynamic>]static field core::Set<dynamic> identitySet = [@vm.inferred-type.metadata=dart.collection::_CompactLinkedIdentityHashSet<dynamic>] col::LinkedHashSet::identity<dynamic>();
+[@vm.inferred-type.metadata=dart.collection::_CompactLinkedHashSet?<dart.core::String>]static field core::Set<core::String> linkedSet = new col::_CompactLinkedHashSet::•<core::String>();
+static field core::Set<core::String> linkedIdentitySet = [@vm.inferred-type.metadata=!] col::LinkedHashSet::•<core::String>(#C1, #C2);
+static field core::Set<core::String> linkedCustomSet = let final (core::String, core::String) → core::bool #t1 = (core::String a, core::String b) → core::bool => [@vm.inferred-type.metadata=!? (receiver not int)] a =={core::String::==}{(core::Object) → core::bool} b in let final (core::String) → core::int #t2 = (core::String o) → core::int => o.{core::String::hashCode}{core::int} in let final (dynamic) → core::bool #t3 = (dynamic o) → core::bool => true in [@vm.inferred-type.metadata=!] col::LinkedHashSet::•<core::String>(#t1, #t2, isValidKey: #t3);
+[@vm.inferred-type.metadata=dart.collection::_InternalLinkedHashMap?<dynamic, dynamic>]static field core::Map<dynamic, dynamic> globalMap = [@vm.inferred-type.metadata=dart.collection::_InternalLinkedHashMap<dynamic, dynamic>] core::Map::•<dynamic, dynamic>();
+[@vm.inferred-type.metadata=dart.collection::_CompactLinkedIdentityHashMap?<dynamic, dynamic>]static field core::Map<dynamic, dynamic> identityMap = [@vm.inferred-type.metadata=dart.collection::_CompactLinkedIdentityHashMap<dynamic, dynamic>] col::LinkedHashMap::identity<dynamic, dynamic>();
+[@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView?<dynamic, dynamic>]static field core::Map<dynamic, dynamic> unmodifiableMap = [@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView<dynamic, dynamic>] core::Map::unmodifiable<dynamic, dynamic>([@vm.inferred-type.metadata=dart.collection::_CompactLinkedIdentityHashMap?<dynamic, dynamic>] self::identityMap);
+[@vm.inferred-type.metadata=dart.collection::_InternalLinkedHashMap?<dynamic, dynamic>]static field core::Map<dynamic, dynamic> globalMapLiteral = <dynamic, dynamic>{};
+[@vm.inferred-type.metadata=dart.collection::_InternalLinkedHashMap?<dart.core::String, dart.core::String>]static field core::Map<core::String, core::String> linkedMap = new col::_InternalLinkedHashMap::•<core::String, core::String>();
+static field core::Map<core::String, core::String> linkedIdentityMap = [@vm.inferred-type.metadata=!] col::LinkedHashMap::•<core::String, core::String>(#C1, #C2);
+static field core::Map<core::String, core::String> linkedCustomMap = let final (core::String, core::String) → core::bool #t4 = (core::String a, core::String b) → core::bool => [@vm.inferred-type.metadata=!? (receiver not int)] a =={core::String::==}{(core::Object) → core::bool} b in let final (core::String) → core::int #t5 = (core::String o) → core::int => o.{core::String::hashCode}{core::int} in let final (dynamic) → core::bool #t6 = (dynamic o) → core::bool => true in [@vm.inferred-type.metadata=!] col::LinkedHashMap::•<core::String, core::String>(#t4, #t5, isValidKey: #t6);
static method main() → dynamic {
core::print([@vm.inferred-type.metadata=dart.collection::_CompactLinkedHashSet?<dynamic>] self::globalSet);
core::print([@vm.inferred-type.metadata=dart.collection::_CompactLinkedIdentityHashSet?<dynamic>] self::identitySet);
- core::print([@vm.inferred-type.metadata=dart.collection::_CompactLinkedHashSet?<dart.core::String*>] self::linkedSet);
+ core::print([@vm.inferred-type.metadata=dart.collection::_CompactLinkedHashSet?<dart.core::String>] self::linkedSet);
core::print(self::linkedIdentitySet);
core::print(self::linkedCustomSet);
core::print([@vm.inferred-type.metadata=dart.collection::_InternalLinkedHashMap?<dynamic, dynamic>] self::globalMap);
core::print([@vm.inferred-type.metadata=dart.collection::_InternalLinkedHashMap?<dynamic, dynamic>] self::globalMapLiteral);
core::print([@vm.inferred-type.metadata=dart.collection::_CompactLinkedIdentityHashMap?<dynamic, dynamic>] self::identityMap);
core::print([@vm.inferred-type.metadata=dart.collection::UnmodifiableMapView?<dynamic, dynamic>] self::unmodifiableMap);
- core::print([@vm.inferred-type.metadata=dart.collection::_InternalLinkedHashMap?<dart.core::String*, dart.core::String*>] self::linkedMap);
+ core::print([@vm.inferred-type.metadata=dart.collection::_InternalLinkedHashMap?<dart.core::String, dart.core::String>] self::linkedMap);
core::print(self::linkedIdentityMap);
core::print(self::linkedCustomMap);
}
constants {
- #C1 = tearoff core::identical
- #C2 = tearoff core::identityHashCode
+ #C1 = static-tearoff core::identical
+ #C2 = static-tearoff core::identityHashCode
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_dynamic_method.dart b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_dynamic_method.dart
index 2d22fe6..e29f9dd 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_dynamic_method.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_dynamic_method.dart
@@ -11,11 +11,11 @@
}
class B extends A {
- int foo() => 1 + knownResult().foo(); // Should have metadata.
+ int foo() => 1 + knownResult().foo() as int; // Should have metadata.
}
class C implements A {
- int foo() => 2 + knownResult().foo(); // Should be unreachable.
+ int foo() => 2 + knownResult().foo() as int; // Should be unreachable.
}
class TearOffDynamicMethod {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_dynamic_method.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_dynamic_method.dart.expect
index 3483f2c..582555f 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_dynamic_method.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_dynamic_method.dart.expect
@@ -1,29 +1,29 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
abstract class A extends core::Object {
- synthetic constructor •() → self::A*
+ synthetic constructor •() → self::A
: super core::Object::•()
;
}
class B extends self::A {
- synthetic constructor •() → self::B*
+ synthetic constructor •() → self::B
: super self::A::•()
;
-[@vm.procedure-attributes.metadata=hasThisUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i] method foo() → core::int*
- return [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=! (skip check)] 1.{core::num::+}([@vm.direct-call.metadata=#lib::B.foo] [@vm.inferred-type.metadata=!? (receiver not int)] [@vm.inferred-type.metadata=#lib::B] self::knownResult(){dynamic}.foo() as{TypeError,ForDynamic} core::num*){(core::num*) →* core::num*} as{TypeError} core::int*;
+[@vm.procedure-attributes.metadata=hasThisUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i] method foo() → core::int
+ return [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=! (skip check)] 1.{core::num::+}([@vm.direct-call.metadata=#lib::B.foo] [@vm.inferred-type.metadata=!? (receiver not int)] [@vm.inferred-type.metadata=#lib::B] self::knownResult(){dynamic}.foo() as{TypeError,ForDynamic,ForNonNullableByDefault} core::num){(core::num) → core::num} as{ForNonNullableByDefault} core::int;
}
class TearOffDynamicMethod extends core::Object {
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] field dynamic bazz;
- constructor •(dynamic arg) → self::TearOffDynamicMethod*
+ constructor •(dynamic arg) → self::TearOffDynamicMethod
: self::TearOffDynamicMethod::bazz = arg{dynamic}.foo, super core::Object::•() {
[@vm.direct-call.metadata=#lib::TearOffDynamicMethod.bazz] this.{self::TearOffDynamicMethod::bazz}{dynamic}{dynamic}.call();
}
}
static method knownResult() → dynamic
return new self::B::•();
-static method main(core::List<core::String*>* args) → dynamic {
- core::Function* closure = () → self::B* => new self::B::•();
+static method main(core::List<core::String> args) → dynamic {
+ core::Function closure = () → self::B => new self::B::•();
new self::TearOffDynamicMethod::•(closure());
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_interface_method.dart b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_interface_method.dart
index 5ce46d8..603bbf6 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_interface_method.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_interface_method.dart
@@ -11,12 +11,12 @@
}
class B extends A {
- int foo() => 1 + knownResult().bar(); // Should have metadata.
+ int foo() => 1 + knownResult().bar() as int; // Should have metadata.
int bar() => 3;
}
class C implements A {
- int foo() => 2 + knownResult().bar(); // Should be unreachable.
+ int foo() => 2 + knownResult().bar() as int; // Should be unreachable.
}
class TearOffInterfaceMethod {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_interface_method.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_interface_method.dart.expect
index 578e8fb..b34fce5 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_interface_method.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_interface_method.dart.expect
@@ -1,31 +1,31 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
import "dart:_internal" as _in;
abstract class A extends core::Object {
- synthetic constructor •() → self::A*
+ synthetic constructor •() → self::A
: super core::Object::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i] abstract method foo() → core::int*;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i] abstract method foo() → core::int;
}
class B extends self::A {
- synthetic constructor •() → self::B*
+ synthetic constructor •() → self::B
: super self::A::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i] method foo() → core::int*
- return _in::unsafeCast<core::int*>([@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] 1.{core::num::+}(_in::unsafeCast<core::num*>([@vm.direct-call.metadata=#lib::B.bar] [@vm.inferred-type.metadata=dart.core::_Smi (value: 3) (receiver not int)] [@vm.inferred-type.metadata=#lib::B] self::knownResult(){dynamic}.bar())){(core::num*) →* core::num*});
-[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] [@vm.unboxing-info.metadata=()->i] method bar() → core::int*
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i] method foo() → core::int
+ return _in::unsafeCast<core::int>([@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] 1.{core::num::+}(_in::unsafeCast<core::num>([@vm.direct-call.metadata=#lib::B.bar] [@vm.inferred-type.metadata=dart.core::_Smi (value: 3) (receiver not int)] [@vm.inferred-type.metadata=#lib::B] self::knownResult(){dynamic}.bar())){(core::num) → core::num});
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] [@vm.unboxing-info.metadata=()->i] method bar() → core::int
return 3;
}
class TearOffInterfaceMethod extends core::Object {
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] field dynamic bazz;
- constructor •([@vm.inferred-type.metadata=#lib::B] self::A* arg) → self::TearOffInterfaceMethod*
- : self::TearOffInterfaceMethod::bazz = arg.{self::A::foo}{() →* core::int*}, super core::Object::•()
+ constructor •([@vm.inferred-type.metadata=#lib::B] self::A arg) → self::TearOffInterfaceMethod
+ : self::TearOffInterfaceMethod::bazz = arg.{self::A::foo}{() → core::int}, super core::Object::•()
;
}
static method knownResult() → dynamic
return new self::B::•();
-static method main(core::List<core::String*>* args) → dynamic {
+static method main(core::List<core::String> args) → dynamic {
[@vm.direct-call.metadata=#lib::TearOffInterfaceMethod.bazz] new self::TearOffInterfaceMethod::•(new self::B::•()).{self::TearOffInterfaceMethod::bazz}{dynamic}{dynamic}.call();
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_super_method.dart b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_super_method.dart
index ebe01db..2980835 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_super_method.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_super_method.dart
@@ -11,26 +11,26 @@
}
class B extends A {
- int foo() => 1 + knownResult().foo(); // Should have metadata.
+ int foo() => 1 + knownResult().foo() as int; // Should have metadata.
}
class C implements A {
- int foo() => 2 + knownResult().foo(); // Should be unreachable.
+ int foo() => 2 + knownResult().foo() as int; // Should be unreachable.
}
class Base {
- int foo() => 3 + knownResult().foo(); // Should have metadata.
- int doCall(x) => x();
+ int foo() => 3 + knownResult().foo() as int; // Should have metadata.
+ int? doCall(x) => x();
}
class TearOffSuperMethod extends Base {
int foo() {
// Should be unreachable.
aa = new C();
- return 4 + knownResult().foo();
+ return 4 + knownResult().foo() as int;
}
- int bar() => doCall(super.foo);
+ int? bar() => doCall(super.foo);
}
main(List<String> args) {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_super_method.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_super_method.dart.expect
index bc69294..0e44dd5 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_super_method.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_super_method.dart.expect
@@ -1,41 +1,41 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
import "dart:_internal" as _in;
abstract class A extends core::Object {
- synthetic constructor •() → self::A*
+ synthetic constructor •() → self::A
: super core::Object::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i] abstract method foo() → core::int*;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i] abstract method foo() → core::int;
}
class B extends self::A {
- synthetic constructor •() → self::B*
+ synthetic constructor •() → self::B
: super self::A::•()
;
-[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i] method foo() → core::int*
- return _in::unsafeCast<core::int*>([@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] 1.{core::num::+}(_in::unsafeCast<core::num*>([@vm.direct-call.metadata=#lib::B.foo] [@vm.inferred-type.metadata=int? (receiver not int)] [@vm.inferred-type.metadata=#lib::B] self::knownResult(){dynamic}.foo())){(core::num*) →* core::num*});
+[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i] method foo() → core::int
+ return _in::unsafeCast<core::int>([@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] 1.{core::num::+}(_in::unsafeCast<core::num>([@vm.direct-call.metadata=#lib::B.foo] [@vm.inferred-type.metadata=int? (receiver not int)] [@vm.inferred-type.metadata=#lib::B] self::knownResult(){dynamic}.foo())){(core::num) → core::num});
}
abstract class Base extends core::Object {
- synthetic constructor •() → self::Base*
+ synthetic constructor •() → self::Base
: super core::Object::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] [@vm.unboxing-info.metadata=()->i] method foo() → core::int*
- return _in::unsafeCast<core::int*>([@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] 3.{core::num::+}(_in::unsafeCast<core::num*>([@vm.direct-call.metadata=#lib::B.foo] [@vm.inferred-type.metadata=int? (receiver not int)] [@vm.inferred-type.metadata=#lib::B] self::knownResult(){dynamic}.foo())){(core::num*) →* core::num*});
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] method doCall(dynamic x) → core::int*
- return x{dynamic}.call() as{TypeError,ForDynamic} core::int*;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] [@vm.unboxing-info.metadata=()->i] method foo() → core::int
+ return _in::unsafeCast<core::int>([@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] 3.{core::num::+}(_in::unsafeCast<core::num>([@vm.direct-call.metadata=#lib::B.foo] [@vm.inferred-type.metadata=int? (receiver not int)] [@vm.inferred-type.metadata=#lib::B] self::knownResult(){dynamic}.foo())){(core::num) → core::num});
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] method doCall(dynamic x) → core::int?
+ return x{dynamic}.call() as{TypeError,ForDynamic,ForNonNullableByDefault} core::int?;
}
class TearOffSuperMethod extends self::Base {
- synthetic constructor •() → self::TearOffSuperMethod*
+ synthetic constructor •() → self::TearOffSuperMethod
: super self::Base::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] method bar() → core::int*
- return [@vm.direct-call.metadata=#lib::Base.doCall] [@vm.inferred-type.metadata=int? (skip check)] this.{self::Base::doCall}(super.{self::Base::foo}){(dynamic) →* core::int*};
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] method bar() → core::int?
+ return [@vm.direct-call.metadata=#lib::Base.doCall] [@vm.inferred-type.metadata=int? (skip check)] this.{self::Base::doCall}(super.{self::Base::foo}){(dynamic) → core::int?};
}
-[@vm.inferred-type.metadata=#lib::B?]static field self::A* aa = new self::B::•();
+[@vm.inferred-type.metadata=#lib::B?]static field self::A aa = new self::B::•();
static method knownResult() → dynamic
return new self::B::•();
-static method main(core::List<core::String*>* args) → dynamic {
- [@vm.direct-call.metadata=#lib::TearOffSuperMethod.bar] [@vm.inferred-type.metadata=!? (skip check)] new self::TearOffSuperMethod::•().{self::TearOffSuperMethod::bar}(){() →* core::int*};
- [@vm.direct-call.metadata=#lib::B.foo??] [@vm.inferred-type.metadata=!? (skip check)] [@vm.inferred-type.metadata=#lib::B?] self::aa.{self::A::foo}(){() →* core::int*};
+static method main(core::List<core::String> args) → dynamic {
+ [@vm.direct-call.metadata=#lib::TearOffSuperMethod.bar] [@vm.inferred-type.metadata=!? (skip check)] new self::TearOffSuperMethod::•().{self::TearOffSuperMethod::bar}(){() → core::int?};
+ [@vm.direct-call.metadata=#lib::B.foo??] [@vm.inferred-type.metadata=!? (skip check)] [@vm.inferred-type.metadata=#lib::B?] self::aa.{self::A::foo}(){() → core::int};
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination.dart.expect
index 7f83b39..c5846d8 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination.dart.expect
@@ -1,58 +1,58 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
import "dart:_internal" as _in;
-class A<T extends core::Object* = dynamic> extends core::Object {
- synthetic constructor •() → self::A<self::A::T*>*
+class A<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::A<self::A::T%>
: super core::Object::•()
;
}
-class B<T extends core::Object* = dynamic> extends self::A<self::B::T*> {
- synthetic constructor •() → self::B<self::B::T*>*
+class B<T extends core::Object? = dynamic> extends self::A<self::B::T%> {
+ synthetic constructor •() → self::B<self::B::T%>
: super self::A::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i] method testT1() → dynamic
- return _in::unsafeCast<self::B::T*>(#C1);
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] method testT2negative([@vm.inferred-type.metadata=#lib::A<dart.core::String*>] dynamic x) → dynamic
- return x as self::B::T*;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] method testAOfT1([@vm.inferred-type.metadata=#lib::A<#lib::A<dart.core::int*>*>] dynamic x) → dynamic
- return _in::unsafeCast<self::A<self::B::T*>*>(x);
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] method testAOfT2negative([@vm.inferred-type.metadata=#lib::A<#lib::A<dart.core::num*>*>] dynamic x) → dynamic
- return x as self::A<self::B::T*>*;
+ return _in::unsafeCast<self::B::T%>(#C1);
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] method testT2negative([@vm.inferred-type.metadata=#lib::A<dart.core::String>] dynamic x) → dynamic
+ return x as{ForNonNullableByDefault} self::B::T%;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] method testAOfT1([@vm.inferred-type.metadata=#lib::A<#lib::A<dart.core::int>>] dynamic x) → dynamic
+ return _in::unsafeCast<self::A<self::B::T%>>(x);
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] method testAOfT2negative([@vm.inferred-type.metadata=#lib::A<#lib::A<dart.core::num>>] dynamic x) → dynamic
+ return x as{ForNonNullableByDefault} self::A<self::B::T%>;
}
[@vm.unboxing-info.metadata=()->i]static method testInt1() → dynamic
- return _in::unsafeCast<core::int*>(#C1);
+ return _in::unsafeCast<core::int>(#C1);
static method testInt2() → dynamic
- return _in::unsafeCast<core::int*>(#C2);
+ return _in::unsafeCast<core::int>(#C2);
static method testDynamic() → dynamic
return _in::unsafeCast<dynamic>(#C3);
static method testObject() → dynamic
return #C4;
-static method testBOfInt([@vm.inferred-type.metadata=#lib::B<dart.core::int*>] dynamic x) → dynamic
- return _in::unsafeCast<self::B<core::int*>*>(x);
-static method testAOfInt([@vm.inferred-type.metadata=#lib::B<dart.core::int*>] dynamic x) → dynamic
- return _in::unsafeCast<self::A<core::int*>*>(x);
-static method testAOfNum([@vm.inferred-type.metadata=#lib::B<dart.core::int*>] dynamic x) → dynamic
- return _in::unsafeCast<self::A<core::num*>*>(x);
-static method testAOfAOfB1([@vm.inferred-type.metadata=#lib::A<#lib::A<#lib::B<dynamic>*>*>] dynamic x) → dynamic
- return _in::unsafeCast<self::A<self::A<self::B<dynamic>*>*>*>(x);
-static method testAOfAOfB2negative([@vm.inferred-type.metadata=#lib::A<#lib::A<#lib::A<dynamic>*>*>] dynamic x) → dynamic
- return x as self::A<self::A<self::B<dynamic>*>*>*;
+static method testBOfInt([@vm.inferred-type.metadata=#lib::B<dart.core::int>] dynamic x) → dynamic
+ return _in::unsafeCast<self::B<core::int>>(x);
+static method testAOfInt([@vm.inferred-type.metadata=#lib::B<dart.core::int>] dynamic x) → dynamic
+ return _in::unsafeCast<self::A<core::int>>(x);
+static method testAOfNum([@vm.inferred-type.metadata=#lib::B<dart.core::int>] dynamic x) → dynamic
+ return _in::unsafeCast<self::A<core::num>>(x);
+static method testAOfAOfB1([@vm.inferred-type.metadata=#lib::A<#lib::A<#lib::B<dynamic>>>] dynamic x) → dynamic
+ return _in::unsafeCast<self::A<self::A<self::B<dynamic>>>>(x);
+static method testAOfAOfB2negative([@vm.inferred-type.metadata=#lib::A<#lib::A<#lib::A<dynamic>>>] dynamic x) → dynamic
+ return x as{ForNonNullableByDefault} self::A<self::A<self::B<dynamic>>>;
static method main() → void {
self::testInt1();
self::testInt2();
self::testDynamic();
self::testObject();
- self::testBOfInt(new self::B::•<core::int*>());
- self::testAOfInt(new self::B::•<core::int*>());
- self::testAOfNum(new self::B::•<core::int*>());
- self::testAOfAOfB1(new self::A::•<self::A<self::B<dynamic>*>*>());
- self::testAOfAOfB2negative(new self::A::•<self::A<self::A<dynamic>*>*>());
- [@vm.direct-call.metadata=#lib::B.testT1] [@vm.inferred-type.metadata=!? (skip check)] new self::B::•<core::int*>().{self::B::testT1}(){(dynamic) →* dynamic};
- [@vm.direct-call.metadata=#lib::B.testT2negative] [@vm.inferred-type.metadata=!? (skip check)] new self::B::•<self::A<core::int*>*>().{self::B::testT2negative}(new self::A::•<core::String*>()){(dynamic) →* dynamic};
- [@vm.direct-call.metadata=#lib::B.testAOfT1] [@vm.inferred-type.metadata=!? (skip check)] new self::B::•<self::A<core::int*>*>().{self::B::testAOfT1}(new self::A::•<self::A<core::int*>*>()){(dynamic) →* dynamic};
- [@vm.direct-call.metadata=#lib::B.testAOfT2negative] [@vm.inferred-type.metadata=!? (skip check)] new self::B::•<self::A<core::int*>*>().{self::B::testAOfT2negative}(new self::A::•<self::A<core::num*>*>()){(dynamic) →* dynamic};
+ self::testBOfInt(new self::B::•<core::int>());
+ self::testAOfInt(new self::B::•<core::int>());
+ self::testAOfNum(new self::B::•<core::int>());
+ self::testAOfAOfB1(new self::A::•<self::A<self::B<dynamic>>>());
+ self::testAOfAOfB2negative(new self::A::•<self::A<self::A<dynamic>>>());
+ [@vm.direct-call.metadata=#lib::B.testT1] [@vm.inferred-type.metadata=!? (skip check)] new self::B::•<core::int>().{self::B::testT1}(){(dynamic) → dynamic};
+ [@vm.direct-call.metadata=#lib::B.testT2negative] [@vm.inferred-type.metadata=!? (skip check)] new self::B::•<self::A<core::int>>().{self::B::testT2negative}(new self::A::•<core::String>()){(dynamic) → dynamic};
+ [@vm.direct-call.metadata=#lib::B.testAOfT1] [@vm.inferred-type.metadata=!? (skip check)] new self::B::•<self::A<core::int>>().{self::B::testAOfT1}(new self::A::•<self::A<core::int>>()){(dynamic) → dynamic};
+ [@vm.direct-call.metadata=#lib::B.testAOfT2negative] [@vm.inferred-type.metadata=!? (skip check)] new self::B::•<self::A<core::int>>().{self::B::testAOfT2negative}(new self::A::•<self::A<core::num>>()){(dynamic) → dynamic};
}
constants {
#C1 = 42
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd.dart b/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd.dart
index 5f0e8e8..e3a95bd 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd.dart
@@ -3,9 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
// Tests elimination of type casts.
-// This test requires non-nullable experiment.
-
-// @dart = 2.10
class A<T> {}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd_strong.dart b/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd_strong.dart
index c828095..337a57a 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd_strong.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd_strong.dart
@@ -3,9 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
// Tests elimination of type casts.
-// This test requires non-nullable experiment and NNBD strong mode.
-
-// @dart = 2.10
+// This test requires sound null safety.
class A<T> {}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd_strong.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd_strong.dart.expect
index 9f7ad71..7ac9fc8 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd_strong.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd_strong.dart.expect
@@ -34,7 +34,7 @@
static method testDynamic() → dynamic
return _in::unsafeCast<dynamic>(#C3);
static method testObjectNegative() → dynamic
- return let dynamic #t1 = #C2 in true ?{core::Object} #t1 as{ForNonNullableByDefault} core::Object : #t1{core::Object};
+ return let dynamic #t1 = #C2 in #t1 as{ForNonNullableByDefault} core::Object;
static method testNullableObject() → dynamic
return #C2;
static method testAOfNum1([@vm.inferred-type.metadata=#lib::B<dart.core::int>] dynamic x) → dynamic
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_getters.dart b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_getters.dart
index 726b6c9..81af9f4 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_getters.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_getters.dart
@@ -13,58 +13,58 @@
}
abstract class BI1 {
- int get value;
+ int? get value;
}
class BI1A implements BI1 {
- final int value;
+ final int? value;
BI1A(this.value);
}
class BI1B implements BI1 {
- int get value => null;
+ int? get value => null;
}
abstract class BI2 {
- int get value;
+ int? get value;
}
class BI2A implements BI2 {
- final int value;
+ final int? value;
BI2A(this.value);
}
class BI2B implements BI2 {
- int get value => smiOrMint;
+ int? get value => smiOrMint;
}
abstract class BI3 {
- int get value;
- set value(int value);
+ int? get value;
+ set value(int? value);
}
class BI3A implements BI3 {
- int value;
+ int? value;
BI3A(this.value);
}
class BI3B implements BI3 {
- int get value => smiOrMint;
- set value(int v) {}
+ int? get value => smiOrMint;
+ set value(int? v) {}
}
abstract class UBI {
- int value;
+ int? value;
}
class UBIA implements UBI {
- int value;
+ int? value;
UBIA(this.value);
}
class UBIB implements UBI {
- int get value => smiOrMint;
- set value(int v) {}
+ int? get value => smiOrMint;
+ set value(int? v) {}
}
main() {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_getters.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_getters.dart.expect
index 542466c..de01101 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_getters.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_getters.dart.expect
@@ -1,96 +1,96 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
abstract class BI1 extends core::Object {
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] abstract get value() → core::int*;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] abstract get value() → core::int?;
}
class BI1A extends core::Object implements self::BI1 {
-[@vm.inferred-type.metadata=int] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] final field core::int* value;
-[@vm.unboxing-info.metadata=(i)->b] constructor •([@vm.inferred-type.metadata=int] core::int* value) → self::BI1A*
+[@vm.inferred-type.metadata=int] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] final field core::int? value;
+[@vm.unboxing-info.metadata=(i)->b] constructor •([@vm.inferred-type.metadata=int] core::int? value) → self::BI1A
: self::BI1A::value = value, super core::Object::•()
;
}
class BI1B extends core::Object implements self::BI1 {
- synthetic constructor •() → self::BI1B*
+ synthetic constructor •() → self::BI1B
: super core::Object::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] get value() → core::int*
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:1] get value() → core::int?
return null;
}
abstract class BI2 extends core::Object {
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:2] abstract get value() → core::int*;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:2] abstract get value() → core::int?;
}
class BI2A extends core::Object implements self::BI2 {
-[@vm.inferred-type.metadata=dart.core::Null? (value: null)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:2] final field core::int* value;
- constructor •() → self::BI2A*
+[@vm.inferred-type.metadata=dart.core::Null? (value: null)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:2] final field core::int? value;
+ constructor •() → self::BI2A
: self::BI2A::value = #C1, super core::Object::•()
;
}
class BI2B extends core::Object implements self::BI2 {
- synthetic constructor •() → self::BI2B*
+ synthetic constructor •() → self::BI2B
: super core::Object::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:2] get value() → core::int*
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:2] get value() → core::int?
return [@vm.inferred-type.metadata=int] self::smiOrMint;
}
abstract class BI3 extends core::Object {
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] abstract get value() → core::int*;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] abstract set value(core::int* value) → void;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] abstract get value() → core::int?;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] abstract set value(core::int? value) → void;
}
class BI3A extends core::Object implements self::BI3 {
-[@vm.inferred-type.metadata=int?] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] field core::int* value;
-[@vm.unboxing-info.metadata=(i)->b] constructor •([@vm.inferred-type.metadata=int] core::int* value) → self::BI3A*
+[@vm.inferred-type.metadata=int?] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] field core::int? value;
+[@vm.unboxing-info.metadata=(i)->b] constructor •([@vm.inferred-type.metadata=int] core::int? value) → self::BI3A
: self::BI3A::value = value, super core::Object::•()
;
}
class BI3B extends core::Object implements self::BI3 {
- synthetic constructor •() → self::BI3B*
+ synthetic constructor •() → self::BI3B
: super core::Object::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] get value() → core::int*
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] get value() → core::int?
return [@vm.inferred-type.metadata=int] self::smiOrMint;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] set value([@vm.inferred-type.metadata=dart.core::Null? (value: null)] core::int* v) → void {}
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] set value([@vm.inferred-type.metadata=dart.core::Null? (value: null)] core::int? v) → void {}
}
abstract class UBI extends core::Object {
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:5] [@vm.unboxing-info.metadata=()->i] abstract get value() → core::int*;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:5] [@vm.unboxing-info.metadata=()->i] abstract get /*isLegacy*/ value() → core::int?;
}
class UBIA extends core::Object implements self::UBI {
-[@vm.inferred-type.metadata=int] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:5] [@vm.unboxing-info.metadata=(i)->i] field core::int* value;
-[@vm.unboxing-info.metadata=(i)->b] constructor •([@vm.inferred-type.metadata=int] core::int* value) → self::UBIA*
+[@vm.inferred-type.metadata=int] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:5] [@vm.unboxing-info.metadata=(i)->i] field core::int? value;
+[@vm.unboxing-info.metadata=(i)->b] constructor •([@vm.inferred-type.metadata=int] core::int? value) → self::UBIA
: self::UBIA::value = value, super core::Object::•()
;
}
class UBIB extends core::Object implements self::UBI {
- synthetic constructor •() → self::UBIB*
+ synthetic constructor •() → self::UBIB
: super core::Object::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:5] [@vm.unboxing-info.metadata=()->i] get value() → core::int*
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:5] [@vm.unboxing-info.metadata=()->i] get value() → core::int?
return [@vm.inferred-type.metadata=int] self::smiOrMint;
}
-[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool* kTrue = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object*) →* core::bool*} 1 ?{core::bool*} true : false;
+[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool kTrue = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object) → core::bool} 1 ?{core::bool} true : false;
[@vm.inferred-type.metadata=int?]static field dynamic usedObject;
-[@vm.unboxing-info.metadata=()->i]static get mint() → core::int*
+[@vm.unboxing-info.metadata=()->i]static get mint() → core::int
return -6144092014192636707;
-[@vm.unboxing-info.metadata=()->i]static get smiOrMint() → core::int*
- return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : [@vm.inferred-type.metadata=int] self::mint;
+[@vm.unboxing-info.metadata=()->i]static get smiOrMint() → core::int
+ return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} 1 : [@vm.inferred-type.metadata=int] self::mint;
static method use([@vm.inferred-type.metadata=int?] dynamic object) → void {
[@vm.inferred-type.metadata=int?] self::usedObject == null ?{dynamic} self::usedObject = object : null;
}
static method main() → dynamic {
- final self::BI1A* bi1a = new self::BI1A::•([@vm.inferred-type.metadata=int] self::smiOrMint);
- final self::BI1B* bi1b = new self::BI1B::•();
- self::use([@vm.inferred-type.metadata=int?]([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::BI1*} bi1a : bi1b).{self::BI1::value}{core::int*});
- final self::BI2A* bi2a = new self::BI2A::•();
- final self::BI2B* bi2b = new self::BI2B::•();
- self::use([@vm.inferred-type.metadata=int?]([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::BI2*} bi2a : bi2b).{self::BI2::value}{core::int*});
- final self::BI3A* bi3a = new self::BI3A::•([@vm.inferred-type.metadata=int] self::smiOrMint);
- final self::BI3B* bi3b = new self::BI3B::•();
- ([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::BI3*} bi3a : bi3b).{self::BI3::value} = null;
- self::use([@vm.inferred-type.metadata=int?]([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::BI3*} bi3a : bi3b).{self::BI3::value}{core::int*});
- final self::UBIA* ubia = new self::UBIA::•([@vm.inferred-type.metadata=int] self::smiOrMint);
- final self::UBIB* ubib = new self::UBIB::•();
- self::use([@vm.inferred-type.metadata=int]([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::UBI*} ubia : ubib).{self::UBI::value}{core::int*});
+ final self::BI1A bi1a = new self::BI1A::•([@vm.inferred-type.metadata=int] self::smiOrMint);
+ final self::BI1B bi1b = new self::BI1B::•();
+ self::use([@vm.inferred-type.metadata=int?]([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::BI1} bi1a : bi1b).{self::BI1::value}{core::int?});
+ final self::BI2A bi2a = new self::BI2A::•();
+ final self::BI2B bi2b = new self::BI2B::•();
+ self::use([@vm.inferred-type.metadata=int?]([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::BI2} bi2a : bi2b).{self::BI2::value}{core::int?});
+ final self::BI3A bi3a = new self::BI3A::•([@vm.inferred-type.metadata=int] self::smiOrMint);
+ final self::BI3B bi3b = new self::BI3B::•();
+ ([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::BI3} bi3a : bi3b).{self::BI3::value} = null;
+ self::use([@vm.inferred-type.metadata=int?]([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::BI3} bi3a : bi3b).{self::BI3::value}{core::int?});
+ final self::UBIA ubia = new self::UBIA::•([@vm.inferred-type.metadata=int] self::smiOrMint);
+ final self::UBIB ubib = new self::UBIB::•();
+ self::use([@vm.inferred-type.metadata=int]([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::UBI} ubia : ubib).{self::UBI::value}{core::int?});
}
constants {
#C1 = null
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_fields.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_fields.dart.expect
index a3d1769b..4cddb45 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_fields.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_fields.dart.expect
@@ -1,9 +1,9 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
class X extends core::Object {
- synthetic constructor •() → self::X*
+ synthetic constructor •() → self::X
: super core::Object::•()
;
}
@@ -17,30 +17,30 @@
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14] field dynamic boxedNullableIntOrDouble;
[@vm.inferred-type.metadata=#lib::X?] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:15,getterSelectorId:16] field dynamic boxedNullableX;
[@vm.inferred-type.metadata=#lib::X] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:17,getterSelectorId:18] field dynamic boxedX;
-[@vm.unboxing-info.metadata=(i,i,d,b,b,b,b,b,b)->b] constructor •([@vm.inferred-type.metadata=dart.core::_Smi] dynamic unboxedSmi, [@vm.inferred-type.metadata=int] dynamic unboxedInt, [@vm.inferred-type.metadata=dart.core::_Double] dynamic unboxedDouble, [@vm.inferred-type.metadata=int?] dynamic boxedNullableInt, [@vm.inferred-type.metadata=dart.core::_Double?] dynamic boxedNullableDouble, [@vm.inferred-type.metadata=!] dynamic boxedNonNullableIntOrDouble, dynamic boxedNullableIntOrDouble, [@vm.inferred-type.metadata=#lib::X?] dynamic boxedNullableX, [@vm.inferred-type.metadata=#lib::X] dynamic boxedX) → self::A*
+[@vm.unboxing-info.metadata=(i,i,d,b,b,b,b,b,b)->b] constructor •([@vm.inferred-type.metadata=dart.core::_Smi] dynamic unboxedSmi, [@vm.inferred-type.metadata=int] dynamic unboxedInt, [@vm.inferred-type.metadata=dart.core::_Double] dynamic unboxedDouble, [@vm.inferred-type.metadata=int?] dynamic boxedNullableInt, [@vm.inferred-type.metadata=dart.core::_Double?] dynamic boxedNullableDouble, [@vm.inferred-type.metadata=!] dynamic boxedNonNullableIntOrDouble, dynamic boxedNullableIntOrDouble, [@vm.inferred-type.metadata=#lib::X?] dynamic boxedNullableX, [@vm.inferred-type.metadata=#lib::X] dynamic boxedX) → self::A
: self::A::unboxedSmi = unboxedSmi, self::A::unboxedInt = unboxedInt, self::A::unboxedDouble = unboxedDouble, self::A::boxedNullableInt = boxedNullableInt, self::A::boxedNullableDouble = boxedNullableDouble, self::A::boxedNonNullableIntOrDouble = boxedNonNullableIntOrDouble, self::A::boxedNullableIntOrDouble = boxedNullableIntOrDouble, self::A::boxedNullableX = boxedNullableX, self::A::boxedX = boxedX, super core::Object::•()
;
}
-[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool* kTrue = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object*) →* core::bool*} 1 ?{core::bool*} true : false;
-[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool* kFalse = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object*) →* core::bool*} 2 ?{core::bool*} true : false;
+[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool kTrue = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object) → core::bool} 1 ?{core::bool} true : false;
+[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool kFalse = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object) → core::bool} 2 ?{core::bool} true : false;
static field dynamic usedObject;
-[@vm.unboxing-info.metadata=()->i]static get mint() → core::int*
+[@vm.unboxing-info.metadata=()->i]static get mint() → core::int
return -6144092014192636707;
-[@vm.unboxing-info.metadata=()->i]static get smiOrMint() → core::int*
- return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : [@vm.inferred-type.metadata=int] self::mint;
+[@vm.unboxing-info.metadata=()->i]static get smiOrMint() → core::int
+ return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} 1 : [@vm.inferred-type.metadata=int] self::mint;
static method use(dynamic object) → void {
self::usedObject == null ?{dynamic} self::usedObject = object : null;
}
static method main() → dynamic {
- final self::A* a = new self::A::•([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : 2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : 2.2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X*} new self::X::•() : null, new self::X::•());
- [@vm.direct-call.metadata=#lib::A.unboxedSmi] [@vm.inferred-type.metadata=!? (skip check)] a.{self::A::unboxedSmi} = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2;
- [@vm.direct-call.metadata=#lib::A.unboxedInt] [@vm.inferred-type.metadata=!? (skip check)] a.{self::A::unboxedInt} = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : 2;
- [@vm.direct-call.metadata=#lib::A.unboxedDouble] [@vm.inferred-type.metadata=!? (skip check)] a.{self::A::unboxedDouble} = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : 2.2;
- [@vm.direct-call.metadata=#lib::A.boxedNullableInt] [@vm.inferred-type.metadata=!? (skip check)] a.{self::A::boxedNullableInt} = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : null;
- [@vm.direct-call.metadata=#lib::A.boxedNullableDouble] [@vm.inferred-type.metadata=!? (skip check)] a.{self::A::boxedNullableDouble} = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : null;
- [@vm.direct-call.metadata=#lib::A.boxedNonNullableIntOrDouble] [@vm.inferred-type.metadata=!? (skip check)] a.{self::A::boxedNonNullableIntOrDouble} = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1;
- [@vm.direct-call.metadata=#lib::A.boxedNullableIntOrDouble] [@vm.inferred-type.metadata=!? (skip check)] a.{self::A::boxedNullableIntOrDouble} = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null;
- [@vm.direct-call.metadata=#lib::A.boxedNullableX] [@vm.inferred-type.metadata=!? (skip check)] a.{self::A::boxedNullableX} = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X*} new self::X::•() : null;
+ final self::A a = new self::A::•([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} 1 : 2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} [@vm.inferred-type.metadata=int] self::smiOrMint : 2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double} 1.1 : 2.2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int?} [@vm.inferred-type.metadata=int] self::smiOrMint : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double?} 1.1 : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num?} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X?} new self::X::•() : null, new self::X::•());
+ [@vm.direct-call.metadata=#lib::A.unboxedSmi] [@vm.inferred-type.metadata=!? (skip check)] a.{self::A::unboxedSmi} = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} 1 : 2;
+ [@vm.direct-call.metadata=#lib::A.unboxedInt] [@vm.inferred-type.metadata=!? (skip check)] a.{self::A::unboxedInt} = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} [@vm.inferred-type.metadata=int] self::smiOrMint : 2;
+ [@vm.direct-call.metadata=#lib::A.unboxedDouble] [@vm.inferred-type.metadata=!? (skip check)] a.{self::A::unboxedDouble} = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double} 1.1 : 2.2;
+ [@vm.direct-call.metadata=#lib::A.boxedNullableInt] [@vm.inferred-type.metadata=!? (skip check)] a.{self::A::boxedNullableInt} = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int?} [@vm.inferred-type.metadata=int] self::smiOrMint : null;
+ [@vm.direct-call.metadata=#lib::A.boxedNullableDouble] [@vm.inferred-type.metadata=!? (skip check)] a.{self::A::boxedNullableDouble} = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double?} 1.1 : null;
+ [@vm.direct-call.metadata=#lib::A.boxedNonNullableIntOrDouble] [@vm.inferred-type.metadata=!? (skip check)] a.{self::A::boxedNonNullableIntOrDouble} = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1;
+ [@vm.direct-call.metadata=#lib::A.boxedNullableIntOrDouble] [@vm.inferred-type.metadata=!? (skip check)] a.{self::A::boxedNullableIntOrDouble} = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num?} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null;
+ [@vm.direct-call.metadata=#lib::A.boxedNullableX] [@vm.inferred-type.metadata=!? (skip check)] a.{self::A::boxedNullableX} = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X?} new self::X::•() : null;
[@vm.direct-call.metadata=#lib::A.boxedX] [@vm.inferred-type.metadata=!? (skip check)] a.{self::A::boxedX} = new self::X::•();
self::use([@vm.direct-call.metadata=#lib::A.unboxedSmi] [@vm.inferred-type.metadata=dart.core::_Smi] a.{self::A::unboxedSmi}{dynamic});
self::use([@vm.direct-call.metadata=#lib::A.unboxedInt] [@vm.inferred-type.metadata=int] a.{self::A::unboxedInt}{dynamic});
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method.dart b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method.dart
index f37b67e..f367c3e 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method.dart
@@ -16,7 +16,7 @@
abstract class Interface {
void takePositional(
- int unboxedSmi,
+ int? unboxedSmi,
dynamic unboxedInt,
dynamic unboxedDouble,
dynamic boxedNullableInt,
@@ -26,20 +26,20 @@
dynamic boxedNullableX,
dynamic boxedX);
- dynamic returnUnboxedSmi(X ignored);
- dynamic returnUnboxedInt(X ignored);
- dynamic returnUnboxedDouble(X ignored);
- dynamic returnBoxedNullableInt(X ignored);
- dynamic returnBoxedNullableDouble(X ignored);
- dynamic returnBoxedIntOrDouble(X ignored);
- dynamic returnBoxedNullableIntOrDouble(X ignored);
- dynamic returnBoxedNullableX(X ignored);
- dynamic returnBoxedX(X ignored);
+ dynamic returnUnboxedSmi(X? ignored);
+ dynamic returnUnboxedInt(X? ignored);
+ dynamic returnUnboxedDouble(X? ignored);
+ dynamic returnBoxedNullableInt(X? ignored);
+ dynamic returnBoxedNullableDouble(X? ignored);
+ dynamic returnBoxedIntOrDouble(X? ignored);
+ dynamic returnBoxedNullableIntOrDouble(X? ignored);
+ dynamic returnBoxedNullableX(X? ignored);
+ dynamic returnBoxedX(X? ignored);
}
class Impl1 implements Interface {
void takePositional(
- int unboxedSmi,
+ int? unboxedSmi,
dynamic unboxedInt,
dynamic unboxedDouble,
dynamic boxedNullableInt,
@@ -58,20 +58,20 @@
use(boxedX);
}
- dynamic returnUnboxedSmi(X ignored) => 1;
- dynamic returnUnboxedInt(X ignored) => 1;
- dynamic returnUnboxedDouble(X ignored) => 1.1;
- dynamic returnBoxedNullableInt(X ignored) => null;
- dynamic returnBoxedNullableDouble(X ignored) => null;
- dynamic returnBoxedIntOrDouble(X ignored) => 1;
- dynamic returnBoxedNullableIntOrDouble(X ignored) => null;
- dynamic returnBoxedNullableX(X ignored) => null;
- dynamic returnBoxedX(X ignored) => X();
+ dynamic returnUnboxedSmi(X? ignored) => 1;
+ dynamic returnUnboxedInt(X? ignored) => 1;
+ dynamic returnUnboxedDouble(X? ignored) => 1.1;
+ dynamic returnBoxedNullableInt(X? ignored) => null;
+ dynamic returnBoxedNullableDouble(X? ignored) => null;
+ dynamic returnBoxedIntOrDouble(X? ignored) => 1;
+ dynamic returnBoxedNullableIntOrDouble(X? ignored) => null;
+ dynamic returnBoxedNullableX(X? ignored) => null;
+ dynamic returnBoxedX(X? ignored) => X();
}
class BaseImpl2 {
void takePositional(
- int unboxedSmi,
+ int? unboxedSmi,
dynamic unboxedInt,
dynamic unboxedDouble,
dynamic boxedNullableInt,
@@ -90,20 +90,20 @@
use(boxedX);
}
- dynamic returnUnboxedSmi(X ignored) => 2;
- dynamic returnUnboxedInt(X ignored) => mint;
- dynamic returnUnboxedDouble(X ignored) => 2.2;
- dynamic returnBoxedNullableInt(X ignored) => 2;
- dynamic returnBoxedNullableDouble(X ignored) => 2.2;
- dynamic returnBoxedIntOrDouble(X ignored) => 2.2;
- dynamic returnBoxedNullableIntOrDouble(X ignored) => 2;
- dynamic returnBoxedNullableX(X ignored) => X();
- dynamic returnBoxedX(X ignored) => X();
+ dynamic returnUnboxedSmi(X? ignored) => 2;
+ dynamic returnUnboxedInt(X? ignored) => mint;
+ dynamic returnUnboxedDouble(X? ignored) => 2.2;
+ dynamic returnBoxedNullableInt(X? ignored) => 2;
+ dynamic returnBoxedNullableDouble(X? ignored) => 2.2;
+ dynamic returnBoxedIntOrDouble(X? ignored) => 2.2;
+ dynamic returnBoxedNullableIntOrDouble(X? ignored) => 2;
+ dynamic returnBoxedNullableX(X? ignored) => X();
+ dynamic returnBoxedX(X? ignored) => X();
}
class SubImpl3 extends BaseImpl2 implements Interface {
void takePositional(
- int unboxedSmi,
+ int? unboxedSmi,
dynamic unboxedInt,
dynamic unboxedDouble,
dynamic boxedNullableInt,
@@ -122,15 +122,15 @@
use(boxedX);
}
- dynamic returnUnboxedSmi(X ignored) => 3;
- dynamic returnUnboxedInt(X ignored) => mint;
- dynamic returnUnboxedDouble(X ignored) => 3.3;
- dynamic returnBoxedNullableInt(X ignored) => mint;
- dynamic returnBoxedNullableDouble(X ignored) => 3.3;
- dynamic returnBoxedIntOrDouble(X ignored) => 3.3;
- dynamic returnBoxedNullableIntOrDouble(X ignored) => 3.3;
- dynamic returnBoxedNullableX(X ignored) => X();
- dynamic returnBoxedX(X ignored) => X();
+ dynamic returnUnboxedSmi(X? ignored) => 3;
+ dynamic returnUnboxedInt(X? ignored) => mint;
+ dynamic returnUnboxedDouble(X? ignored) => 3.3;
+ dynamic returnBoxedNullableInt(X? ignored) => mint;
+ dynamic returnBoxedNullableDouble(X? ignored) => 3.3;
+ dynamic returnBoxedIntOrDouble(X? ignored) => 3.3;
+ dynamic returnBoxedNullableIntOrDouble(X? ignored) => 3.3;
+ dynamic returnBoxedNullableX(X? ignored) => X();
+ dynamic returnBoxedX(X? ignored) => X();
}
main() {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method.dart.expect
index 0811f05..40650ad 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method.dart.expect
@@ -1,9 +1,9 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
class X extends core::Object {
- synthetic constructor •() → self::X*
+ synthetic constructor •() → self::X
: super core::Object::•()
;
}
@@ -20,7 +20,7 @@
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:19,getterSelectorId:20] abstract method returnBoxedX() → dynamic;
}
class Impl1 extends core::Object implements self::Interface {
- synthetic constructor •() → self::Impl1*
+ synthetic constructor •() → self::Impl1
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=(i,d,b,b,b,b,b,b)->b] method takePositional([@vm.inferred-type.metadata=int] dynamic unboxedInt, [@vm.inferred-type.metadata=dart.core::_Double] dynamic unboxedDouble, [@vm.inferred-type.metadata=int?] dynamic boxedNullableInt, [@vm.inferred-type.metadata=dart.core::_Double?] dynamic boxedNullableDouble, [@vm.inferred-type.metadata=!] dynamic boxedNonNullableIntOrDouble, [@vm.inferred-type.metadata=dart.core::_Double?] dynamic boxedNullableIntOrDouble, [@vm.inferred-type.metadata=#lib::X?] dynamic boxedNullableX, [@vm.inferred-type.metadata=#lib::X] dynamic boxedX) → void {
@@ -53,7 +53,7 @@
return new self::X::•();
}
class BaseImpl2 extends core::Object {
- synthetic constructor •() → self::BaseImpl2*
+ synthetic constructor •() → self::BaseImpl2
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=(i,d,b,b,b,b,b,b)->b] method takePositional([@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic unboxedInt, [@vm.inferred-type.metadata=dart.core::_Double (value: 2.2)] dynamic unboxedDouble, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic boxedNullableInt, [@vm.inferred-type.metadata=dart.core::_Double (value: 2.2)] dynamic boxedNullableDouble, [@vm.inferred-type.metadata=dart.core::_Double (value: 2.2)] dynamic boxedNonNullableIntOrDouble, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic boxedNullableIntOrDouble, [@vm.inferred-type.metadata=#lib::X] dynamic boxedNullableX, [@vm.inferred-type.metadata=#lib::X] dynamic boxedX) → void {
@@ -86,7 +86,7 @@
return new self::X::•();
}
class SubImpl3 extends self::BaseImpl2 implements self::Interface {
- synthetic constructor •() → self::SubImpl3*
+ synthetic constructor •() → self::SubImpl3
: super self::BaseImpl2::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] [@vm.unboxing-info.metadata=(i,d,b,b,b,b,b,b)->b] method takePositional([@vm.inferred-type.metadata=int] dynamic unboxedInt, [@vm.inferred-type.metadata=dart.core::_Double] dynamic unboxedDouble, [@vm.inferred-type.metadata=int] dynamic boxedNullableInt, [@vm.inferred-type.metadata=dart.core::_Double] dynamic boxedNullableDouble, [@vm.inferred-type.metadata=dart.core::_Double] dynamic boxedNonNullableIntOrDouble, [@vm.inferred-type.metadata=!] dynamic boxedNullableIntOrDouble, [@vm.inferred-type.metadata=#lib::X] dynamic boxedNullableX, [@vm.inferred-type.metadata=#lib::X] dynamic boxedX) → void {
@@ -119,55 +119,55 @@
return new self::X::•();
}
static field dynamic usedObject;
-[@vm.unboxing-info.metadata=()->i]static get mint() → core::int*
+[@vm.unboxing-info.metadata=()->i]static get mint() → core::int
return -6144092014192636707;
static method use(dynamic object) → void {
self::usedObject == null ?{dynamic} self::usedObject = object : null;
}
static method main() → dynamic {
- final core::List<core::Object*>* values = [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::Object*>] core::_GrowableList::_literal3<core::Object*>(new self::Impl1::•(), new self::BaseImpl2::•(), new self::SubImpl3::•());
- final self::Impl1* a = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int?] core::int::parse("0")){(core::int*) →* core::Object*} as self::Impl1*;
- final self::BaseImpl2* b = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int?] core::int::parse("1")){(core::int*) →* core::Object*} as self::BaseImpl2*;
- final self::SubImpl3* c = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int?] core::int::parse("2")){(core::int*) →* core::Object*} as self::SubImpl3*;
- final self::Interface* d = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int?] core::int::parse("2")){(core::int*) →* core::Object*} as self::Interface*;
- [@vm.direct-call.metadata=#lib::Impl1.takePositional??] [@vm.inferred-type.metadata=!? (skip check)] a.{self::Impl1::takePositional}(1, 1.1, null, null, 1, null, null, new self::X::•()){(core::int*, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) →* void};
- b.{self::BaseImpl2::takePositional}(2, 2.2, 2, 2.2, 2.2, 2, new self::X::•(), new self::X::•()){(core::int*, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) →* void};
- [@vm.direct-call.metadata=#lib::SubImpl3.takePositional??] [@vm.inferred-type.metadata=!? (skip check)] c.{self::SubImpl3::takePositional}([@vm.inferred-type.metadata=int] self::mint, 3.3, [@vm.inferred-type.metadata=int] self::mint, 3.3, 3.3, 3.3, new self::X::•(), new self::X::•()){(core::int*, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) →* void};
- d.{self::Interface::takePositional}([@vm.inferred-type.metadata=int] self::mint, 3.3, [@vm.inferred-type.metadata=int] self::mint, 3.3, 3.3, 3.3, new self::X::•(), new self::X::•()){(core::int*, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) →* void};
- self::use([@vm.direct-call.metadata=#lib::Impl1.returnUnboxedSmi] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 1)] a.{self::Impl1::returnUnboxedSmi}(){(self::X*) →* dynamic});
- self::use([@vm.direct-call.metadata=#lib::Impl1.returnUnboxedInt] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 1)] a.{self::Impl1::returnUnboxedInt}(){(self::X*) →* dynamic});
- self::use([@vm.direct-call.metadata=#lib::Impl1.returnUnboxedDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 1.1)] a.{self::Impl1::returnUnboxedDouble}(){(self::X*) →* dynamic});
- self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableInt] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableInt}(){(self::X*) →* dynamic});
- self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableDouble] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableDouble}(){(self::X*) →* dynamic});
- self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedIntOrDouble] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 1)] a.{self::Impl1::returnBoxedIntOrDouble}(){(self::X*) →* dynamic});
- self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableIntOrDouble] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableIntOrDouble}(){(self::X*) →* dynamic});
- self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableX] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableX}(){(self::X*) →* dynamic});
- self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedX] [@vm.inferred-type.metadata=#lib::X (skip check)] a.{self::Impl1::returnBoxedX}(){(self::X*) →* dynamic});
- self::use([@vm.inferred-type.metadata=dart.core::_Smi] b.{self::BaseImpl2::returnUnboxedSmi}(){(self::X*) →* dynamic});
- self::use([@vm.inferred-type.metadata=int] b.{self::BaseImpl2::returnUnboxedInt}(){(self::X*) →* dynamic});
- self::use([@vm.inferred-type.metadata=dart.core::_Double] b.{self::BaseImpl2::returnUnboxedDouble}(){(self::X*) →* dynamic});
- self::use([@vm.inferred-type.metadata=int] b.{self::BaseImpl2::returnBoxedNullableInt}(){(self::X*) →* dynamic});
- self::use([@vm.inferred-type.metadata=dart.core::_Double] b.{self::BaseImpl2::returnBoxedNullableDouble}(){(self::X*) →* dynamic});
- self::use([@vm.inferred-type.metadata=dart.core::_Double] b.{self::BaseImpl2::returnBoxedIntOrDouble}(){(self::X*) →* dynamic});
- self::use([@vm.inferred-type.metadata=!] b.{self::BaseImpl2::returnBoxedNullableIntOrDouble}(){(self::X*) →* dynamic});
- self::use([@vm.inferred-type.metadata=#lib::X] b.{self::BaseImpl2::returnBoxedNullableX}(){(self::X*) →* dynamic});
- self::use([@vm.inferred-type.metadata=#lib::X] b.{self::BaseImpl2::returnBoxedX}(){(self::X*) →* dynamic});
- self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnUnboxedSmi] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 3)] c.{self::SubImpl3::returnUnboxedSmi}(){(self::X*) →* dynamic});
- self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnUnboxedInt] [@vm.inferred-type.metadata=int (skip check)] c.{self::SubImpl3::returnUnboxedInt}(){(self::X*) →* dynamic});
- self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnUnboxedDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnUnboxedDouble}(){(self::X*) →* dynamic});
- self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableInt] [@vm.inferred-type.metadata=int (skip check)] c.{self::SubImpl3::returnBoxedNullableInt}(){(self::X*) →* dynamic});
- self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnBoxedNullableDouble}(){(self::X*) →* dynamic});
- self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedIntOrDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnBoxedIntOrDouble}(){(self::X*) →* dynamic});
- self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableIntOrDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnBoxedNullableIntOrDouble}(){(self::X*) →* dynamic});
- self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableX] [@vm.inferred-type.metadata=#lib::X (skip check)] c.{self::SubImpl3::returnBoxedNullableX}(){(self::X*) →* dynamic});
- self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedX] [@vm.inferred-type.metadata=#lib::X (skip check)] c.{self::SubImpl3::returnBoxedX}(){(self::X*) →* dynamic});
- self::use([@vm.inferred-type.metadata=dart.core::_Smi] d.{self::Interface::returnUnboxedSmi}(){(self::X*) →* dynamic});
- self::use([@vm.inferred-type.metadata=int] d.{self::Interface::returnUnboxedInt}(){(self::X*) →* dynamic});
- self::use([@vm.inferred-type.metadata=dart.core::_Double] d.{self::Interface::returnUnboxedDouble}(){(self::X*) →* dynamic});
- self::use([@vm.inferred-type.metadata=int?] d.{self::Interface::returnBoxedNullableInt}(){(self::X*) →* dynamic});
- self::use([@vm.inferred-type.metadata=dart.core::_Double?] d.{self::Interface::returnBoxedNullableDouble}(){(self::X*) →* dynamic});
- self::use([@vm.inferred-type.metadata=!] d.{self::Interface::returnBoxedIntOrDouble}(){(self::X*) →* dynamic});
- self::use([@vm.inferred-type.metadata=dart.core::_Double?] d.{self::Interface::returnBoxedNullableIntOrDouble}(){(self::X*) →* dynamic});
- self::use([@vm.inferred-type.metadata=#lib::X?] d.{self::Interface::returnBoxedNullableX}(){(self::X*) →* dynamic});
- self::use([@vm.inferred-type.metadata=#lib::X] d.{self::Interface::returnBoxedX}(){(self::X*) →* dynamic});
+ final core::List<core::Object> values = [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::Object>] core::_GrowableList::_literal3<core::Object>(new self::Impl1::•(), new self::BaseImpl2::•(), new self::SubImpl3::•());
+ final self::Impl1 a = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int?] core::int::parse("0")){(core::int) → core::Object} as{ForNonNullableByDefault} self::Impl1;
+ final self::BaseImpl2 b = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int?] core::int::parse("1")){(core::int) → core::Object} as{ForNonNullableByDefault} self::BaseImpl2;
+ final self::SubImpl3 c = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int?] core::int::parse("2")){(core::int) → core::Object} as{ForNonNullableByDefault} self::SubImpl3;
+ final self::Interface d = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int?] core::int::parse("2")){(core::int) → core::Object} as{ForNonNullableByDefault} self::Interface;
+ [@vm.direct-call.metadata=#lib::Impl1.takePositional??] [@vm.inferred-type.metadata=!? (skip check)] a.{self::Impl1::takePositional}(1, 1.1, null, null, 1, null, null, new self::X::•()){(core::int?, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) → void};
+ b.{self::BaseImpl2::takePositional}(2, 2.2, 2, 2.2, 2.2, 2, new self::X::•(), new self::X::•()){(core::int?, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) → void};
+ [@vm.direct-call.metadata=#lib::SubImpl3.takePositional??] [@vm.inferred-type.metadata=!? (skip check)] c.{self::SubImpl3::takePositional}([@vm.inferred-type.metadata=int] self::mint, 3.3, [@vm.inferred-type.metadata=int] self::mint, 3.3, 3.3, 3.3, new self::X::•(), new self::X::•()){(core::int?, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) → void};
+ d.{self::Interface::takePositional}([@vm.inferred-type.metadata=int] self::mint, 3.3, [@vm.inferred-type.metadata=int] self::mint, 3.3, 3.3, 3.3, new self::X::•(), new self::X::•()){(core::int?, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) → void};
+ self::use([@vm.direct-call.metadata=#lib::Impl1.returnUnboxedSmi] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 1)] a.{self::Impl1::returnUnboxedSmi}(){(self::X?) → dynamic});
+ self::use([@vm.direct-call.metadata=#lib::Impl1.returnUnboxedInt] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 1)] a.{self::Impl1::returnUnboxedInt}(){(self::X?) → dynamic});
+ self::use([@vm.direct-call.metadata=#lib::Impl1.returnUnboxedDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 1.1)] a.{self::Impl1::returnUnboxedDouble}(){(self::X?) → dynamic});
+ self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableInt] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableInt}(){(self::X?) → dynamic});
+ self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableDouble] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableDouble}(){(self::X?) → dynamic});
+ self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedIntOrDouble] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 1)] a.{self::Impl1::returnBoxedIntOrDouble}(){(self::X?) → dynamic});
+ self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableIntOrDouble] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableIntOrDouble}(){(self::X?) → dynamic});
+ self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableX] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableX}(){(self::X?) → dynamic});
+ self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedX] [@vm.inferred-type.metadata=#lib::X (skip check)] a.{self::Impl1::returnBoxedX}(){(self::X?) → dynamic});
+ self::use([@vm.inferred-type.metadata=dart.core::_Smi] b.{self::BaseImpl2::returnUnboxedSmi}(){(self::X?) → dynamic});
+ self::use([@vm.inferred-type.metadata=int] b.{self::BaseImpl2::returnUnboxedInt}(){(self::X?) → dynamic});
+ self::use([@vm.inferred-type.metadata=dart.core::_Double] b.{self::BaseImpl2::returnUnboxedDouble}(){(self::X?) → dynamic});
+ self::use([@vm.inferred-type.metadata=int] b.{self::BaseImpl2::returnBoxedNullableInt}(){(self::X?) → dynamic});
+ self::use([@vm.inferred-type.metadata=dart.core::_Double] b.{self::BaseImpl2::returnBoxedNullableDouble}(){(self::X?) → dynamic});
+ self::use([@vm.inferred-type.metadata=dart.core::_Double] b.{self::BaseImpl2::returnBoxedIntOrDouble}(){(self::X?) → dynamic});
+ self::use([@vm.inferred-type.metadata=!] b.{self::BaseImpl2::returnBoxedNullableIntOrDouble}(){(self::X?) → dynamic});
+ self::use([@vm.inferred-type.metadata=#lib::X] b.{self::BaseImpl2::returnBoxedNullableX}(){(self::X?) → dynamic});
+ self::use([@vm.inferred-type.metadata=#lib::X] b.{self::BaseImpl2::returnBoxedX}(){(self::X?) → dynamic});
+ self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnUnboxedSmi] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 3)] c.{self::SubImpl3::returnUnboxedSmi}(){(self::X?) → dynamic});
+ self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnUnboxedInt] [@vm.inferred-type.metadata=int (skip check)] c.{self::SubImpl3::returnUnboxedInt}(){(self::X?) → dynamic});
+ self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnUnboxedDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnUnboxedDouble}(){(self::X?) → dynamic});
+ self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableInt] [@vm.inferred-type.metadata=int (skip check)] c.{self::SubImpl3::returnBoxedNullableInt}(){(self::X?) → dynamic});
+ self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnBoxedNullableDouble}(){(self::X?) → dynamic});
+ self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedIntOrDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnBoxedIntOrDouble}(){(self::X?) → dynamic});
+ self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableIntOrDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnBoxedNullableIntOrDouble}(){(self::X?) → dynamic});
+ self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableX] [@vm.inferred-type.metadata=#lib::X (skip check)] c.{self::SubImpl3::returnBoxedNullableX}(){(self::X?) → dynamic});
+ self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedX] [@vm.inferred-type.metadata=#lib::X (skip check)] c.{self::SubImpl3::returnBoxedX}(){(self::X?) → dynamic});
+ self::use([@vm.inferred-type.metadata=dart.core::_Smi] d.{self::Interface::returnUnboxedSmi}(){(self::X?) → dynamic});
+ self::use([@vm.inferred-type.metadata=int] d.{self::Interface::returnUnboxedInt}(){(self::X?) → dynamic});
+ self::use([@vm.inferred-type.metadata=dart.core::_Double] d.{self::Interface::returnUnboxedDouble}(){(self::X?) → dynamic});
+ self::use([@vm.inferred-type.metadata=int?] d.{self::Interface::returnBoxedNullableInt}(){(self::X?) → dynamic});
+ self::use([@vm.inferred-type.metadata=dart.core::_Double?] d.{self::Interface::returnBoxedNullableDouble}(){(self::X?) → dynamic});
+ self::use([@vm.inferred-type.metadata=!] d.{self::Interface::returnBoxedIntOrDouble}(){(self::X?) → dynamic});
+ self::use([@vm.inferred-type.metadata=dart.core::_Double?] d.{self::Interface::returnBoxedNullableIntOrDouble}(){(self::X?) → dynamic});
+ self::use([@vm.inferred-type.metadata=#lib::X?] d.{self::Interface::returnBoxedNullableX}(){(self::X?) → dynamic});
+ self::use([@vm.inferred-type.metadata=#lib::X] d.{self::Interface::returnBoxedX}(){(self::X?) → dynamic});
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method_tearoff.dart b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method_tearoff.dart
index ddbf2a0..f8637c8 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method_tearoff.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method_tearoff.dart
@@ -16,7 +16,7 @@
abstract class Interface {
void takePositional(
- int unboxedSmi,
+ int? unboxedSmi,
dynamic unboxedInt,
dynamic unboxedDouble,
dynamic boxedNullableInt,
@@ -26,20 +26,20 @@
dynamic boxedNullableX,
dynamic boxedX);
- dynamic returnUnboxedSmi(X ignored);
- dynamic returnUnboxedInt(X ignored);
- dynamic returnUnboxedDouble(X ignored);
- dynamic returnBoxedNullableInt(X ignored);
- dynamic returnBoxedNullableDouble(X ignored);
- dynamic returnBoxedIntOrDouble(X ignored);
- dynamic returnBoxedNullableIntOrDouble(X ignored);
- dynamic returnBoxedNullableX(X ignored);
- dynamic returnBoxedX(X ignored);
+ dynamic returnUnboxedSmi(X? ignored);
+ dynamic returnUnboxedInt(X? ignored);
+ dynamic returnUnboxedDouble(X? ignored);
+ dynamic returnBoxedNullableInt(X? ignored);
+ dynamic returnBoxedNullableDouble(X? ignored);
+ dynamic returnBoxedIntOrDouble(X? ignored);
+ dynamic returnBoxedNullableIntOrDouble(X? ignored);
+ dynamic returnBoxedNullableX(X? ignored);
+ dynamic returnBoxedX(X? ignored);
}
class Impl1 implements Interface {
void takePositional(
- int unboxedSmi,
+ int? unboxedSmi,
dynamic unboxedInt,
dynamic unboxedDouble,
dynamic boxedNullableInt,
@@ -58,20 +58,20 @@
use(boxedX);
}
- dynamic returnUnboxedSmi(X ignored) => 1;
- dynamic returnUnboxedInt(X ignored) => 1;
- dynamic returnUnboxedDouble(X ignored) => 1.1;
- dynamic returnBoxedNullableInt(X ignored) => null;
- dynamic returnBoxedNullableDouble(X ignored) => null;
- dynamic returnBoxedIntOrDouble(X ignored) => 1;
- dynamic returnBoxedNullableIntOrDouble(X ignored) => null;
- dynamic returnBoxedNullableX(X ignored) => null;
- dynamic returnBoxedX(X ignored) => X();
+ dynamic returnUnboxedSmi(X? ignored) => 1;
+ dynamic returnUnboxedInt(X? ignored) => 1;
+ dynamic returnUnboxedDouble(X? ignored) => 1.1;
+ dynamic returnBoxedNullableInt(X? ignored) => null;
+ dynamic returnBoxedNullableDouble(X? ignored) => null;
+ dynamic returnBoxedIntOrDouble(X? ignored) => 1;
+ dynamic returnBoxedNullableIntOrDouble(X? ignored) => null;
+ dynamic returnBoxedNullableX(X? ignored) => null;
+ dynamic returnBoxedX(X? ignored) => X();
}
class BaseImpl2 {
void takePositional(
- int unboxedSmi,
+ int? unboxedSmi,
dynamic unboxedInt,
dynamic unboxedDouble,
dynamic boxedNullableInt,
@@ -90,20 +90,20 @@
use(boxedX);
}
- dynamic returnUnboxedSmi(X ignored) => 2;
- dynamic returnUnboxedInt(X ignored) => mint;
- dynamic returnUnboxedDouble(X ignored) => 2.2;
- dynamic returnBoxedNullableInt(X ignored) => 2;
- dynamic returnBoxedNullableDouble(X ignored) => 2.2;
- dynamic returnBoxedIntOrDouble(X ignored) => 2.2;
- dynamic returnBoxedNullableIntOrDouble(X ignored) => 2;
- dynamic returnBoxedNullableX(X ignored) => X();
- dynamic returnBoxedX(X ignored) => X();
+ dynamic returnUnboxedSmi(X? ignored) => 2;
+ dynamic returnUnboxedInt(X? ignored) => mint;
+ dynamic returnUnboxedDouble(X? ignored) => 2.2;
+ dynamic returnBoxedNullableInt(X? ignored) => 2;
+ dynamic returnBoxedNullableDouble(X? ignored) => 2.2;
+ dynamic returnBoxedIntOrDouble(X? ignored) => 2.2;
+ dynamic returnBoxedNullableIntOrDouble(X? ignored) => 2;
+ dynamic returnBoxedNullableX(X? ignored) => X();
+ dynamic returnBoxedX(X? ignored) => X();
}
class SubImpl3 extends BaseImpl2 implements Interface {
void takePositional(
- int unboxedSmi,
+ int? unboxedSmi,
dynamic unboxedInt,
dynamic unboxedDouble,
dynamic boxedNullableInt,
@@ -122,15 +122,15 @@
use(boxedX);
}
- dynamic returnUnboxedSmi(X ignored) => 3;
- dynamic returnUnboxedInt(X ignored) => mint;
- dynamic returnUnboxedDouble(X ignored) => 3.3;
- dynamic returnBoxedNullableInt(X ignored) => mint;
- dynamic returnBoxedNullableDouble(X ignored) => 3.3;
- dynamic returnBoxedIntOrDouble(X ignored) => 3.3;
- dynamic returnBoxedNullableIntOrDouble(X ignored) => 3.3;
- dynamic returnBoxedNullableX(X ignored) => X();
- dynamic returnBoxedX(X ignored) => X();
+ dynamic returnUnboxedSmi(X? ignored) => 3;
+ dynamic returnUnboxedInt(X? ignored) => mint;
+ dynamic returnUnboxedDouble(X? ignored) => 3.3;
+ dynamic returnBoxedNullableInt(X? ignored) => mint;
+ dynamic returnBoxedNullableDouble(X? ignored) => 3.3;
+ dynamic returnBoxedIntOrDouble(X? ignored) => 3.3;
+ dynamic returnBoxedNullableIntOrDouble(X? ignored) => 3.3;
+ dynamic returnBoxedNullableX(X? ignored) => X();
+ dynamic returnBoxedX(X? ignored) => X();
}
main() {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method_tearoff.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method_tearoff.dart.expect
index d22492c..2405a88 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method_tearoff.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_instance_method_tearoff.dart.expect
@@ -1,29 +1,29 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
class X extends core::Object {
- synthetic constructor •() → self::X*
+ synthetic constructor •() → self::X
: super core::Object::•()
;
}
abstract class Interface extends core::Object {
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] abstract method takePositional(core::int* unboxedSmi, dynamic unboxedInt, dynamic unboxedDouble, dynamic boxedNullableInt, dynamic boxedNullableDouble, dynamic boxedNonNullableIntOrDouble, dynamic boxedNullableIntOrDouble, dynamic boxedNullableX, dynamic boxedX) → void;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] [@vm.unboxing-info.metadata=(b)->i] abstract method returnUnboxedSmi(self::X* ignored) → dynamic;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=(b)->i] abstract method returnUnboxedInt(self::X* ignored) → dynamic;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] [@vm.unboxing-info.metadata=(b)->d] abstract method returnUnboxedDouble(self::X* ignored) → dynamic;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10] abstract method returnBoxedNullableInt(self::X* ignored) → dynamic;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] abstract method returnBoxedNullableDouble(self::X* ignored) → dynamic;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14] abstract method returnBoxedIntOrDouble(self::X* ignored) → dynamic;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:15,getterSelectorId:16] abstract method returnBoxedNullableIntOrDouble(self::X* ignored) → dynamic;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:17,getterSelectorId:18] abstract method returnBoxedNullableX(self::X* ignored) → dynamic;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:19,getterSelectorId:20] abstract method returnBoxedX(self::X* ignored) → dynamic;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] abstract method takePositional(core::int? unboxedSmi, dynamic unboxedInt, dynamic unboxedDouble, dynamic boxedNullableInt, dynamic boxedNullableDouble, dynamic boxedNonNullableIntOrDouble, dynamic boxedNullableIntOrDouble, dynamic boxedNullableX, dynamic boxedX) → void;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] [@vm.unboxing-info.metadata=(b)->i] abstract method returnUnboxedSmi(self::X? ignored) → dynamic;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=(b)->i] abstract method returnUnboxedInt(self::X? ignored) → dynamic;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] [@vm.unboxing-info.metadata=(b)->d] abstract method returnUnboxedDouble(self::X? ignored) → dynamic;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10] abstract method returnBoxedNullableInt(self::X? ignored) → dynamic;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] abstract method returnBoxedNullableDouble(self::X? ignored) → dynamic;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14] abstract method returnBoxedIntOrDouble(self::X? ignored) → dynamic;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:15,getterSelectorId:16] abstract method returnBoxedNullableIntOrDouble(self::X? ignored) → dynamic;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:17,getterSelectorId:18] abstract method returnBoxedNullableX(self::X? ignored) → dynamic;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:19,getterSelectorId:20] abstract method returnBoxedX(self::X? ignored) → dynamic;
}
class Impl1 extends core::Object implements self::Interface {
- synthetic constructor •() → self::Impl1*
+ synthetic constructor •() → self::Impl1
: super core::Object::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method takePositional(core::int* unboxedSmi, dynamic unboxedInt, dynamic unboxedDouble, dynamic boxedNullableInt, dynamic boxedNullableDouble, dynamic boxedNonNullableIntOrDouble, dynamic boxedNullableIntOrDouble, dynamic boxedNullableX, dynamic boxedX) → void {
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method takePositional(core::int? unboxedSmi, dynamic unboxedInt, dynamic unboxedDouble, dynamic boxedNullableInt, dynamic boxedNullableDouble, dynamic boxedNonNullableIntOrDouble, dynamic boxedNullableIntOrDouble, dynamic boxedNullableX, dynamic boxedX) → void {
self::use(unboxedInt);
self::use(unboxedDouble);
self::use(boxedNullableInt);
@@ -33,30 +33,30 @@
self::use(boxedNullableX);
self::use(boxedX);
}
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] [@vm.unboxing-info.metadata=(b)->i] method returnUnboxedSmi(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] [@vm.unboxing-info.metadata=(b)->i] method returnUnboxedSmi(self::X? ignored) → dynamic
return 1;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=(b)->i] method returnUnboxedInt(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=(b)->i] method returnUnboxedInt(self::X? ignored) → dynamic
return 1;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] [@vm.unboxing-info.metadata=(b)->d] method returnUnboxedDouble(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] [@vm.unboxing-info.metadata=(b)->d] method returnUnboxedDouble(self::X? ignored) → dynamic
return 1.1;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:9,getterSelectorId:10] method returnBoxedNullableInt(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:9,getterSelectorId:10] method returnBoxedNullableInt(self::X? ignored) → dynamic
return null;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] method returnBoxedNullableDouble(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] method returnBoxedNullableDouble(self::X? ignored) → dynamic
return null;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:13,getterSelectorId:14] method returnBoxedIntOrDouble(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:13,getterSelectorId:14] method returnBoxedIntOrDouble(self::X? ignored) → dynamic
return 1;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:15,getterSelectorId:16] method returnBoxedNullableIntOrDouble(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:15,getterSelectorId:16] method returnBoxedNullableIntOrDouble(self::X? ignored) → dynamic
return null;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:17,getterSelectorId:18] method returnBoxedNullableX(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:17,getterSelectorId:18] method returnBoxedNullableX(self::X? ignored) → dynamic
return null;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:19,getterSelectorId:20] method returnBoxedX(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:19,getterSelectorId:20] method returnBoxedX(self::X? ignored) → dynamic
return new self::X::•();
}
class BaseImpl2 extends core::Object {
- synthetic constructor •() → self::BaseImpl2*
+ synthetic constructor •() → self::BaseImpl2
: super core::Object::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method takePositional([@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] core::int* unboxedSmi, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic unboxedInt, [@vm.inferred-type.metadata=dart.core::_Double (value: 2.2)] dynamic unboxedDouble, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic boxedNullableInt, [@vm.inferred-type.metadata=dart.core::_Double (value: 2.2)] dynamic boxedNullableDouble, [@vm.inferred-type.metadata=dart.core::_Double (value: 2.2)] dynamic boxedNonNullableIntOrDouble, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic boxedNullableIntOrDouble, [@vm.inferred-type.metadata=#lib::X] dynamic boxedNullableX, [@vm.inferred-type.metadata=#lib::X] dynamic boxedX) → void {
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method takePositional([@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] core::int? unboxedSmi, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic unboxedInt, [@vm.inferred-type.metadata=dart.core::_Double (value: 2.2)] dynamic unboxedDouble, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic boxedNullableInt, [@vm.inferred-type.metadata=dart.core::_Double (value: 2.2)] dynamic boxedNullableDouble, [@vm.inferred-type.metadata=dart.core::_Double (value: 2.2)] dynamic boxedNonNullableIntOrDouble, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic boxedNullableIntOrDouble, [@vm.inferred-type.metadata=#lib::X] dynamic boxedNullableX, [@vm.inferred-type.metadata=#lib::X] dynamic boxedX) → void {
self::use(unboxedInt);
self::use(unboxedDouble);
self::use(boxedNullableInt);
@@ -66,30 +66,30 @@
self::use(boxedNullableX);
self::use(boxedX);
}
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] [@vm.unboxing-info.metadata=(b)->i] method returnUnboxedSmi([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] [@vm.unboxing-info.metadata=(b)->i] method returnUnboxedSmi([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X? ignored) → dynamic
return 2;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=(b)->i] method returnUnboxedInt([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=(b)->i] method returnUnboxedInt([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X? ignored) → dynamic
return [@vm.inferred-type.metadata=int] self::mint;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] [@vm.unboxing-info.metadata=(b)->d] method returnUnboxedDouble([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] [@vm.unboxing-info.metadata=(b)->d] method returnUnboxedDouble([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X? ignored) → dynamic
return 2.2;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10] method returnBoxedNullableInt([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10] method returnBoxedNullableInt([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X? ignored) → dynamic
return 2;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] method returnBoxedNullableDouble([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] method returnBoxedNullableDouble([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X? ignored) → dynamic
return 2.2;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14] method returnBoxedIntOrDouble([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14] method returnBoxedIntOrDouble([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X? ignored) → dynamic
return 2.2;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:15,getterSelectorId:16] method returnBoxedNullableIntOrDouble([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:15,getterSelectorId:16] method returnBoxedNullableIntOrDouble([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X? ignored) → dynamic
return 2;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:17,getterSelectorId:18] method returnBoxedNullableX([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:17,getterSelectorId:18] method returnBoxedNullableX([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X? ignored) → dynamic
return new self::X::•();
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:19,getterSelectorId:20] method returnBoxedX([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:19,getterSelectorId:20] method returnBoxedX([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::X? ignored) → dynamic
return new self::X::•();
}
class SubImpl3 extends self::BaseImpl2 implements self::Interface {
- synthetic constructor •() → self::SubImpl3*
+ synthetic constructor •() → self::SubImpl3
: super self::BaseImpl2::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method takePositional(core::int* unboxedSmi, dynamic unboxedInt, dynamic unboxedDouble, dynamic boxedNullableInt, dynamic boxedNullableDouble, dynamic boxedNonNullableIntOrDouble, dynamic boxedNullableIntOrDouble, dynamic boxedNullableX, dynamic boxedX) → void {
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method takePositional(core::int? unboxedSmi, dynamic unboxedInt, dynamic unboxedDouble, dynamic boxedNullableInt, dynamic boxedNullableDouble, dynamic boxedNonNullableIntOrDouble, dynamic boxedNullableIntOrDouble, dynamic boxedNullableX, dynamic boxedX) → void {
self::use(unboxedInt);
self::use(unboxedDouble);
self::use(boxedNullableInt);
@@ -99,85 +99,85 @@
self::use(boxedNullableX);
self::use(boxedX);
}
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] [@vm.unboxing-info.metadata=(b)->i] method returnUnboxedSmi(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] [@vm.unboxing-info.metadata=(b)->i] method returnUnboxedSmi(self::X? ignored) → dynamic
return 3;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=(b)->i] method returnUnboxedInt(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] [@vm.unboxing-info.metadata=(b)->i] method returnUnboxedInt(self::X? ignored) → dynamic
return [@vm.inferred-type.metadata=int] self::mint;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] [@vm.unboxing-info.metadata=(b)->d] method returnUnboxedDouble(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] [@vm.unboxing-info.metadata=(b)->d] method returnUnboxedDouble(self::X? ignored) → dynamic
return 3.3;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:9,getterSelectorId:10] method returnBoxedNullableInt(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:9,getterSelectorId:10] method returnBoxedNullableInt(self::X? ignored) → dynamic
return [@vm.inferred-type.metadata=int] self::mint;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] method returnBoxedNullableDouble(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] method returnBoxedNullableDouble(self::X? ignored) → dynamic
return 3.3;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:13,getterSelectorId:14] method returnBoxedIntOrDouble(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:13,getterSelectorId:14] method returnBoxedIntOrDouble(self::X? ignored) → dynamic
return 3.3;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:15,getterSelectorId:16] method returnBoxedNullableIntOrDouble(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:15,getterSelectorId:16] method returnBoxedNullableIntOrDouble(self::X? ignored) → dynamic
return 3.3;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:17,getterSelectorId:18] method returnBoxedNullableX(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:17,getterSelectorId:18] method returnBoxedNullableX(self::X? ignored) → dynamic
return new self::X::•();
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:19,getterSelectorId:20] method returnBoxedX(self::X* ignored) → dynamic
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,methodOrSetterSelectorId:19,getterSelectorId:20] method returnBoxedX(self::X? ignored) → dynamic
return new self::X::•();
}
static field dynamic usedObject;
-[@vm.unboxing-info.metadata=()->i]static get mint() → core::int*
+[@vm.unboxing-info.metadata=()->i]static get mint() → core::int
return -6144092014192636707;
static method use(dynamic object) → void {
self::usedObject == null ?{dynamic} self::usedObject = object : null;
}
static method main() → dynamic {
- final core::List<core::Object*>* values = [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::Object*>] core::_GrowableList::_literal3<core::Object*>(new self::Impl1::•(), new self::BaseImpl2::•(), new self::SubImpl3::•());
- final self::Impl1* a = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int?] core::int::parse("0")){(core::int*) →* core::Object*} as self::Impl1*;
- final self::BaseImpl2* b = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int?] core::int::parse("1")){(core::int*) →* core::Object*} as self::BaseImpl2*;
- final self::SubImpl3* c = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int?] core::int::parse("2")){(core::int*) →* core::Object*} as self::SubImpl3*;
- final self::Interface* d = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int?] core::int::parse("2")){(core::int*) →* core::Object*} as self::Interface*;
- [@vm.direct-call.metadata=#lib::Impl1.takePositional??] [@vm.inferred-type.metadata=!? (skip check)] a.{self::Impl1::takePositional}(1, 1, 1.1, null, null, 1, null, null, new self::X::•()){(core::int*, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) →* void};
- b.{self::BaseImpl2::takePositional}(2, 2, 2.2, 2, 2.2, 2.2, 2, new self::X::•(), new self::X::•()){(core::int*, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) →* void};
- [@vm.direct-call.metadata=#lib::SubImpl3.takePositional??] [@vm.inferred-type.metadata=!? (skip check)] c.{self::SubImpl3::takePositional}(3, [@vm.inferred-type.metadata=int] self::mint, 3.3, [@vm.inferred-type.metadata=int] self::mint, 3.3, 3.3, 3.3, new self::X::•(), new self::X::•()){(core::int*, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) →* void};
- d.{self::Interface::takePositional}(3, [@vm.inferred-type.metadata=int] self::mint, 3.3, [@vm.inferred-type.metadata=int] self::mint, 3.3, 3.3, 3.3, new self::X::•(), new self::X::•()){(core::int*, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) →* void};
- self::use([@vm.direct-call.metadata=#lib::Impl1.returnUnboxedSmi] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 1)] a.{self::Impl1::returnUnboxedSmi}(null){(self::X*) →* dynamic});
- self::use([@vm.direct-call.metadata=#lib::Impl1.returnUnboxedInt] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 1)] a.{self::Impl1::returnUnboxedInt}(null){(self::X*) →* dynamic});
- self::use([@vm.direct-call.metadata=#lib::Impl1.returnUnboxedDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 1.1)] a.{self::Impl1::returnUnboxedDouble}(null){(self::X*) →* dynamic});
- self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableInt] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableInt}(null){(self::X*) →* dynamic});
- self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableDouble] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableDouble}(null){(self::X*) →* dynamic});
- self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedIntOrDouble] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 1)] a.{self::Impl1::returnBoxedIntOrDouble}(null){(self::X*) →* dynamic});
- self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableIntOrDouble] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableIntOrDouble}(null){(self::X*) →* dynamic});
- self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableX] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableX}(null){(self::X*) →* dynamic});
- self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedX] [@vm.inferred-type.metadata=#lib::X (skip check)] a.{self::Impl1::returnBoxedX}(null){(self::X*) →* dynamic});
- self::use([@vm.inferred-type.metadata=dart.core::_Smi] b.{self::BaseImpl2::returnUnboxedSmi}(null){(self::X*) →* dynamic});
- self::use([@vm.inferred-type.metadata=int] b.{self::BaseImpl2::returnUnboxedInt}(null){(self::X*) →* dynamic});
- self::use([@vm.inferred-type.metadata=dart.core::_Double] b.{self::BaseImpl2::returnUnboxedDouble}(null){(self::X*) →* dynamic});
- self::use([@vm.inferred-type.metadata=int] b.{self::BaseImpl2::returnBoxedNullableInt}(null){(self::X*) →* dynamic});
- self::use([@vm.inferred-type.metadata=dart.core::_Double] b.{self::BaseImpl2::returnBoxedNullableDouble}(null){(self::X*) →* dynamic});
- self::use([@vm.inferred-type.metadata=dart.core::_Double] b.{self::BaseImpl2::returnBoxedIntOrDouble}(null){(self::X*) →* dynamic});
- self::use([@vm.inferred-type.metadata=!] b.{self::BaseImpl2::returnBoxedNullableIntOrDouble}(null){(self::X*) →* dynamic});
- self::use([@vm.inferred-type.metadata=#lib::X] b.{self::BaseImpl2::returnBoxedNullableX}(null){(self::X*) →* dynamic});
- self::use([@vm.inferred-type.metadata=#lib::X] b.{self::BaseImpl2::returnBoxedX}(null){(self::X*) →* dynamic});
- self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnUnboxedSmi] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 3)] c.{self::SubImpl3::returnUnboxedSmi}(null){(self::X*) →* dynamic});
- self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnUnboxedInt] [@vm.inferred-type.metadata=int (skip check)] c.{self::SubImpl3::returnUnboxedInt}(null){(self::X*) →* dynamic});
- self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnUnboxedDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnUnboxedDouble}(null){(self::X*) →* dynamic});
- self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableInt] [@vm.inferred-type.metadata=int (skip check)] c.{self::SubImpl3::returnBoxedNullableInt}(null){(self::X*) →* dynamic});
- self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnBoxedNullableDouble}(null){(self::X*) →* dynamic});
- self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedIntOrDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnBoxedIntOrDouble}(null){(self::X*) →* dynamic});
- self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableIntOrDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnBoxedNullableIntOrDouble}(null){(self::X*) →* dynamic});
- self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableX] [@vm.inferred-type.metadata=#lib::X (skip check)] c.{self::SubImpl3::returnBoxedNullableX}(null){(self::X*) →* dynamic});
- self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedX] [@vm.inferred-type.metadata=#lib::X (skip check)] c.{self::SubImpl3::returnBoxedX}(null){(self::X*) →* dynamic});
- self::use([@vm.inferred-type.metadata=dart.core::_Smi] d.{self::Interface::returnUnboxedSmi}(null){(self::X*) →* dynamic});
- self::use([@vm.inferred-type.metadata=int] d.{self::Interface::returnUnboxedInt}(null){(self::X*) →* dynamic});
- self::use([@vm.inferred-type.metadata=dart.core::_Double] d.{self::Interface::returnUnboxedDouble}(null){(self::X*) →* dynamic});
- self::use([@vm.inferred-type.metadata=int?] d.{self::Interface::returnBoxedNullableInt}(null){(self::X*) →* dynamic});
- self::use([@vm.inferred-type.metadata=dart.core::_Double?] d.{self::Interface::returnBoxedNullableDouble}(null){(self::X*) →* dynamic});
- self::use([@vm.inferred-type.metadata=!] d.{self::Interface::returnBoxedIntOrDouble}(null){(self::X*) →* dynamic});
- self::use([@vm.inferred-type.metadata=dart.core::_Double?] d.{self::Interface::returnBoxedNullableIntOrDouble}(null){(self::X*) →* dynamic});
- self::use([@vm.inferred-type.metadata=#lib::X?] d.{self::Interface::returnBoxedNullableX}(null){(self::X*) →* dynamic});
- self::use([@vm.inferred-type.metadata=#lib::X] d.{self::Interface::returnBoxedX}(null){(self::X*) →* dynamic});
- self::use(d.{self::Interface::takePositional}{(core::int*, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) →* void});
- self::use(d.{self::Interface::returnUnboxedSmi}{(self::X*) →* dynamic});
- self::use(d.{self::Interface::returnUnboxedInt}{(self::X*) →* dynamic});
- self::use(d.{self::Interface::returnUnboxedDouble}{(self::X*) →* dynamic});
- self::use(d.{self::Interface::returnBoxedNullableInt}{(self::X*) →* dynamic});
- self::use(d.{self::Interface::returnBoxedNullableDouble}{(self::X*) →* dynamic});
- self::use(d.{self::Interface::returnBoxedIntOrDouble}{(self::X*) →* dynamic});
- self::use(d.{self::Interface::returnBoxedNullableIntOrDouble}{(self::X*) →* dynamic});
- self::use(d.{self::Interface::returnBoxedNullableX}{(self::X*) →* dynamic});
- self::use(d.{self::Interface::returnBoxedX}{(self::X*) →* dynamic});
+ final core::List<core::Object> values = [@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::Object>] core::_GrowableList::_literal3<core::Object>(new self::Impl1::•(), new self::BaseImpl2::•(), new self::SubImpl3::•());
+ final self::Impl1 a = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int?] core::int::parse("0")){(core::int) → core::Object} as{ForNonNullableByDefault} self::Impl1;
+ final self::BaseImpl2 b = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int?] core::int::parse("1")){(core::int) → core::Object} as{ForNonNullableByDefault} self::BaseImpl2;
+ final self::SubImpl3 c = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int?] core::int::parse("2")){(core::int) → core::Object} as{ForNonNullableByDefault} self::SubImpl3;
+ final self::Interface d = [@vm.direct-call.metadata=dart.core::_GrowableList.[]] [@vm.inferred-type.metadata=!? (skip check)] values.{core::List::[]}([@vm.inferred-type.metadata=int?] core::int::parse("2")){(core::int) → core::Object} as{ForNonNullableByDefault} self::Interface;
+ [@vm.direct-call.metadata=#lib::Impl1.takePositional??] [@vm.inferred-type.metadata=!? (skip check)] a.{self::Impl1::takePositional}(1, 1, 1.1, null, null, 1, null, null, new self::X::•()){(core::int?, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) → void};
+ b.{self::BaseImpl2::takePositional}(2, 2, 2.2, 2, 2.2, 2.2, 2, new self::X::•(), new self::X::•()){(core::int?, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) → void};
+ [@vm.direct-call.metadata=#lib::SubImpl3.takePositional??] [@vm.inferred-type.metadata=!? (skip check)] c.{self::SubImpl3::takePositional}(3, [@vm.inferred-type.metadata=int] self::mint, 3.3, [@vm.inferred-type.metadata=int] self::mint, 3.3, 3.3, 3.3, new self::X::•(), new self::X::•()){(core::int?, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) → void};
+ d.{self::Interface::takePositional}(3, [@vm.inferred-type.metadata=int] self::mint, 3.3, [@vm.inferred-type.metadata=int] self::mint, 3.3, 3.3, 3.3, new self::X::•(), new self::X::•()){(core::int?, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) → void};
+ self::use([@vm.direct-call.metadata=#lib::Impl1.returnUnboxedSmi] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 1)] a.{self::Impl1::returnUnboxedSmi}(null){(self::X?) → dynamic});
+ self::use([@vm.direct-call.metadata=#lib::Impl1.returnUnboxedInt] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 1)] a.{self::Impl1::returnUnboxedInt}(null){(self::X?) → dynamic});
+ self::use([@vm.direct-call.metadata=#lib::Impl1.returnUnboxedDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 1.1)] a.{self::Impl1::returnUnboxedDouble}(null){(self::X?) → dynamic});
+ self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableInt] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableInt}(null){(self::X?) → dynamic});
+ self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableDouble] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableDouble}(null){(self::X?) → dynamic});
+ self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedIntOrDouble] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 1)] a.{self::Impl1::returnBoxedIntOrDouble}(null){(self::X?) → dynamic});
+ self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableIntOrDouble] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableIntOrDouble}(null){(self::X?) → dynamic});
+ self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedNullableX] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] a.{self::Impl1::returnBoxedNullableX}(null){(self::X?) → dynamic});
+ self::use([@vm.direct-call.metadata=#lib::Impl1.returnBoxedX] [@vm.inferred-type.metadata=#lib::X (skip check)] a.{self::Impl1::returnBoxedX}(null){(self::X?) → dynamic});
+ self::use([@vm.inferred-type.metadata=dart.core::_Smi] b.{self::BaseImpl2::returnUnboxedSmi}(null){(self::X?) → dynamic});
+ self::use([@vm.inferred-type.metadata=int] b.{self::BaseImpl2::returnUnboxedInt}(null){(self::X?) → dynamic});
+ self::use([@vm.inferred-type.metadata=dart.core::_Double] b.{self::BaseImpl2::returnUnboxedDouble}(null){(self::X?) → dynamic});
+ self::use([@vm.inferred-type.metadata=int] b.{self::BaseImpl2::returnBoxedNullableInt}(null){(self::X?) → dynamic});
+ self::use([@vm.inferred-type.metadata=dart.core::_Double] b.{self::BaseImpl2::returnBoxedNullableDouble}(null){(self::X?) → dynamic});
+ self::use([@vm.inferred-type.metadata=dart.core::_Double] b.{self::BaseImpl2::returnBoxedIntOrDouble}(null){(self::X?) → dynamic});
+ self::use([@vm.inferred-type.metadata=!] b.{self::BaseImpl2::returnBoxedNullableIntOrDouble}(null){(self::X?) → dynamic});
+ self::use([@vm.inferred-type.metadata=#lib::X] b.{self::BaseImpl2::returnBoxedNullableX}(null){(self::X?) → dynamic});
+ self::use([@vm.inferred-type.metadata=#lib::X] b.{self::BaseImpl2::returnBoxedX}(null){(self::X?) → dynamic});
+ self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnUnboxedSmi] [@vm.inferred-type.metadata=dart.core::_Smi (skip check) (value: 3)] c.{self::SubImpl3::returnUnboxedSmi}(null){(self::X?) → dynamic});
+ self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnUnboxedInt] [@vm.inferred-type.metadata=int (skip check)] c.{self::SubImpl3::returnUnboxedInt}(null){(self::X?) → dynamic});
+ self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnUnboxedDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnUnboxedDouble}(null){(self::X?) → dynamic});
+ self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableInt] [@vm.inferred-type.metadata=int (skip check)] c.{self::SubImpl3::returnBoxedNullableInt}(null){(self::X?) → dynamic});
+ self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnBoxedNullableDouble}(null){(self::X?) → dynamic});
+ self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedIntOrDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnBoxedIntOrDouble}(null){(self::X?) → dynamic});
+ self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableIntOrDouble] [@vm.inferred-type.metadata=dart.core::_Double (skip check) (value: 3.3)] c.{self::SubImpl3::returnBoxedNullableIntOrDouble}(null){(self::X?) → dynamic});
+ self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedNullableX] [@vm.inferred-type.metadata=#lib::X (skip check)] c.{self::SubImpl3::returnBoxedNullableX}(null){(self::X?) → dynamic});
+ self::use([@vm.direct-call.metadata=#lib::SubImpl3.returnBoxedX] [@vm.inferred-type.metadata=#lib::X (skip check)] c.{self::SubImpl3::returnBoxedX}(null){(self::X?) → dynamic});
+ self::use([@vm.inferred-type.metadata=dart.core::_Smi] d.{self::Interface::returnUnboxedSmi}(null){(self::X?) → dynamic});
+ self::use([@vm.inferred-type.metadata=int] d.{self::Interface::returnUnboxedInt}(null){(self::X?) → dynamic});
+ self::use([@vm.inferred-type.metadata=dart.core::_Double] d.{self::Interface::returnUnboxedDouble}(null){(self::X?) → dynamic});
+ self::use([@vm.inferred-type.metadata=int?] d.{self::Interface::returnBoxedNullableInt}(null){(self::X?) → dynamic});
+ self::use([@vm.inferred-type.metadata=dart.core::_Double?] d.{self::Interface::returnBoxedNullableDouble}(null){(self::X?) → dynamic});
+ self::use([@vm.inferred-type.metadata=!] d.{self::Interface::returnBoxedIntOrDouble}(null){(self::X?) → dynamic});
+ self::use([@vm.inferred-type.metadata=dart.core::_Double?] d.{self::Interface::returnBoxedNullableIntOrDouble}(null){(self::X?) → dynamic});
+ self::use([@vm.inferred-type.metadata=#lib::X?] d.{self::Interface::returnBoxedNullableX}(null){(self::X?) → dynamic});
+ self::use([@vm.inferred-type.metadata=#lib::X] d.{self::Interface::returnBoxedX}(null){(self::X?) → dynamic});
+ self::use(d.{self::Interface::takePositional}{(core::int?, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic, dynamic) → void});
+ self::use(d.{self::Interface::returnUnboxedSmi}{(self::X?) → dynamic});
+ self::use(d.{self::Interface::returnUnboxedInt}{(self::X?) → dynamic});
+ self::use(d.{self::Interface::returnUnboxedDouble}{(self::X?) → dynamic});
+ self::use(d.{self::Interface::returnBoxedNullableInt}{(self::X?) → dynamic});
+ self::use(d.{self::Interface::returnBoxedNullableDouble}{(self::X?) → dynamic});
+ self::use(d.{self::Interface::returnBoxedIntOrDouble}{(self::X?) → dynamic});
+ self::use(d.{self::Interface::returnBoxedNullableIntOrDouble}{(self::X?) → dynamic});
+ self::use(d.{self::Interface::returnBoxedNullableX}{(self::X?) → dynamic});
+ self::use(d.{self::Interface::returnBoxedX}{(self::X?) → dynamic});
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method.dart b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method.dart
index 5151f2e..3522029 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method.dart
@@ -15,7 +15,7 @@
class X {}
void takePositional(
- int unboxedSmi,
+ int? unboxedSmi,
dynamic unboxedInt,
dynamic unboxedDouble,
dynamic boxedNullableInt,
@@ -35,7 +35,7 @@
}
void takeOptional(
- [int unboxedSmi,
+ [int? unboxedSmi,
dynamic unboxedInt,
dynamic unboxedDouble,
dynamic boxedNullableInt,
@@ -55,7 +55,7 @@
}
void takeNamed(
- {int unboxedSmi,
+ {int? unboxedSmi,
dynamic unboxedInt,
dynamic unboxedDouble,
dynamic boxedNullableInt,
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method.dart.expect
index 2577681..3615da2 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method.dart.expect
@@ -1,19 +1,19 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
class X extends core::Object {
- synthetic constructor •() → self::X*
+ synthetic constructor •() → self::X
: super core::Object::•()
;
}
-[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool* kTrue = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object*) →* core::bool*} 1 ?{core::bool*} true : false;
-[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool* kFalse = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object*) →* core::bool*} 2 ?{core::bool*} true : false;
+[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool kTrue = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object) → core::bool} 1 ?{core::bool} true : false;
+[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool kFalse = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object) → core::bool} 2 ?{core::bool} true : false;
static field dynamic usedObject;
-[@vm.unboxing-info.metadata=()->i]static get mint() → core::int*
+[@vm.unboxing-info.metadata=()->i]static get mint() → core::int
return -6144092014192636707;
-[@vm.unboxing-info.metadata=()->i]static get smiOrMint() → core::int*
- return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : [@vm.inferred-type.metadata=int] self::mint;
+[@vm.unboxing-info.metadata=()->i]static get smiOrMint() → core::int
+ return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} 1 : [@vm.inferred-type.metadata=int] self::mint;
static method use(dynamic object) → void {
self::usedObject == null ?{dynamic} self::usedObject = object : null;
}
@@ -48,33 +48,33 @@
self::use(boxedX);
}
[@vm.unboxing-info.metadata=()->i]static method returnUnboxedSmi() → dynamic
- return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2;
+ return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} 1 : 2;
[@vm.unboxing-info.metadata=()->i]static method returnUnboxedInt() → dynamic
- return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : 2;
+ return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} [@vm.inferred-type.metadata=int] self::smiOrMint : 2;
[@vm.unboxing-info.metadata=()->d]static method returnUnboxedDouble() → dynamic
- return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : 2.2;
+ return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double} 1.1 : 2.2;
static method returnBoxedNullableInt() → dynamic
- return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : null;
+ return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int?} [@vm.inferred-type.metadata=int] self::smiOrMint : null;
static method returnBoxedNullableDouble() → dynamic
- return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : null;
+ return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double?} 1.1 : null;
static method returnBoxedIntOrDouble() → dynamic
- return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1;
+ return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1;
static method returnBoxedNullableIntOrDouble() → dynamic
- return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null;
+ return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num?} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null;
static method returnBoxedNullableX() → dynamic
- return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X*} new self::X::•() : null;
+ return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X?} new self::X::•() : null;
static method returnBoxedX() → dynamic
return new self::X::•();
@#C3
-static method returnBoxedSmiFromEntryPoint() → core::int*
- return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2;
+static method returnBoxedSmiFromEntryPoint() → core::int
+ return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} 1 : 2;
@#C3
-static method takeBoxedSmiFromEntryPoint(core::int* value) → void {}
+static method takeBoxedSmiFromEntryPoint(core::int value) → void {}
static method main() → dynamic {
- let final core::int* #t1 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2 in let final core::int* #t2 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : 2 in let final core::double* #t3 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : 2.2 in let final core::int* #t4 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : null in let final core::double* #t5 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : null in let final core::num* #t6 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 in let final core::num* #t7 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null in let final self::X* #t8 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X*} new self::X::•() : null in let final self::X* #t9 = new self::X::•() in self::takePositional(#t2, #t3, #t4, #t5, #t6, #t7, #t8, #t9);
- let final core::int* #t10 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2 in let final core::int* #t11 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : 2 in let final core::double* #t12 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : 2.2 in let final core::int* #t13 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : null in let final core::double* #t14 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : null in let final core::num* #t15 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 in let final core::num* #t16 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null in let final self::X* #t17 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X*} new self::X::•() : null in let final self::X* #t18 = new self::X::•() in self::takeOptional(#t11, #t12, #t13, #t14, #t15, #t16, #t17, #t18);
- let final core::int* #t19 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2 in let final core::int* #t20 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : 2 in let final core::double* #t21 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : 2.2 in let final core::int* #t22 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : null in let final core::double* #t23 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : null in let final core::num* #t24 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 in let final core::num* #t25 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null in let final self::X* #t26 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X*} new self::X::•() : null in let final self::X* #t27 = new self::X::•() in self::takeNamed(#t24, #t23, #t22, #t25, #t26, #t27, #t21, #t20);
- self::takeBoxedSmiFromEntryPoint([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2);
+ let final core::int #t1 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} 1 : 2 in let final core::int #t2 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} [@vm.inferred-type.metadata=int] self::smiOrMint : 2 in let final core::double #t3 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double} 1.1 : 2.2 in let final core::int? #t4 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int?} [@vm.inferred-type.metadata=int] self::smiOrMint : null in let final core::double? #t5 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double?} 1.1 : null in let final core::num #t6 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 in let final core::num? #t7 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num?} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null in let final self::X? #t8 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X?} new self::X::•() : null in let final self::X #t9 = new self::X::•() in self::takePositional(#t2, #t3, #t4, #t5, #t6, #t7, #t8, #t9);
+ let final core::int #t10 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} 1 : 2 in let final core::int #t11 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} [@vm.inferred-type.metadata=int] self::smiOrMint : 2 in let final core::double #t12 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double} 1.1 : 2.2 in let final core::int? #t13 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int?} [@vm.inferred-type.metadata=int] self::smiOrMint : null in let final core::double? #t14 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double?} 1.1 : null in let final core::num #t15 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 in let final core::num? #t16 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num?} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null in let final self::X? #t17 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X?} new self::X::•() : null in let final self::X #t18 = new self::X::•() in self::takeOptional(#t11, #t12, #t13, #t14, #t15, #t16, #t17, #t18);
+ let final core::int #t19 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} 1 : 2 in let final core::int #t20 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} [@vm.inferred-type.metadata=int] self::smiOrMint : 2 in let final core::double #t21 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double} 1.1 : 2.2 in let final core::int? #t22 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int?} [@vm.inferred-type.metadata=int] self::smiOrMint : null in let final core::double? #t23 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double?} 1.1 : null in let final core::num #t24 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 in let final core::num? #t25 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num?} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null in let final self::X? #t26 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X?} new self::X::•() : null in let final self::X #t27 = new self::X::•() in self::takeNamed(#t24, #t23, #t22, #t25, #t26, #t27, #t21, #t20);
+ self::takeBoxedSmiFromEntryPoint([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} 1 : 2);
self::use([@vm.inferred-type.metadata=dart.core::_Smi] self::returnUnboxedSmi());
self::use([@vm.inferred-type.metadata=int] self::returnUnboxedInt());
self::use([@vm.inferred-type.metadata=dart.core::_Double] self::returnUnboxedDouble());
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method_tearoff.dart b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method_tearoff.dart
index f20e0ce..21788ee 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method_tearoff.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method_tearoff.dart
@@ -15,7 +15,7 @@
class X {}
void takePositional(
- int unboxedSmi,
+ int? unboxedSmi,
dynamic unboxedInt,
dynamic unboxedDouble,
dynamic boxedNullableInt,
@@ -35,7 +35,7 @@
}
void takeOptional(
- [int unboxedSmi,
+ [int? unboxedSmi,
dynamic unboxedInt,
dynamic unboxedDouble,
dynamic boxedNullableInt,
@@ -55,7 +55,7 @@
}
void takeNamed(
- {int unboxedSmi,
+ {int? unboxedSmi,
dynamic unboxedInt,
dynamic unboxedDouble,
dynamic boxedNullableInt,
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method_tearoff.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method_tearoff.dart.expect
index 8296cf3..3ab3d19 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method_tearoff.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method_tearoff.dart.expect
@@ -1,23 +1,23 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
class X extends core::Object {
- synthetic constructor •() → self::X*
+ synthetic constructor •() → self::X
: super core::Object::•()
;
}
-[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool* kTrue = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object*) →* core::bool*} 1 ?{core::bool*} true : false;
-[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool* kFalse = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object*) →* core::bool*} 2 ?{core::bool*} true : false;
+[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool kTrue = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object) → core::bool} 1 ?{core::bool} true : false;
+[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool kFalse = [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object) → core::bool} 2 ?{core::bool} true : false;
static field dynamic usedObject;
-[@vm.unboxing-info.metadata=()->i]static get mint() → core::int*
+[@vm.unboxing-info.metadata=()->i]static get mint() → core::int
return -6144092014192636707;
-[@vm.unboxing-info.metadata=()->i]static get smiOrMint() → core::int*
- return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : [@vm.inferred-type.metadata=int] self::mint;
+[@vm.unboxing-info.metadata=()->i]static get smiOrMint() → core::int
+ return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} 1 : [@vm.inferred-type.metadata=int] self::mint;
static method use(dynamic object) → void {
self::usedObject == null ?{dynamic} self::usedObject = object : null;
}
-static method takePositional(core::int* unboxedSmi, dynamic unboxedInt, dynamic unboxedDouble, dynamic boxedNullableInt, dynamic boxedNullableDouble, dynamic boxedIntOrDouble, dynamic boxedNullableIntOrDouble, dynamic boxedNullableX, dynamic boxedX) → void {
+static method takePositional(core::int? unboxedSmi, dynamic unboxedInt, dynamic unboxedDouble, dynamic boxedNullableInt, dynamic boxedNullableDouble, dynamic boxedIntOrDouble, dynamic boxedNullableIntOrDouble, dynamic boxedNullableX, dynamic boxedX) → void {
self::use(unboxedInt);
self::use(unboxedDouble);
self::use(boxedNullableInt);
@@ -27,7 +27,7 @@
self::use(boxedNullableX);
self::use(boxedX);
}
-static method takeOptional([core::int* unboxedSmi = #C1, dynamic unboxedInt = #C1, dynamic unboxedDouble = #C1, dynamic boxedNullableInt = #C1, dynamic boxedNullableDouble = #C1, dynamic boxedIntOrDouble = #C1, dynamic boxedNullableIntOrDouble = #C1, dynamic boxedNullableX = #C1, dynamic boxedX = #C1]) → void {
+static method takeOptional([core::int? unboxedSmi = #C1, dynamic unboxedInt = #C1, dynamic unboxedDouble = #C1, dynamic boxedNullableInt = #C1, dynamic boxedNullableDouble = #C1, dynamic boxedIntOrDouble = #C1, dynamic boxedNullableIntOrDouble = #C1, dynamic boxedNullableX = #C1, dynamic boxedX = #C1]) → void {
self::use(unboxedInt);
self::use(unboxedDouble);
self::use(boxedNullableInt);
@@ -37,7 +37,7 @@
self::use(boxedNullableX);
self::use(boxedX);
}
-static method takeNamed({core::int* unboxedSmi = #C1, dynamic unboxedInt = #C1, dynamic unboxedDouble = #C1, dynamic boxedNullableInt = #C1, dynamic boxedNullableDouble = #C1, dynamic boxedIntOrDouble = #C1, dynamic boxedNullableIntOrDouble = #C1, dynamic boxedNullableX = #C1, dynamic boxedX = #C1}) → void {
+static method takeNamed({core::int? unboxedSmi = #C1, dynamic unboxedInt = #C1, dynamic unboxedDouble = #C1, dynamic boxedNullableInt = #C1, dynamic boxedNullableDouble = #C1, dynamic boxedIntOrDouble = #C1, dynamic boxedNullableIntOrDouble = #C1, dynamic boxedNullableX = #C1, dynamic boxedX = #C1}) → void {
self::use(unboxedInt);
self::use(unboxedDouble);
self::use(boxedNullableInt);
@@ -48,27 +48,27 @@
self::use(boxedX);
}
[@vm.unboxing-info.metadata=()->i]static method returnUnboxedSmi() → dynamic
- return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2;
+ return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} 1 : 2;
[@vm.unboxing-info.metadata=()->i]static method returnUnboxedInt() → dynamic
- return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : 2;
+ return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} [@vm.inferred-type.metadata=int] self::smiOrMint : 2;
[@vm.unboxing-info.metadata=()->d]static method returnUnboxedDouble() → dynamic
- return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : 2.2;
+ return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double} 1.1 : 2.2;
static method returnBoxedNullableInt() → dynamic
- return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : null;
+ return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int?} [@vm.inferred-type.metadata=int] self::smiOrMint : null;
static method returnBoxedNullableDouble() → dynamic
- return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : null;
+ return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double?} 1.1 : null;
static method returnBoxedIntOrDouble() → dynamic
- return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1;
+ return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1;
static method returnBoxedNullableIntOrDouble() → dynamic
- return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null;
+ return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num?} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null;
static method returnBoxedNullableX() → dynamic
- return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X*} new self::X::•() : null;
+ return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X?} new self::X::•() : null;
static method returnBoxedX() → dynamic
return new self::X::•();
static method main() → dynamic {
- self::takePositional([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : 2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : 2.2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X*} new self::X::•() : null, new self::X::•());
- self::takeOptional([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : 2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : 2.2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X*} new self::X::•() : null, new self::X::•());
- self::takeNamed(unboxedSmi: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2, unboxedInt: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : 2, unboxedDouble: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : 2.2, boxedNullableInt: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : null, boxedNullableDouble: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : null, boxedIntOrDouble: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1, boxedNullableIntOrDouble: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null, boxedNullableX: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X*} new self::X::•() : null, boxedX: new self::X::•());
+ self::takePositional([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} 1 : 2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} [@vm.inferred-type.metadata=int] self::smiOrMint : 2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double} 1.1 : 2.2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int?} [@vm.inferred-type.metadata=int] self::smiOrMint : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double?} 1.1 : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num?} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X?} new self::X::•() : null, new self::X::•());
+ self::takeOptional([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} 1 : 2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} [@vm.inferred-type.metadata=int] self::smiOrMint : 2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double} 1.1 : 2.2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int?} [@vm.inferred-type.metadata=int] self::smiOrMint : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double?} 1.1 : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num?} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X?} new self::X::•() : null, new self::X::•());
+ self::takeNamed(unboxedSmi: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} 1 : 2, unboxedInt: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int} [@vm.inferred-type.metadata=int] self::smiOrMint : 2, unboxedDouble: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double} 1.1 : 2.2, boxedNullableInt: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int?} [@vm.inferred-type.metadata=int] self::smiOrMint : null, boxedNullableDouble: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double?} 1.1 : null, boxedIntOrDouble: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1, boxedNullableIntOrDouble: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num?} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null, boxedNullableX: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X?} new self::X::•() : null, boxedX: new self::X::•());
self::use([@vm.inferred-type.metadata=dart.core::_Smi] self::returnUnboxedSmi());
self::use([@vm.inferred-type.metadata=int] self::returnUnboxedInt());
self::use([@vm.inferred-type.metadata=dart.core::_Double] self::returnUnboxedDouble());
@@ -93,16 +93,16 @@
}
constants {
#C1 = null
- #C2 = tearoff self::takePositional
- #C3 = tearoff self::takeOptional
- #C4 = tearoff self::takeNamed
- #C5 = tearoff self::returnUnboxedSmi
- #C6 = tearoff self::returnUnboxedInt
- #C7 = tearoff self::returnUnboxedDouble
- #C8 = tearoff self::returnBoxedNullableInt
- #C9 = tearoff self::returnBoxedNullableDouble
- #C10 = tearoff self::returnBoxedIntOrDouble
- #C11 = tearoff self::returnBoxedNullableIntOrDouble
- #C12 = tearoff self::returnBoxedNullableX
- #C13 = tearoff self::returnBoxedX
+ #C2 = static-tearoff self::takePositional
+ #C3 = static-tearoff self::takeOptional
+ #C4 = static-tearoff self::takeNamed
+ #C5 = static-tearoff self::returnUnboxedSmi
+ #C6 = static-tearoff self::returnUnboxedInt
+ #C7 = static-tearoff self::returnUnboxedDouble
+ #C8 = static-tearoff self::returnBoxedNullableInt
+ #C9 = static-tearoff self::returnBoxedNullableDouble
+ #C10 = static-tearoff self::returnBoxedIntOrDouble
+ #C11 = static-tearoff self::returnBoxedNullableIntOrDouble
+ #C12 = static-tearoff self::returnBoxedNullableX
+ #C13 = static-tearoff self::returnBoxedX
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unfinished_static_field_init.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/unfinished_static_field_init.dart.expect
index 74d3bb3..ed5a63a 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unfinished_static_field_init.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unfinished_static_field_init.dart.expect
@@ -1,9 +1,9 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
class A extends core::Object {
- synthetic constructor •() → self::A*
+ synthetic constructor •() → self::A
: super core::Object::•()
;
}
@@ -13,7 +13,7 @@
return new self::A::•();
static method bad() → dynamic
return throw "No return!";
-static method main(core::List<core::String*>* args) → dynamic {
+static method main(core::List<core::String> args) → dynamic {
core::print([@vm.inferred-type.metadata=#lib::A?] self::static_field_good);
core::print([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::static_field_bad);
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unreachable.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/unreachable.dart.expect
index 0ed46d3..6cd1f40 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unreachable.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unreachable.dart.expect
@@ -1,22 +1,18 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
abstract class I extends core::Object {
}
-abstract class A extends core::Object implements self::I {
-}
class B extends core::Object implements self::I {
- synthetic constructor •() → self::B*
+ synthetic constructor •() → self::B
: super core::Object::•()
;
}
-[@vm.inferred-type.metadata=#lib::B?]static field self::I* ii = new self::B::•();
-static method bar([@vm.inferred-type.metadata=#lib::B?] self::I* i) → void {
- if(i is self::A*) {
- throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
- }
+[@vm.inferred-type.metadata=#lib::B?]static field self::I ii = new self::B::•();
+static method bar([@vm.inferred-type.metadata=#lib::B?] self::I i) → void {
+ ;
}
-static method main(core::List<core::String*>* args) → dynamic {
+static method main(core::List<core::String> args) → dynamic {
self::bar([@vm.inferred-type.metadata=#lib::B?] self::ii);
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field.dart b/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field.dart
index 6abe2d5..d7b90d8 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field.dart
@@ -11,7 +11,7 @@
}
}
-var field = A();
+A? field = A();
class B {
B() {
@@ -20,7 +20,7 @@
}
class C {
- var instanceField = new B();
+ B? instanceField = new B();
}
void main() {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field.dart.expect
index cc689dc..e544ddf 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field.dart.expect
@@ -1,18 +1,18 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
class B extends core::Object {
- constructor •() → self::B*
+ constructor •() → self::B
: super core::Object::•() {
core::print("B");
}
}
class C extends core::Object {
- synthetic constructor •() → self::C*
+ synthetic constructor •() → self::C
: dynamic #t1 = new self::B::•(), super core::Object::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1] set instanceField(self::B* value) → void;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1] set /*isLegacy*/ instanceField(self::B? value) → void;
}
static method main() → void {
null;
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field2.dart b/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field2.dart
index af6a9b8..45dd11b 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field2.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field2.dart
@@ -31,12 +31,12 @@
class C<T> {
// Should be replaced with setter.
- T bar;
+ T? bar;
}
class D implements C<int> {
// Should be replaced with setter.
- int bar;
+ int? bar;
}
class E {
@@ -59,7 +59,7 @@
class H {
// Should be replaced with setter.
- int unused6;
+ int? unused6;
}
class I extends H {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field2.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field2.dart.expect
index 6e40a3c..057cfe3 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field2.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field2.dart.expect
@@ -1,4 +1,4 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
import "package:expect/expect.dart" as exp;
@@ -6,45 +6,45 @@
import "package:expect/expect.dart";
class A extends core::Object {
- synthetic constructor •() → self::A*
+ synthetic constructor •() → self::A
: dynamic #t1 = [@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::foo(), super core::Object::•()
;
}
class B extends core::Object {
- constructor •() → self::B*
+ constructor •() → self::B
: dynamic #t2 = [@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::foo(), super core::Object::•()
;
}
-abstract class C<T extends core::Object* = dynamic> extends core::Object {
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1] abstract set bar(generic-covariant-impl self::C::T* value) → void;
+abstract class C<T extends core::Object? = dynamic> extends core::Object {
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1] abstract set /*isLegacy*/ bar(generic-covariant-impl self::C::T? value) → void;
}
-class D extends core::Object implements self::C<core::int*> {
- synthetic constructor •() → self::D*
+class D extends core::Object implements self::C<core::int> {
+ synthetic constructor •() → self::D
: super core::Object::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1] set bar(generic-covariant-impl core::int* value) → void;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1] set /*isLegacy*/ bar(generic-covariant-impl core::int? value) → void;
}
abstract class E extends core::Object {
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i] abstract get bar() → core::int*;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i] abstract get /*isLegacy*/ bar() → core::int;
}
class F extends core::Object implements self::E {
- synthetic constructor •() → self::F*
+ synthetic constructor •() → self::F
: super core::Object::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i] get bar() → core::int*
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:2] [@vm.unboxing-info.metadata=()->i] get bar() → core::int
return 42;
}
class G extends core::Object /*hasConstConstructor*/ {
-[@vm.inferred-type.metadata=dart.core::_Smi] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3] [@vm.unboxing-info.metadata=()->i] final field core::int* bazz;
+[@vm.inferred-type.metadata=dart.core::_Smi] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3] [@vm.unboxing-info.metadata=()->i] final field core::int bazz;
}
abstract class H extends core::Object {
- synthetic constructor •() → self::H*
+ synthetic constructor •() → self::H
: super core::Object::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4] set unused6(core::int* value) → void;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4] set /*isLegacy*/ unused6(core::int? value) → void;
}
class I extends self::H {
- synthetic constructor •() → self::I*
+ synthetic constructor •() → self::I
: super self::H::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] method foo() → dynamic {
@@ -55,14 +55,14 @@
static method main() → void {
new self::A::•();
new self::B::•();
- self::C<core::num*>* c = new self::D::•();
- exp::Expect::throws<dynamic>(() → Null {
- [@vm.call-site-attributes.metadata=receiverType:#lib::C<dart.core::num*>*] [@vm.direct-call.metadata=#lib::D.bar] c.{self::C::bar} = 3.14;
+ self::C<core::num> c = new self::D::•();
+ exp::Expect::throws<dynamic>(() → void {
+ [@vm.call-site-attributes.metadata=receiverType:#lib::C<dart.core::num>] [@vm.direct-call.metadata=#lib::D.bar] c.{self::C::bar} = 3.14;
});
- self::E* e = new self::F::•();
- let final core::int* #t3 = [@vm.direct-call.metadata=#lib::F.bar] [@vm.inferred-type.metadata=dart.core::_Smi (value: 42)] e.{self::E::bar}{core::int*} in exp::Expect::equals();
+ self::E e = new self::F::•();
+ let final core::int #t3 = [@vm.direct-call.metadata=#lib::F.bar] [@vm.inferred-type.metadata=dart.core::_Smi (value: 42)] e.{self::E::bar}{core::int} in exp::Expect::equals();
exp::Expect::isTrue(![@vm.inferred-type.metadata=dart.core::bool] core::identical(#C2, #C4));
- [@vm.direct-call.metadata=#lib::I.foo] [@vm.inferred-type.metadata=!? (skip check)] new self::I::•().{self::I::foo}(){() →* dynamic};
+ [@vm.direct-call.metadata=#lib::I.foo] [@vm.inferred-type.metadata=!? (skip check)] new self::I::•().{self::I::foo}(){() → dynamic};
5;
}
constants {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field3_nnbd.dart b/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field3_nnbd.dart
index ea59290..a777b1b 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field3_nnbd.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field3_nnbd.dart
@@ -3,9 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
// Test for tree shaking of write-only late fields.
-// This test requires non-nullable experiment.
-
-// @dart = 2.10
foo() {}
diff --git a/pkg/vm/testcases/transformations/unreachable_code_elimination/uce_testcases.dart b/pkg/vm/testcases/transformations/unreachable_code_elimination/uce_testcases.dart
index 6115eb3..33f4458 100644
--- a/pkg/vm/testcases/transformations/unreachable_code_elimination/uce_testcases.dart
+++ b/pkg/vm/testcases/transformations/unreachable_code_elimination/uce_testcases.dart
@@ -7,7 +7,7 @@
const bool constTrue2 = !constFalse;
const bool constFalse2 = const bool.fromEnvironment('test.define.notDefined');
-bool foo() => null;
+bool? foo() => null;
void testSimpleConditions() {
if (constTrue) {
@@ -25,10 +25,10 @@
}
void testAndConditions() {
- if (constTrue && foo()) {
+ if (constTrue && foo()!) {
print('1_yes');
}
- if (constFalse && foo()) {
+ if (constFalse && foo()!) {
print('2_no');
}
if (constTrue && constFalse) {
@@ -40,10 +40,10 @@
}
void testOrConditions() {
- if (constTrue || foo()) {
+ if (constTrue || foo()!) {
print('1_yes');
}
- if (constFalse || foo()) {
+ if (constFalse || foo()!) {
print('2_yes');
}
if (constFalse || constFalse2) {
@@ -61,54 +61,54 @@
if (!constFalse) {
print('2_yes');
}
- if (!(!(!constTrue && foo()) || foo())) {
+ if (!(!(!constTrue && foo()!) || foo()!)) {
print('3_no');
}
}
testConditionalExpressions() {
print(!constFalse && constTrue ? '1_yes' : '2_no');
- print(constFalse && foo() ? '3_no' : '4_yes ${foo()}');
+ print(constFalse && foo()! ? '3_no' : '4_yes ${foo()}');
}
void testAsserts() {
- assert(foo());
- assert(!foo(), "oops!");
+ assert(foo()!);
+ assert(!foo()!, "oops!");
}
class TestAssertInitializer {
- TestAssertInitializer() : assert(foo()) {}
+ TestAssertInitializer() : assert(foo()!) {}
}
testRemovalOfStatementBodies() {
- if (foo()) assert(foo());
- while (foo()) assert(foo());
- do assert(foo()); while (foo());
- for (;;) assert(foo());
- for (var i in [1, 2]) assert(foo());
+ if (foo()!) assert(foo()!);
+ while (foo()!) assert(foo()!);
+ do assert(foo()!); while (foo()!);
+ for (;;) assert(foo()!);
+ for (var i in [1, 2]) assert(foo()!);
try {
- assert(foo());
+ assert(foo()!);
} finally {
- assert(foo());
+ assert(foo()!);
}
try {
- assert(foo());
+ assert(foo()!);
} catch (e) {
- assert(foo());
+ assert(foo()!);
}
try {
- assert(foo());
+ assert(foo()!);
} catch (e) {
- assert(foo());
+ assert(foo()!);
rethrow;
}
switch (42) {
case 10:
- assert(foo());
+ assert(foo()!);
}
switch (42) {
default:
- assert(foo());
+ assert(foo()!);
}
}
diff --git a/pkg/vm/testcases/transformations/unreachable_code_elimination/uce_testcases.dart.expect b/pkg/vm/testcases/transformations/unreachable_code_elimination/uce_testcases.dart.expect
index e9346d5..4bf2ed9 100644
--- a/pkg/vm/testcases/transformations/unreachable_code_elimination/uce_testcases.dart.expect
+++ b/pkg/vm/testcases/transformations/unreachable_code_elimination/uce_testcases.dart.expect
@@ -1,26 +1,16 @@
-library #lib;
+library #lib /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
class TestAssertInitializer extends core::Object {
- constructor •() → self::TestAssertInitializer*
+ constructor •() → self::TestAssertInitializer
: super core::Object::•() {}
- abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
- abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
- abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
- abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
- abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
- abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
- abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
- abstract member-signature method toString() → core::String*; -> core::Object::toString
- abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
- abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
}
-static const field core::bool* constTrue = #C1;
-static const field core::bool* constFalse = #C2;
-static const field core::bool* constTrue2 = #C1;
-static const field core::bool* constFalse2 = #C2;
-static method foo() → core::bool*
+static const field core::bool constTrue = #C1;
+static const field core::bool constFalse = #C2;
+static const field core::bool constTrue2 = #C1;
+static const field core::bool constFalse2 = #C2;
+static method foo() → core::bool?
return null;
static method testSimpleConditions() → void {
{
@@ -31,7 +21,7 @@
}
}
static method testAndConditions() → void {
- if((#C1) && self::foo()) {
+ if((#C1) && self::foo()!) {
core::print("1_yes");
}
}
@@ -39,7 +29,7 @@
{
core::print("1_yes");
}
- if((#C2) || self::foo()) {
+ if((#C2) || self::foo()!) {
core::print("2_yes");
}
{
@@ -57,25 +47,25 @@
}
static method testAsserts() → void {}
static method testRemovalOfStatementBodies() → dynamic {
- if(self::foo()) {
+ if(self::foo()!) {
}
- while (self::foo()) {
+ while (self::foo()!) {
}
do {
}
- while (self::foo())
+ while (self::foo()!)
for (; ; ) {
}
{
- core::Iterator<core::int*>* :sync-for-iterator = core::_GrowableList::_literal2<core::int*>(1, 2).{core::Iterable::iterator}{core::Iterator<core::int*>*};
+ core::Iterator<core::int> :sync-for-iterator = core::_GrowableList::_literal2<core::int>(1, 2).{core::Iterable::iterator}{core::Iterator<core::int>};
for (; :sync-for-iterator.{core::Iterator::moveNext}(){() → core::bool}; ) {
- core::int* i = :sync-for-iterator.{core::Iterator::current}{core::int*};
+ core::int i = :sync-for-iterator.{core::Iterator::current}{core::int};
}
}
{}
try {
}
- on dynamic catch(final dynamic e) {
+ on core::Object catch(final core::Object e) {
}
{}
switch(42) {
@@ -89,7 +79,7 @@
{}
}
}
-static method main(core::List<core::String*>* args) → dynamic {
+static method main(core::List<core::String> args) → dynamic {
self::testSimpleConditions();
self::testAndConditions();
self::testOrConditions();
diff --git a/pkg/vm_service/CHANGELOG.md b/pkg/vm_service/CHANGELOG.md
index 4d071d5..3c1a964 100644
--- a/pkg/vm_service/CHANGELOG.md
+++ b/pkg/vm_service/CHANGELOG.md
@@ -1,8 +1,12 @@
# Changelog
## 7.1.1
-- Update to version `3.47` of the spec.
+- Update to version `3.48` of the spec.
- Added `shows` and `hides` properties to `LibraryDependency`.
+- Added `Profiler` stream, `UserTagChanged` event kind, and `updatedTag` and
+ `previousTag` properties to `Event`.
+- Fixed bug where a response without a type would cause a null type failure
+ (dart-lang/sdk#46559).
## 7.1.0
- Update to version `3.46` of the spec.
diff --git a/pkg/vm_service/example/vm_service_assert.dart b/pkg/vm_service/example/vm_service_assert.dart
index b458ad6..0af318b 100644
--- a/pkg/vm_service/example/vm_service_assert.dart
+++ b/pkg/vm_service/example/vm_service_assert.dart
@@ -137,6 +137,7 @@
if (obj == "BreakpointRemoved") return obj;
if (obj == "BreakpointResolved") return obj;
if (obj == "BreakpointUpdated") return obj;
+ if (obj == "CpuSamples") return obj;
if (obj == "Extension") return obj;
if (obj == "GC") return obj;
if (obj == "Inspect") return obj;
@@ -177,6 +178,7 @@
if (obj == "Float64List") return obj;
if (obj == "Float64x2") return obj;
if (obj == "Float64x2List") return obj;
+ if (obj == "FunctionType") return obj;
if (obj == "Int") return obj;
if (obj == "Int16List") return obj;
if (obj == "Int32List") return obj;
@@ -577,6 +579,7 @@
}
assertBool(obj.isStatic!);
assertBool(obj.isConst!);
+ assertBool(obj.implicit!);
return obj;
}
@@ -602,6 +605,8 @@
}
assertBool(obj.isStatic!);
assertBool(obj.isConst!);
+ assertBool(obj.implicit!);
+ assertInstanceRef(obj.signature!);
return obj;
}
@@ -879,6 +884,13 @@
return obj;
}
+vms.Parameter assertParameter(vms.Parameter obj) {
+ assertNotNull(obj);
+ assertInstanceRef(obj.parameterType!);
+ assertBool(obj.fixed!);
+ return obj;
+}
+
vms.PortList assertPortList(vms.PortList obj) {
assertNotNull(obj);
assertListOfInstanceRef(obj.ports!);
@@ -1120,6 +1132,14 @@
return obj;
}
+vms.TypeParameters assertTypeParameters(vms.TypeParameters obj) {
+ assertNotNull(obj);
+ assertListOfString(obj.names!);
+ assertTypeArgumentsRef(obj.bounds!);
+ assertTypeArgumentsRef(obj.defaults!);
+ return obj;
+}
+
vms.UnresolvedSourceLocation assertUnresolvedSourceLocation(
vms.UnresolvedSourceLocation obj) {
assertNotNull(obj);
diff --git a/pkg/vm_service/java/.gitignore b/pkg/vm_service/java/.gitignore
index cdc39af..cc8a3e7 100644
--- a/pkg/vm_service/java/.gitignore
+++ b/pkg/vm_service/java/.gitignore
@@ -99,6 +99,7 @@
src/org/dartlang/vm/service/element/NullRef.java
src/org/dartlang/vm/service/element/Obj.java
src/org/dartlang/vm/service/element/ObjRef.java
+src/org/dartlang/vm/service/element/Parameter.java
src/org/dartlang/vm/service/element/PortList.java
src/org/dartlang/vm/service/element/ProcessMemoryItem.java
src/org/dartlang/vm/service/element/ProcessMemoryUsage.java
@@ -128,6 +129,7 @@
src/org/dartlang/vm/service/element/Timestamp.java
src/org/dartlang/vm/service/element/TypeArguments.java
src/org/dartlang/vm/service/element/TypeArgumentsRef.java
+src/org/dartlang/vm/service/element/TypeParameters.java
src/org/dartlang/vm/service/element/UnresolvedSourceLocation.java
src/org/dartlang/vm/service/element/VM.java
src/org/dartlang/vm/service/element/VMRef.java
diff --git a/pkg/vm_service/java/version.properties b/pkg/vm_service/java/version.properties
index 62cbe79..5e787ed 100644
--- a/pkg/vm_service/java/version.properties
+++ b/pkg/vm_service/java/version.properties
@@ -1 +1 @@
-version=3.48
+version=3.49
diff --git a/pkg/vm_service/lib/src/vm_service.dart b/pkg/vm_service/lib/src/vm_service.dart
index 903bb0c..77ce904 100644
--- a/pkg/vm_service/lib/src/vm_service.dart
+++ b/pkg/vm_service/lib/src/vm_service.dart
@@ -26,7 +26,7 @@
HeapSnapshotObjectNoData,
HeapSnapshotObjectNullData;
-const String vmServiceVersion = '3.48.0';
+const String vmServiceVersion = '3.49.0';
/// @optional
const String optional = 'optional';
@@ -44,7 +44,7 @@
if (json is List) {
return json.map((e) => createServiceObject(e, expectedTypes)).toList();
- } else if (json is Map) {
+ } else if (json is Map<String, dynamic>) {
String? type = json['type'];
// Not a Response type.
@@ -53,7 +53,7 @@
if (expectedTypes.length == 1) {
type = expectedTypes.first;
} else {
- return null;
+ return Response.parse(json);
}
} else if (_isNullInstance(json) &&
(!expectedTypes.contains('InstanceRef'))) {
@@ -157,6 +157,7 @@
'Null': NullVal.parse,
'@Object': ObjRef.parse,
'Object': Obj.parse,
+ 'Parameter': Parameter.parse,
'PortList': PortList.parse,
'ProfileFunction': ProfileFunction.parse,
'ProtocolList': ProtocolList.parse,
@@ -183,6 +184,7 @@
'Timestamp': Timestamp.parse,
'@TypeArguments': TypeArgumentsRef.parse,
'TypeArguments': TypeArguments.parse,
+ 'TypeParameters': TypeParameters.parse,
'UnresolvedSourceLocation': UnresolvedSourceLocation.parse,
'Version': Version.parse,
'@VM': VMRef.parse,
@@ -824,8 +826,7 @@
/// returned.
Future<SourceReport> getSourceReport(
String isolateId,
- /*List<SourceReportKind>*/
- List<String> reports, {
+ /*List<SourceReportKind>*/ List<String> reports, {
String? scriptId,
int? tokenPos,
int? endTokenPos,
@@ -1150,7 +1151,7 @@
/// Debug | PauseStart, PauseExit, PauseBreakpoint, PauseInterrupted,
/// PauseException, PausePostRequest, Resume, BreakpointAdded,
/// BreakpointResolved, BreakpointRemoved, BreakpointUpdated, Inspect, None
- /// Profiler | UserTagChanged
+ /// Profiler | CpuSamples, UserTagChanged
/// GC | GC
/// Extension | Extension
/// Timeline | TimelineEvents, TimelineStreamsSubscriptionUpdate
@@ -1691,7 +1692,7 @@
// PauseStart, PauseExit, PauseBreakpoint, PauseInterrupted, PauseException, PausePostRequest, Resume, BreakpointAdded, BreakpointResolved, BreakpointRemoved, BreakpointUpdated, Inspect, None
Stream<Event> get onDebugEvent => _getEventController('Debug').stream;
- // UserTagChanged
+ // CpuSamples, UserTagChanged
Stream<Event> get onProfilerEvent => _getEventController('Profiler').stream;
// GC
@@ -1923,8 +1924,7 @@
@override
Future<SourceReport> getSourceReport(
String isolateId,
- /*List<SourceReportKind>*/
- List<String> reports, {
+ /*List<SourceReportKind>*/ List<String> reports, {
String? scriptId,
int? tokenPos,
int? endTokenPos,
@@ -2196,7 +2196,7 @@
request.completeError(RPCError.parse(request.method, json['error']));
} else {
Map<String, dynamic> result = json['result'] as Map<String, dynamic>;
- String type = result['type'];
+ String? type = result['type'];
if (type == 'Sentinel') {
request.completeError(SentinelException.parse(request.method, result));
} else if (_typeFactories[type] == null) {
@@ -2504,6 +2504,9 @@
/// Notification that the UserTag for an isolate has been changed.
static const String kUserTagChanged = 'UserTagChanged';
+
+ /// A block of recently collected CPU samples.
+ static const String kCpuSamples = 'CpuSamples';
}
/// Adding new values to `InstanceKind` is considered a backwards compatible
@@ -2584,6 +2587,9 @@
/// An instance of the Dart class TypeRef.
static const String kTypeRef = 'TypeRef';
+ /// An instance of the Dart class FunctionType.
+ static const String kFunctionType = 'FunctionType';
+
/// An instance of the Dart class BoundedType.
static const String kBoundedType = 'BoundedType';
@@ -2929,11 +2935,18 @@
/// The library which contains this class.
LibraryRef? library;
+ /// The type parameters for the class.
+ ///
+ /// Provided if the class is generic.
+ @optional
+ List<InstanceRef>? typeParameters;
+
ClassRef({
required this.name,
required this.library,
required String id,
this.location,
+ this.typeParameters,
}) : super(
id: id,
);
@@ -2944,6 +2957,11 @@
as SourceLocation?;
library = createServiceObject(json['library'], const ['LibraryRef'])
as LibraryRef?;
+ typeParameters = json['typeParameters'] == null
+ ? null
+ : List<InstanceRef>.from(
+ createServiceObject(json['typeParameters'], const ['InstanceRef'])!
+ as List);
}
@override
@@ -2958,6 +2976,8 @@
'library': library?.toJson(),
});
_setIfNotNull(json, 'location', location?.toJson());
+ _setIfNotNull(json, 'typeParameters',
+ typeParameters?.map((f) => f.toJson()).toList());
return json;
}
@@ -2984,6 +3004,12 @@
/// The library which contains this class.
LibraryRef? library;
+ /// The type parameters for the class.
+ ///
+ /// Provided if the class is generic.
+ @optional
+ List<InstanceRef>? typeParameters;
+
/// The error which occurred during class finalization, if it exists.
@optional
ErrorRef? error;
@@ -3040,6 +3066,7 @@
required this.subclasses,
required String id,
this.location,
+ this.typeParameters,
this.error,
this.superClass,
this.superType,
@@ -3054,6 +3081,11 @@
as SourceLocation?;
library = createServiceObject(json['library'], const ['LibraryRef'])
as LibraryRef?;
+ typeParameters = json['typeParameters'] == null
+ ? null
+ : List<InstanceRef>.from(
+ createServiceObject(json['typeParameters'], const ['InstanceRef'])!
+ as List);
error = createServiceObject(json['error'], const ['ErrorRef']) as ErrorRef?;
isAbstract = json['abstract'] ?? false;
isConst = json['const'] ?? false;
@@ -3097,6 +3129,8 @@
'subclasses': subclasses?.map((f) => f.toJson()).toList(),
});
_setIfNotNull(json, 'location', location?.toJson());
+ _setIfNotNull(json, 'typeParameters',
+ typeParameters?.map((f) => f.toJson()).toList());
_setIfNotNull(json, 'error', error?.toJson());
_setIfNotNull(json, 'super', superClass?.toJson());
_setIfNotNull(json, 'superType', superType?.toJson());
@@ -3901,6 +3935,10 @@
@optional
String? previousTag;
+ /// A CPU profile containing recent samples.
+ @optional
+ CpuSamples? cpuSamples;
+
/// Binary data associated with the event.
///
/// This is provided for the event kinds:
@@ -3935,6 +3973,7 @@
this.last,
this.updatedTag,
this.previousTag,
+ this.cpuSamples,
this.data,
});
@@ -3979,6 +4018,8 @@
last = json['last'];
updatedTag = json['updatedTag'];
previousTag = json['previousTag'];
+ cpuSamples = createServiceObject(json['cpuSamples'], const ['CpuSamples'])
+ as CpuSamples?;
data = json['data'];
}
@@ -4020,6 +4061,7 @@
_setIfNotNull(json, 'last', last);
_setIfNotNull(json, 'updatedTag', updatedTag);
_setIfNotNull(json, 'previousTag', previousTag);
+ _setIfNotNull(json, 'cpuSamples', cpuSamples?.toJson());
_setIfNotNull(json, 'data', data);
return json;
}
@@ -4307,8 +4349,7 @@
List<BoundVariable>? vars;
@optional
- /*FrameKind*/
- String? kind;
+ /*FrameKind*/ String? kind;
Frame({
required this.index,
@@ -4374,6 +4415,9 @@
/// Is this function const?
bool? isConst;
+ /// Is this function implicitly defined (e.g., implicit getter/setter)?
+ bool? implicit;
+
/// The location of this function in the source code.
@optional
SourceLocation? location;
@@ -4383,6 +4427,7 @@
required this.owner,
required this.isStatic,
required this.isConst,
+ required this.implicit,
required String id,
this.location,
}) : super(
@@ -4395,6 +4440,7 @@
json['owner'], const ['LibraryRef', 'ClassRef', 'FuncRef']) as dynamic;
isStatic = json['static'] ?? false;
isConst = json['const'] ?? false;
+ implicit = json['implicit'] ?? false;
location = createServiceObject(json['location'], const ['SourceLocation'])
as SourceLocation?;
}
@@ -4411,6 +4457,7 @@
'owner': owner?.toJson(),
'static': isStatic,
'const': isConst,
+ 'implicit': implicit,
});
_setIfNotNull(json, 'location', location?.toJson());
return json;
@@ -4422,7 +4469,7 @@
String toString() => '[FuncRef ' //
'id: ${id}, name: ${name}, owner: ${owner}, isStatic: ${isStatic}, ' //
- 'isConst: ${isConst}]';
+ 'isConst: ${isConst}, implicit: ${implicit}]';
}
/// A `Func` represents a Dart language function.
@@ -4444,10 +4491,16 @@
/// Is this function const?
bool? isConst;
+ /// Is this function implicitly defined (e.g., implicit getter/setter)?
+ bool? implicit;
+
/// The location of this function in the source code.
@optional
SourceLocation? location;
+ /// The signature of the function.
+ InstanceRef? signature;
+
/// The compiled code associated with this function.
@optional
CodeRef? code;
@@ -4457,6 +4510,8 @@
required this.owner,
required this.isStatic,
required this.isConst,
+ required this.implicit,
+ required this.signature,
required String id,
this.location,
this.code,
@@ -4470,8 +4525,11 @@
json['owner'], const ['LibraryRef', 'ClassRef', 'FuncRef']) as dynamic;
isStatic = json['static'] ?? false;
isConst = json['const'] ?? false;
+ implicit = json['implicit'] ?? false;
location = createServiceObject(json['location'], const ['SourceLocation'])
as SourceLocation?;
+ signature = createServiceObject(json['signature'], const ['InstanceRef'])
+ as InstanceRef?;
code = createServiceObject(json['code'], const ['CodeRef']) as CodeRef?;
}
@@ -4487,6 +4545,8 @@
'owner': owner?.toJson(),
'static': isStatic,
'const': isConst,
+ 'implicit': implicit,
+ 'signature': signature?.toJson(),
});
_setIfNotNull(json, 'location', location?.toJson());
_setIfNotNull(json, 'code', code?.toJson());
@@ -4499,7 +4559,7 @@
String toString() => '[Func ' //
'id: ${id}, name: ${name}, owner: ${owner}, isStatic: ${isStatic}, ' //
- 'isConst: ${isConst}]';
+ 'isConst: ${isConst}, implicit: ${implicit}, signature: ${signature}]';
}
/// `InstanceRef` is a reference to an `Instance`.
@@ -4578,13 +4638,34 @@
@optional
ClassRef? typeClass;
- /// The parameterized class of a type parameter:
+ /// The parameterized class of a type parameter.
///
/// Provided for instance kinds:
/// - TypeParameter
@optional
ClassRef? parameterizedClass;
+ /// The return type of a function.
+ ///
+ /// Provided for instance kinds:
+ /// - FunctionType
+ @optional
+ InstanceRef? returnType;
+
+ /// The list of parameter types for a function.
+ ///
+ /// Provided for instance kinds:
+ /// - FunctionType
+ @optional
+ List<Parameter>? parameters;
+
+ /// The type parameters for a function.
+ ///
+ /// Provided for instance kinds:
+ /// - FunctionType
+ @optional
+ List<InstanceRef>? typeParameters;
+
/// The pattern of a RegExp instance.
///
/// The pattern is always an instance of kind String.
@@ -4640,6 +4721,9 @@
this.name,
this.typeClass,
this.parameterizedClass,
+ this.returnType,
+ this.parameters,
+ this.typeParameters,
this.pattern,
this.closureFunction,
this.closureContext,
@@ -4664,6 +4748,18 @@
parameterizedClass =
createServiceObject(json['parameterizedClass'], const ['ClassRef'])
as ClassRef?;
+ returnType = createServiceObject(json['returnType'], const ['InstanceRef'])
+ as InstanceRef?;
+ parameters = json['parameters'] == null
+ ? null
+ : List<Parameter>.from(
+ createServiceObject(json['parameters'], const ['Parameter'])!
+ as List);
+ typeParameters = json['typeParameters'] == null
+ ? null
+ : List<InstanceRef>.from(
+ createServiceObject(json['typeParameters'], const ['InstanceRef'])!
+ as List);
pattern = createServiceObject(json['pattern'], const ['InstanceRef'])
as InstanceRef?;
closureFunction =
@@ -4697,6 +4793,11 @@
_setIfNotNull(json, 'name', name);
_setIfNotNull(json, 'typeClass', typeClass?.toJson());
_setIfNotNull(json, 'parameterizedClass', parameterizedClass?.toJson());
+ _setIfNotNull(json, 'returnType', returnType?.toJson());
+ _setIfNotNull(
+ json, 'parameters', parameters?.map((f) => f.toJson()).toList());
+ _setIfNotNull(json, 'typeParameters',
+ typeParameters?.map((f) => f.toJson()).toList());
_setIfNotNull(json, 'pattern', pattern?.toJson());
_setIfNotNull(json, 'closureFunction', closureFunction?.toJson());
_setIfNotNull(json, 'closureContext', closureContext?.toJson());
@@ -4843,6 +4944,27 @@
@optional
ClassRef? parameterizedClass;
+ /// The return type of a function.
+ ///
+ /// Provided for instance kinds:
+ /// - FunctionType
+ @optional
+ InstanceRef? returnType;
+
+ /// The list of parameter types for a function.
+ ///
+ /// Provided for instance kinds:
+ /// - FunctionType
+ @optional
+ List<Parameter>? parameters;
+
+ /// The type parameters for a function.
+ ///
+ /// Provided for instance kinds:
+ /// - FunctionType
+ @optional
+ List<InstanceRef>? typeParameters;
+
/// The fields of this Instance.
@optional
List<BoundField>? fields;
@@ -5010,6 +5132,9 @@
this.name,
this.typeClass,
this.parameterizedClass,
+ this.returnType,
+ this.parameters,
+ this.typeParameters,
this.fields,
this.elements,
this.associations,
@@ -5050,6 +5175,18 @@
parameterizedClass =
createServiceObject(json['parameterizedClass'], const ['ClassRef'])
as ClassRef?;
+ returnType = createServiceObject(json['returnType'], const ['InstanceRef'])
+ as InstanceRef?;
+ parameters = json['parameters'] == null
+ ? null
+ : List<Parameter>.from(
+ createServiceObject(json['parameters'], const ['Parameter'])!
+ as List);
+ typeParameters = json['typeParameters'] == null
+ ? null
+ : List<InstanceRef>.from(
+ createServiceObject(json['typeParameters'], const ['InstanceRef'])!
+ as List);
fields = json['fields'] == null
? null
: List<BoundField>.from(
@@ -5117,6 +5254,11 @@
_setIfNotNull(json, 'name', name);
_setIfNotNull(json, 'typeClass', typeClass?.toJson());
_setIfNotNull(json, 'parameterizedClass', parameterizedClass?.toJson());
+ _setIfNotNull(json, 'returnType', returnType?.toJson());
+ _setIfNotNull(
+ json, 'parameters', parameters?.map((f) => f.toJson()).toList());
+ _setIfNotNull(json, 'typeParameters',
+ typeParameters?.map((f) => f.toJson()).toList());
_setIfNotNull(json, 'fields', fields?.map((f) => f.toJson()).toList());
_setIfNotNull(json, 'elements', elements?.map((f) => f.toJson()).toList());
_setIfNotNull(
@@ -5447,18 +5589,19 @@
'id: ${id}, number: ${number}, name: ${name}, isSystemIsolateGroup: ${isSystemIsolateGroup}]';
}
-/// An `Isolate` object provides information about one isolate in the VM.
+/// An `IsolateGroup` object provides information about an isolate group in the
+/// VM.
class IsolateGroup extends Response implements IsolateGroupRef {
static IsolateGroup? parse(Map<String, dynamic>? json) =>
json == null ? null : IsolateGroup._fromJson(json);
- /// The id which is passed to the getIsolate RPC to reload this isolate.
+ /// The id which is passed to the getIsolateGroup RPC to reload this isolate.
String? id;
/// A numeric id for this isolate, represented as a string. Unique.
String? number;
- /// A name identifying this isolate. Not guaranteed to be unique.
+ /// A name identifying this isolate group. Not guaranteed to be unique.
String? name;
/// Specifies whether the isolate group was spawned by the VM or embedder for
@@ -6328,6 +6471,58 @@
String toString() => '[Obj id: ${id}]';
}
+/// A `Parameter` is a representation of a function parameter.
+///
+/// See [Instance].
+class Parameter {
+ static Parameter? parse(Map<String, dynamic>? json) =>
+ json == null ? null : Parameter._fromJson(json);
+
+ /// The type of the parameter.
+ InstanceRef? parameterType;
+
+ /// Represents whether or not this parameter is fixed or optional.
+ bool? fixed;
+
+ /// The name of a named optional parameter.
+ @optional
+ String? name;
+
+ /// Whether or not this named optional parameter is marked as required.
+ @optional
+ bool? required;
+
+ Parameter({
+ required this.parameterType,
+ required this.fixed,
+ this.name,
+ this.required,
+ });
+
+ Parameter._fromJson(Map<String, dynamic> json) {
+ parameterType =
+ createServiceObject(json['parameterType'], const ['InstanceRef'])
+ as InstanceRef?;
+ fixed = json['fixed'] ?? false;
+ name = json['name'];
+ required = json['required'];
+ }
+
+ Map<String, dynamic> toJson() {
+ final json = <String, dynamic>{};
+ json.addAll({
+ 'parameterType': parameterType?.toJson(),
+ 'fixed': fixed,
+ });
+ _setIfNotNull(json, 'name', name);
+ _setIfNotNull(json, 'required', required);
+ return json;
+ }
+
+ String toString() =>
+ '[Parameter parameterType: ${parameterType}, fixed: ${fixed}]';
+}
+
/// A `PortList` contains a list of ports associated with some isolate.
///
/// See [getPort].
@@ -7553,6 +7748,49 @@
'[TypeArguments id: ${id}, name: ${name}, types: ${types}]';
}
+/// A `TypeParameters` object represents the type argument vector for some
+/// uninstantiated generic type.
+class TypeParameters {
+ static TypeParameters? parse(Map<String, dynamic>? json) =>
+ json == null ? null : TypeParameters._fromJson(json);
+
+ /// The names of the type parameters.
+ List<String>? names;
+
+ /// The bounds set on each type parameter.
+ TypeArgumentsRef? bounds;
+
+ /// The default types for each type parameter.
+ TypeArgumentsRef? defaults;
+
+ TypeParameters({
+ required this.names,
+ required this.bounds,
+ required this.defaults,
+ });
+
+ TypeParameters._fromJson(Map<String, dynamic> json) {
+ names = List<String>.from(json['names']);
+ bounds = createServiceObject(json['bounds'], const ['TypeArgumentsRef'])
+ as TypeArgumentsRef?;
+ defaults = createServiceObject(json['defaults'], const ['TypeArgumentsRef'])
+ as TypeArgumentsRef?;
+ }
+
+ Map<String, dynamic> toJson() {
+ final json = <String, dynamic>{};
+ json.addAll({
+ 'names': names?.map((f) => f).toList(),
+ 'bounds': bounds?.toJson(),
+ 'defaults': defaults?.toJson(),
+ });
+ return json;
+ }
+
+ String toString() =>
+ '[TypeParameters names: ${names}, bounds: ${bounds}, defaults: ${defaults}]';
+}
+
/// The `UnresolvedSourceLocation` class is used to refer to an unresolved
/// breakpoint location. As such, it is meant to approximate the final location
/// of the breakpoint but it is not exact.
diff --git a/pkg/vm_service/pubspec.yaml b/pkg/vm_service/pubspec.yaml
index 9ea0b77..5aad6b6 100644
--- a/pkg/vm_service/pubspec.yaml
+++ b/pkg/vm_service/pubspec.yaml
@@ -3,7 +3,7 @@
A library to communicate with a service implementing the Dart VM
service protocol.
-version: 7.1.0
+version: 7.1.1
homepage: https://github.com/dart-lang/sdk/tree/master/pkg/vm_service
diff --git a/pkg/vm_service/test/cpu_samples_stream_test.dart b/pkg/vm_service/test/cpu_samples_stream_test.dart
new file mode 100644
index 0000000..d6846ef
--- /dev/null
+++ b/pkg/vm_service/test/cpu_samples_stream_test.dart
@@ -0,0 +1,71 @@
+// 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.
+
+import 'dart:async';
+
+import 'package:test/test.dart';
+import 'package:vm_service/vm_service.dart';
+
+import 'common/service_test_common.dart';
+import 'common/test_helper.dart';
+
+fib(int n) {
+ if (n <= 1) {
+ return n;
+ }
+ return fib(n - 1) + fib(n - 2);
+}
+
+void testMain() async {
+ int i = 10;
+ while (true) {
+ ++i;
+ // Create progressively deeper stacks to more quickly fill the sample
+ // buffer.
+ fib(i);
+ }
+}
+
+late StreamSubscription sub;
+
+var tests = <IsolateTest>[
+ (VmService service, IsolateRef isolate) async {
+ final completer = Completer<void>();
+ int count = 0;
+ int previousOrigin = 0;
+ sub = service.onProfilerEvent.listen((event) async {
+ count++;
+ expect(event.kind, EventKind.kCpuSamples);
+ expect(event.cpuSamples, isNotNull);
+ expect(event.cpuSamples!.samples!.isNotEmpty, true);
+ if (previousOrigin != 0) {
+ expect(
+ event.cpuSamples!.timeOriginMicros! >= previousOrigin,
+ true,
+ );
+ }
+ previousOrigin = event.cpuSamples!.timeOriginMicros!;
+
+ if (count == 2) {
+ await sub.cancel();
+ completer.complete();
+ }
+ });
+ await service.streamListen(EventStreams.kProfiler);
+
+ await completer.future;
+ await service.streamCancel(EventStreams.kProfiler);
+ },
+];
+
+main([args = const <String>[]]) async => await runIsolateTests(
+ args,
+ tests,
+ 'cpu_samples_stream_test.dart',
+ testeeConcurrent: testMain,
+ extraArgs: [
+ '--sample-buffer-duration=1',
+ '--profile-vm',
+ ],
+ );
diff --git a/pkg/vm_service/test/library_dependency_test.dart b/pkg/vm_service/test/library_dependency_test.dart
index 5f308ef..5745ca1 100644
--- a/pkg/vm_service/test/library_dependency_test.dart
+++ b/pkg/vm_service/test/library_dependency_test.dart
@@ -8,7 +8,6 @@
import 'package:test/test.dart';
import 'package:vm_service/vm_service.dart';
-import 'common/service_test_common.dart';
import 'common/test_helper.dart';
export 'dart:io' show Socket hide SecureSocket;
diff --git a/pkg/vm_service/test/mark_main_isolate_as_system_isolate_test.dart b/pkg/vm_service/test/mark_main_isolate_as_system_isolate_test.dart
new file mode 100644
index 0000000..c69323d
--- /dev/null
+++ b/pkg/vm_service/test/mark_main_isolate_as_system_isolate_test.dart
@@ -0,0 +1,39 @@
+// 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.
+
+import 'dart:isolate';
+import 'package:test/test.dart';
+import 'package:vm_service/vm_service.dart' as service;
+
+import 'common/service_test_common.dart';
+import 'common/test_helper.dart';
+
+foo(void _) async {
+ print('non system isolate started');
+ while (true) {}
+}
+
+testMain() async {
+ await Isolate.spawn<void>(foo, null);
+ print('started system isolate main');
+ while (true) {}
+}
+
+var tests = <VMTest>[
+ (service.VmService service) async {
+ final vm = await service.getVM();
+ expect(vm.isolates!.length, 1);
+ expect(vm.isolates!.first.name, 'foo');
+ expect(vm.systemIsolates!.length, greaterThanOrEqualTo(1));
+ expect(vm.systemIsolates!.where((e) => e.name == 'main').isNotEmpty, true);
+ }
+];
+
+main([args = const <String>[]]) => runVMTests(
+ args,
+ tests,
+ 'mark_main_isolate_as_system_isolate_test.dart',
+ testeeConcurrent: testMain,
+ extraArgs: ['--mark-main-isolate-as-system-isolate'],
+ );
diff --git a/pkg/vm_service/test/regress_46559_test.dart b/pkg/vm_service/test/regress_46559_test.dart
new file mode 100644
index 0000000..84fceae
--- /dev/null
+++ b/pkg/vm_service/test/regress_46559_test.dart
@@ -0,0 +1,45 @@
+// 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.
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:developer';
+
+import 'package:vm_service/vm_service.dart';
+
+import 'common/service_test_common.dart';
+import 'common/test_helper.dart';
+
+Future<ServiceExtensionResponse> echo(
+ String method, Map<String, String> args) async {
+ print('In service extension');
+ return ServiceExtensionResponse.result(json.encode(args));
+}
+
+testMain() {
+ registerExtension('ext.foo', echo);
+ debugger();
+}
+
+final tests = <IsolateTest>[
+ hasStoppedAtBreakpoint,
+ resumeIsolate,
+ (VmService vm, IsolateRef isolateRef) async {
+ print('waiting for response');
+ final response = await vm.callServiceExtension(
+ 'ext.foo',
+ isolateId: isolateRef.id!,
+ args: {'foo': 'bar'},
+ );
+ print('got response');
+ print(response.json);
+ },
+];
+
+main([args = const <String>[]]) async => await runIsolateTests(
+ args,
+ tests,
+ 'regress_46559_test.dart',
+ testeeConcurrent: testMain,
+ );
diff --git a/pkg/vm_service/tool/dart/generate_dart.dart b/pkg/vm_service/tool/dart/generate_dart.dart
index 2cf8fd8..844b1ff 100644
--- a/pkg/vm_service/tool/dart/generate_dart.dart
+++ b/pkg/vm_service/tool/dart/generate_dart.dart
@@ -200,7 +200,7 @@
request.completeError(RPCError.parse(request.method, json['error']));
} else {
Map<String, dynamic> result = json['result'] as Map<String, dynamic>;
- String type = result['type'];
+ String? type = result['type'];
if (type == 'Sentinel') {
request.completeError(SentinelException.parse(request.method, result));
} else if (_typeFactories[type] == null) {
@@ -517,7 +517,7 @@
if (json is List) {
return json.map((e) => createServiceObject(e, expectedTypes)).toList();
- } else if (json is Map) {
+ } else if (json is Map<String, dynamic>) {
String? type = json['type'];
// Not a Response type.
@@ -526,7 +526,7 @@
if (expectedTypes.length == 1) {
type = expectedTypes.first;
} else {
- return null;
+ return Response.parse(json);
}
} else if (_isNullInstance(json) && (!expectedTypes.contains('InstanceRef'))) {
// Replace null instances with null when we don't expect an instance to
diff --git a/runtime/bin/dart_io_api_impl.cc b/runtime/bin/dart_io_api_impl.cc
index a890132..8ec2c1d 100644
--- a/runtime/bin/dart_io_api_impl.cc
+++ b/runtime/bin/dart_io_api_impl.cc
@@ -31,6 +31,7 @@
void CleanupDartIo() {
EventHandler::Stop();
+ Process::TerminateExitCodeHandler();
#if !defined(DART_IO_SECURE_SOCKET_DISABLED)
SSLFilter::Cleanup();
#endif
diff --git a/runtime/bin/elf_loader.cc b/runtime/bin/elf_loader.cc
index 92d6685..43b152d 100644
--- a/runtime/bin/elf_loader.cc
+++ b/runtime/bin/elf_loader.cc
@@ -6,7 +6,6 @@
#include <bin/file.h>
#include <platform/elf.h>
#include <platform/globals.h>
-#include <vm/bss_relocs.h>
#include <vm/cpu.h>
#include <vm/virtual_memory.h>
@@ -239,8 +238,6 @@
const char* dynamic_string_table_ = nullptr;
const dart::elf::Symbol* dynamic_symbol_table_ = nullptr;
uword dynamic_symbol_count_ = 0;
- uword* vm_bss_ = nullptr;
- uword* isolate_bss_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(LoadedElf);
};
@@ -468,20 +465,11 @@
dynamic_symbol_table_ = reinterpret_cast<const dart::elf::Symbol*>(
base_->start() + header.memory_offset);
dynamic_symbol_count_ = header.file_size / sizeof(dart::elf::Symbol);
- } else if (strcmp(name, ".bss") == 0) {
- auto const bss_size =
- (BSS::kVmEntryCount + BSS::kIsolateEntryCount) * kWordSize;
- CHECK_ERROR(header.memory_offset != 0, ".bss must be loaded.");
- CHECK_ERROR(header.file_size >= bss_size,
- ".bss does not have enough space.");
- vm_bss_ = reinterpret_cast<uword*>(base_->start() + header.memory_offset);
- isolate_bss_ = vm_bss_ + BSS::kVmEntryCount;
}
}
CHECK_ERROR(dynamic_string_table_ != nullptr, "Couldn't find .dynstr.");
CHECK_ERROR(dynamic_symbol_table_ != nullptr, "Couldn't find .dynsym.");
- CHECK_ERROR(vm_bss_ != nullptr, "Couldn't find .bss.");
return true;
}
diff --git a/runtime/bin/ffi_test/ffi_test_functions_vmspecific.cc b/runtime/bin/ffi_test/ffi_test_functions_vmspecific.cc
index a4ad2d5..adcdc07 100644
--- a/runtime/bin/ffi_test/ffi_test_functions_vmspecific.cc
+++ b/runtime/bin/ffi_test/ffi_test_functions_vmspecific.cc
@@ -1080,4 +1080,36 @@
Dart_DeletePersistentHandle_DL(closure_to_callback_);
}
+////////////////////////////////////////////////////////////////////////////////
+// Functions for testing @FfiNative.
+
+DART_EXPORT Dart_Handle GetRootLibraryUrl() {
+ Dart_Handle root_lib = Dart_RootLibrary();
+ Dart_Handle lib_url = Dart_LibraryUrl(root_lib);
+ ENSURE(!Dart_IsError(lib_url));
+ return lib_url;
+}
+
+intptr_t ReturnIntPtr(intptr_t x) {
+ return x;
+}
+
+static void* FfiNativeResolver(const char* name) {
+ if (strcmp(name, "ReturnIntPtr") == 0) {
+ return reinterpret_cast<void*>(ReturnIntPtr);
+ }
+ if (strcmp(name, "IsThreadInGenerated") == 0) {
+ return reinterpret_cast<void*>(IsThreadInGenerated);
+ }
+ // This should be unreachable in tests.
+ ENSURE(false);
+}
+
+DART_EXPORT void SetFfiNativeResolverForTest(Dart_Handle url) {
+ Dart_Handle library = Dart_LookupLibrary(url);
+ ENSURE(!Dart_IsError(library));
+ Dart_Handle result = Dart_SetFfiNativeResolver(library, &FfiNativeResolver);
+ ENSURE(!Dart_IsError(result));
+}
+
} // namespace dart
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index 9610153..a288a79 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -762,6 +762,7 @@
Dart_Isolate isolate = NULL;
+ IsolateData* isolate_data = nullptr;
#if !defined(DART_PRECOMPILED_RUNTIME)
if (!isolate_run_app_snapshot && (isolate_snapshot_data == NULL)) {
const uint8_t* platform_kernel_buffer = NULL;
@@ -783,18 +784,18 @@
// TODO(sivachandra): When the platform program is unavailable, check if
// application kernel binary is self contained or an incremental binary.
// Isolate should be created only if it is a self contained kernel binary.
- auto isolate_data = new IsolateData(isolate_group_data);
+ isolate_data = new IsolateData(isolate_group_data);
isolate = Dart_CreateIsolateGroupFromKernel(
script_uri, name, platform_kernel_buffer, platform_kernel_buffer_size,
flags, isolate_group_data, isolate_data, error);
} else {
- auto isolate_data = new IsolateData(isolate_group_data);
+ isolate_data = new IsolateData(isolate_group_data);
isolate = Dart_CreateIsolateGroup(script_uri, name, isolate_snapshot_data,
isolate_snapshot_instructions, flags,
isolate_group_data, isolate_data, error);
}
#else
- auto isolate_data = new IsolateData(isolate_group_data);
+ isolate_data = new IsolateData(isolate_group_data);
isolate = Dart_CreateIsolateGroup(script_uri, name, isolate_snapshot_data,
isolate_snapshot_instructions, flags,
isolate_group_data, isolate_data, error);
@@ -802,6 +803,7 @@
Dart_Isolate created_isolate = NULL;
if (isolate == NULL) {
+ delete isolate_data;
delete isolate_group_data;
} else {
created_isolate = IsolateSetupHelper(
@@ -932,6 +934,7 @@
int exit_code = 0;
Dart_IsolateFlags flags;
Dart_IsolateFlagsInitialize(&flags);
+ flags.is_system_isolate = Options::mark_main_isolate_as_system_isolate();
Dart_Isolate isolate = CreateIsolateGroupAndSetupHelper(
/* is_main_isolate */ true, script_name, "main",
diff --git a/runtime/bin/main_options.h b/runtime/bin/main_options.h
index 8f9736d..66e6fde 100644
--- a/runtime/bin/main_options.h
+++ b/runtime/bin/main_options.h
@@ -46,7 +46,8 @@
V(disable_dart_dev, disable_dart_dev) \
V(long_ssl_cert_evaluation, long_ssl_cert_evaluation) \
V(bypass_trusting_system_roots, bypass_trusting_system_roots) \
- V(delayed_filewatch_callback, delayed_filewatch_callback)
+ V(delayed_filewatch_callback, delayed_filewatch_callback) \
+ V(mark_main_isolate_as_system_isolate, mark_main_isolate_as_system_isolate)
// Boolean flags that have a short form.
#define SHORT_BOOL_OPTIONS_LIST(V) \
diff --git a/runtime/bin/platform.cc b/runtime/bin/platform.cc
index 1b04cfc..3f9ff26 100644
--- a/runtime/bin/platform.cc
+++ b/runtime/bin/platform.cc
@@ -12,6 +12,8 @@
namespace dart {
namespace bin {
+AcqRelAtomic<const char*> Platform::resolved_executable_name_ = nullptr;
+
void FUNCTION_NAME(Platform_NumberOfProcessors)(Dart_NativeArguments args) {
Dart_SetReturnValue(args, Dart_NewInteger(Platform::NumberOfProcessors()));
}
diff --git a/runtime/bin/platform.h b/runtime/bin/platform.h
index bf2d6b1..a34db67 100644
--- a/runtime/bin/platform.h
+++ b/runtime/bin/platform.h
@@ -6,6 +6,8 @@
#define RUNTIME_BIN_PLATFORM_H_
#include "bin/builtin.h"
+
+#include "platform/atomic.h"
#include "platform/globals.h"
#include "platform/utils.h"
@@ -83,14 +85,19 @@
}
static const char* GetExecutableName();
static const char* GetResolvedExecutableName() {
- if (resolved_executable_name_ == NULL) {
+ if (resolved_executable_name_.load() == nullptr) {
// Try to resolve the executable path using platform specific APIs.
const char* resolved_name = Platform::ResolveExecutablePath();
- if (resolved_name != NULL) {
- resolved_executable_name_ = Utils::StrDup(resolved_name);
+ if (resolved_name != nullptr) {
+ char* resolved_name_copy = Utils::StrDup(resolved_name);
+ const char* expect_old_is_null = nullptr;
+ if (!resolved_executable_name_.compare_exchange_strong(
+ expect_old_is_null, resolved_name_copy)) {
+ free(resolved_name_copy);
+ }
}
}
- return resolved_executable_name_;
+ return resolved_executable_name_.load();
}
// Stores and gets the flags passed to the executable.
@@ -108,8 +115,12 @@
private:
// The path to the executable.
static const char* executable_name_;
+
// The path to the resolved executable.
- static char* resolved_executable_name_;
+ //
+ // We use require-release semantics to ensure initializing stores to the
+ // string are visible when the string becomes visible.
+ static AcqRelAtomic<const char*> resolved_executable_name_;
static int script_index_;
static char** argv_; // VM flags are argv_[1 ... script_index_ - 1]
diff --git a/runtime/bin/platform_android.cc b/runtime/bin/platform_android.cc
index 6e5a34a..a9a5cda 100644
--- a/runtime/bin/platform_android.cc
+++ b/runtime/bin/platform_android.cc
@@ -22,7 +22,6 @@
namespace bin {
const char* Platform::executable_name_ = NULL;
-char* Platform::resolved_executable_name_ = NULL;
int Platform::script_index_ = 1;
char** Platform::argv_ = NULL;
diff --git a/runtime/bin/platform_fuchsia.cc b/runtime/bin/platform_fuchsia.cc
index 5c23480..47c1907 100644
--- a/runtime/bin/platform_fuchsia.cc
+++ b/runtime/bin/platform_fuchsia.cc
@@ -23,7 +23,6 @@
namespace bin {
const char* Platform::executable_name_ = NULL;
-char* Platform::resolved_executable_name_ = NULL;
int Platform::script_index_ = 1;
char** Platform::argv_ = NULL;
diff --git a/runtime/bin/platform_linux.cc b/runtime/bin/platform_linux.cc
index d9443bb..adbfac1 100644
--- a/runtime/bin/platform_linux.cc
+++ b/runtime/bin/platform_linux.cc
@@ -21,7 +21,6 @@
namespace bin {
const char* Platform::executable_name_ = NULL;
-char* Platform::resolved_executable_name_ = NULL;
int Platform::script_index_ = 1;
char** Platform::argv_ = NULL;
diff --git a/runtime/bin/platform_macos.cc b/runtime/bin/platform_macos.cc
index 0479776..8083949 100644
--- a/runtime/bin/platform_macos.cc
+++ b/runtime/bin/platform_macos.cc
@@ -29,7 +29,6 @@
namespace bin {
const char* Platform::executable_name_ = NULL;
-char* Platform::resolved_executable_name_ = NULL;
int Platform::script_index_ = 1;
char** Platform::argv_ = NULL;
diff --git a/runtime/bin/platform_win.cc b/runtime/bin/platform_win.cc
index 59e1b74..515a569 100644
--- a/runtime/bin/platform_win.cc
+++ b/runtime/bin/platform_win.cc
@@ -25,7 +25,6 @@
namespace bin {
const char* Platform::executable_name_ = NULL;
-char* Platform::resolved_executable_name_ = NULL;
int Platform::script_index_ = 1;
char** Platform::argv_ = NULL;
diff --git a/runtime/bin/process_android.cc b/runtime/bin/process_android.cc
index 874d99a..16955e9 100644
--- a/runtime/bin/process_android.cc
+++ b/runtime/bin/process_android.cc
@@ -1109,6 +1109,7 @@
}
void ProcessInfoList::Init() {
+ active_processes_ = NULL;
ASSERT(ProcessInfoList::mutex_ == nullptr);
ProcessInfoList::mutex_ = new Mutex();
}
@@ -1120,6 +1121,9 @@
}
void ExitCodeHandler::Init() {
+ running_ = false;
+ process_count_ = 0;
+ terminate_done_ = false;
ASSERT(ExitCodeHandler::monitor_ == nullptr);
ExitCodeHandler::monitor_ = new Monitor();
}
@@ -1136,6 +1140,7 @@
ASSERT(signal_mutex == nullptr);
signal_mutex = new Mutex();
+ signal_handlers = NULL;
ASSERT(Process::global_exit_code_mutex_ == nullptr);
Process::global_exit_code_mutex_ = new Mutex();
diff --git a/runtime/bin/process_fuchsia.cc b/runtime/bin/process_fuchsia.cc
index f87c28c..de4433c 100644
--- a/runtime/bin/process_fuchsia.cc
+++ b/runtime/bin/process_fuchsia.cc
@@ -826,6 +826,7 @@
void Process::ClearSignalHandlerByFd(intptr_t fd, Dart_Port port) {}
void ProcessInfoList::Init() {
+ active_processes_ = NULL;
ASSERT(ProcessInfoList::mutex_ == nullptr);
ProcessInfoList::mutex_ = new Mutex();
}
@@ -837,6 +838,9 @@
}
void ExitCodeHandler::Init() {
+ port_ = ZX_HANDLE_INVALID;
+ running_ = false;
+ terminate_done_ = false;
ASSERT(ExitCodeHandler::monitor_ == nullptr);
ExitCodeHandler::monitor_ = new Monitor();
}
diff --git a/runtime/bin/process_linux.cc b/runtime/bin/process_linux.cc
index c20649e..95a9c86 100644
--- a/runtime/bin/process_linux.cc
+++ b/runtime/bin/process_linux.cc
@@ -1105,6 +1105,7 @@
}
void ProcessInfoList::Init() {
+ active_processes_ = NULL;
ASSERT(ProcessInfoList::mutex_ == nullptr);
ProcessInfoList::mutex_ = new Mutex();
}
@@ -1116,6 +1117,9 @@
}
void ExitCodeHandler::Init() {
+ running_ = false;
+ process_count_ = 0;
+ terminate_done_ = false;
ASSERT(ExitCodeHandler::monitor_ == nullptr);
ExitCodeHandler::monitor_ = new Monitor();
}
@@ -1132,6 +1136,7 @@
ASSERT(signal_mutex == nullptr);
signal_mutex = new Mutex();
+ signal_handlers = NULL;
ASSERT(Process::global_exit_code_mutex_ == nullptr);
Process::global_exit_code_mutex_ = new Mutex();
diff --git a/runtime/bin/process_macos.cc b/runtime/bin/process_macos.cc
index f20c589..6bbbfae 100644
--- a/runtime/bin/process_macos.cc
+++ b/runtime/bin/process_macos.cc
@@ -1141,6 +1141,7 @@
}
void ProcessInfoList::Init() {
+ active_processes_ = NULL;
ASSERT(ProcessInfoList::mutex_ == nullptr);
ProcessInfoList::mutex_ = new Mutex();
}
@@ -1152,6 +1153,9 @@
}
void ExitCodeHandler::Init() {
+ running_ = false;
+ process_count_ = 0;
+ terminate_done_ = false;
ASSERT(ExitCodeHandler::monitor_ == nullptr);
ExitCodeHandler::monitor_ = new Monitor();
}
@@ -1168,6 +1172,7 @@
ASSERT(signal_mutex == nullptr);
signal_mutex = new Mutex();
+ signal_handlers = NULL;
ASSERT(Process::global_exit_code_mutex_ == nullptr);
Process::global_exit_code_mutex_ = new Mutex();
diff --git a/runtime/bin/process_win.cc b/runtime/bin/process_win.cc
index 1e3a02c..c34b003 100644
--- a/runtime/bin/process_win.cc
+++ b/runtime/bin/process_win.cc
@@ -1096,6 +1096,7 @@
}
void ProcessInfoList::Init() {
+ active_processes_ = nullptr;
ASSERT(ProcessInfoList::mutex_ == nullptr);
ProcessInfoList::mutex_ = new Mutex();
}
@@ -1109,11 +1110,13 @@
void Process::Init() {
ProcessInfoList::Init();
+ signal_handlers = NULL;
ASSERT(signal_mutex == nullptr);
signal_mutex = new Mutex();
ASSERT(initialized_mutex == nullptr);
initialized_mutex = new Mutex();
+ load_attempted = false;
ASSERT(Process::global_exit_code_mutex_ == nullptr);
Process::global_exit_code_mutex_ = new Mutex();
diff --git a/runtime/bin/security_context_macos.cc b/runtime/bin/security_context_macos.cc
index 410a33b..357173d 100644
--- a/runtime/bin/security_context_macos.cc
+++ b/runtime/bin/security_context_macos.cc
@@ -162,15 +162,13 @@
ScopedCFMutableArrayRef trusted_certs(CFArrayCreateMutable(NULL, 0, NULL));
ASSERT(store != NULL);
- if (store->objs != NULL) {
- for (uintptr_t i = 0; i < sk_X509_OBJECT_num(store->objs); ++i) {
- X509* ca = sk_X509_OBJECT_value(store->objs, i)->data.x509;
- ScopedSecCertificateRef cert(CreateSecCertificateFromX509(ca));
- if (cert == NULL) {
- return ssl_verify_invalid;
- }
- CFArrayAppendValue(trusted_certs.get(), cert.release());
+ for (const X509_OBJECT* obj : X509_STORE_get0_objects(store)) {
+ X509* ca = X509_OBJECT_get0_X509(obj);
+ ScopedSecCertificateRef cert(CreateSecCertificateFromX509(ca));
+ if (cert == NULL) {
+ return ssl_verify_invalid;
}
+ CFArrayAppendValue(trusted_certs.get(), cert.release());
}
// Generate a policy for validating chains for SSL.
diff --git a/runtime/bin/socket.cc b/runtime/bin/socket.cc
index ec52dad..1f39427c 100644
--- a/runtime/bin/socket.cc
+++ b/runtime/bin/socket.cc
@@ -130,13 +130,13 @@
// created the socket. Feed same fd and store it into native field
// of dart socket_object. Sockets here will share same fd but contain a
// different port() through EventHandler_SendData.
- Socket* socketfd = new Socket(os_socket->fd);
- os_socket->ref_count++;
+ Socket* socketfd = new Socket(os_socket_same_addr->fd);
+ os_socket_same_addr->ref_count++;
// We set as a side-effect the file descriptor on the dart
// socket_object.
Socket::ReuseSocketIdNativeField(socket_object, socketfd,
Socket::kFinalizerListening);
- InsertByFd(socketfd, os_socket);
+ InsertByFd(socketfd, os_socket_same_addr);
return Dart_True();
}
}
@@ -234,13 +234,13 @@
// created the socket. Feed the same fd and store it into the native
// field of dart socket_object. Sockets here will share same fd but
// contain a different port() through EventHandler_SendData.
- Socket* socketfd = new Socket(os_socket->fd);
- os_socket->ref_count++;
+ Socket* socketfd = new Socket(os_socket_same_addr->fd);
+ os_socket_same_addr->ref_count++;
// We set as a side-effect the file descriptor on the dart
// socket_object.
Socket::ReuseSocketIdNativeField(socket_object, socketfd,
Socket::kFinalizerListening);
- InsertByFd(socketfd, os_socket);
+ InsertByFd(socketfd, os_socket_same_addr);
return Dart_True();
}
}
diff --git a/runtime/docs/gc.md b/runtime/docs/gc.md
index 7857b3d..1daea96 100644
--- a/runtime/docs/gc.md
+++ b/runtime/docs/gc.md
@@ -6,7 +6,7 @@
Object pointers refer either to immediate objects or heap objects, distinguished by a tag in the low bits of the pointer. The Dart VM has only one kind of immediate object, Smis (small integers), whose pointers have a tag of 0. Heap objects have a pointer tag of 1. The upper bits of a Smi pointer are its value, and the upper bits of a heap object pointer are the most significant bits of its address (the least significant bit is always 0 because heap objects always have greater than 2-byte alignment).
-A tag of 0 allows many operations to be performed on Smis without untagging and retagging. It also allows hiding aligned addresses to the C heap from the GC.
+A tag of 0 allows many operations to be performed on Smis without untagging and retagging.
A tag of 1 has no penalty on heap object access because removing the tag can be folded into the offset used by load and store instructions.
diff --git a/runtime/include/dart_tools_api.h b/runtime/include/dart_tools_api.h
index 65d35ce..7d40798 100644
--- a/runtime/include/dart_tools_api.h
+++ b/runtime/include/dart_tools_api.h
@@ -371,6 +371,20 @@
*/
DART_EXPORT int64_t Dart_TimelineGetMicros();
+/**
+ * Returns a raw timestamp in from the monotonic clock.
+ *
+ * \return A raw timestamp from the monotonic clock.
+ */
+DART_EXPORT int64_t Dart_TimelineGetTicks();
+
+/**
+ * Returns the frequency of the monotonic clock.
+ *
+ * \return The frequency of the monotonic clock.
+ */
+DART_EXPORT int64_t Dart_TimelineGetTicksFrequency();
+
/** Timeline stream for Dart API calls */
#define DART_TIMELINE_STREAM_API (1 << 0)
/** Timeline stream for compiler events */
diff --git a/runtime/lib/function.cc b/runtime/lib/function.cc
index 748e056..53ff1e6 100644
--- a/runtime/lib/function.cc
+++ b/runtime/lib/function.cc
@@ -30,42 +30,52 @@
return result.ptr();
}
+static bool ClosureEqualsHelper(Zone* zone,
+ const Closure& receiver,
+ const Object& other) {
+ if (receiver.ptr() == other.ptr()) {
+ return true;
+ }
+ if (!other.IsClosure()) {
+ return false;
+ }
+ const auto& other_closure = Closure::Cast(other);
+ // Check that the delayed type argument vectors match.
+ if (receiver.delayed_type_arguments() !=
+ other_closure.delayed_type_arguments()) {
+ // Mismatches should only happen when a generic function is involved.
+ ASSERT(Function::Handle(receiver.function()).IsGeneric() ||
+ Function::Handle(other_closure.function()).IsGeneric());
+ return false;
+ }
+ // Closures that are not implicit instance closures are unique.
+ const auto& func_a = Function::Handle(zone, receiver.function());
+ if (!func_a.IsImplicitInstanceClosureFunction()) {
+ return false;
+ }
+ const auto& func_b = Function::Handle(zone, other_closure.function());
+ if (!func_b.IsImplicitInstanceClosureFunction()) {
+ return false;
+ }
+ // If the closure functions are not the same, check the function's name and
+ // owner, as multiple function objects could exist for the same function due
+ // to hot reload.
+ if (func_a.ptr() != func_b.ptr() &&
+ (func_a.name() != func_b.name() || func_a.Owner() != func_b.Owner())) {
+ return false;
+ }
+ // Check that the both receiver instances are the same.
+ const Context& context_a = Context::Handle(zone, receiver.context());
+ const Context& context_b = Context::Handle(zone, other_closure.context());
+ return context_a.At(0) == context_b.At(0);
+}
+
DEFINE_NATIVE_ENTRY(Closure_equals, 0, 2) {
const Closure& receiver =
Closure::CheckedHandle(zone, arguments->NativeArgAt(0));
GET_NATIVE_ARGUMENT(Instance, other, arguments->NativeArgAt(1));
ASSERT(!other.IsNull());
- // For implicit instance closures compare receiver instance and function's
- // name and owner (multiple function objects could exist for the same
- // function due to hot reload).
- // Objects of other closure kinds are unique, so use identity comparison.
- if (receiver.ptr() == other.ptr()) {
- return Bool::True().ptr();
- }
- if (other.IsClosure()) {
- const Function& func_a = Function::Handle(zone, receiver.function());
- if (func_a.IsImplicitInstanceClosureFunction()) {
- const Closure& other_closure = Closure::Cast(other);
- const Function& func_b = Function::Handle(zone, other_closure.function());
- if (func_b.IsImplicitInstanceClosureFunction()) {
- const Context& context_a = Context::Handle(zone, receiver.context());
- const Context& context_b =
- Context::Handle(zone, other_closure.context());
- ObjectPtr receiver_a = context_a.At(0);
- ObjectPtr receiver_b = context_b.At(0);
- if ((receiver_a == receiver_b) &&
- (!func_a.IsGeneric() ||
- receiver.delayed_type_arguments() ==
- other_closure.delayed_type_arguments()) &&
- ((func_a.ptr() == func_b.ptr()) ||
- ((func_a.name() == func_b.name()) &&
- (func_a.Owner() == func_b.Owner())))) {
- return Bool::True().ptr();
- }
- }
- }
- }
- return Bool::False().ptr();
+ return Bool::Get(ClosureEqualsHelper(zone, receiver, other)).ptr();
}
DEFINE_NATIVE_ENTRY(Closure_computeHash, 0, 1) {
diff --git a/runtime/lib/isolate.cc b/runtime/lib/isolate.cc
index 922ad2b..0b72f7f 100644
--- a/runtime/lib/isolate.cc
+++ b/runtime/lib/isolate.cc
@@ -19,7 +19,9 @@
#include "vm/lockers.h"
#include "vm/longjump.h"
#include "vm/message_handler.h"
+#include "vm/message_snapshot.h"
#include "vm/object.h"
+#include "vm/object_graph_copy.h"
#include "vm/object_store.h"
#include "vm/port.h"
#include "vm/resolver.h"
@@ -111,10 +113,22 @@
PortMap::PostMessage(
Message::New(destination_port_id, obj.ptr(), Message::kNormalPriority));
} else {
- MessageWriter writer(can_send_any_object);
- // TODO(turnidge): Throw an exception when the return value is false?
- PortMap::PostMessage(writer.WriteMessage(obj, destination_port_id,
- Message::kNormalPriority));
+ const bool same_group = FLAG_enable_isolate_groups &&
+ PortMap::IsReceiverInThisIsolateGroup(
+ destination_port_id, isolate->group());
+ if (same_group) {
+ const auto& copy = Object::Handle(CopyMutableObjectGraph(obj));
+ auto handle = isolate->group()->api_state()->AllocatePersistentHandle();
+ handle->set_ptr(copy.ptr());
+ std::unique_ptr<Message> message(
+ new Message(destination_port_id, handle, Message::kNormalPriority));
+ PortMap::PostMessage(std::move(message));
+ } else {
+ // TODO(turnidge): Throw an exception when the return value is false?
+ PortMap::PostMessage(WriteMessage(can_send_any_object, obj,
+ destination_port_id,
+ Message::kNormalPriority));
+ }
}
return Object::null();
}
@@ -559,8 +573,7 @@
if (message->IsRaw()) {
return Instance::RawCast(message->raw_obj());
} else {
- MessageSnapshotReader reader(message, thread);
- const Object& obj = Object::Handle(zone, reader.ReadObject());
+ const Object& obj = Object::Handle(zone, ReadMessage(thread, message));
ASSERT(!obj.IsError());
return Instance::RawCast(obj.ptr());
}
@@ -601,7 +614,7 @@
ASSERT(name != nullptr);
auto group = state_->isolate_group();
- if (!IsolateGroup::AreIsolateGroupsEnabled() || group == nullptr) {
+ if (!FLAG_enable_isolate_groups || group == nullptr) {
RunHeavyweight(name);
} else {
RunLightweight(name);
@@ -621,6 +634,7 @@
// Make a copy of the state's isolate flags and hand it to the callback.
Dart_IsolateFlags api_flags = *(state_->isolate_flags());
+ api_flags.is_system_isolate = false;
Dart_Isolate isolate = (create_group_callback)(
state_->script_url(), name, nullptr, state_->package_config(),
&api_flags, parent_isolate_->init_callback_data(), &error);
@@ -778,10 +792,10 @@
isolate->message_handler()->increment_paused();
}
{
- MessageWriter writer(/*can_send_any_object=*/false);
// If parent isolate died, we ignore the fact that we cannot notify it.
- PortMap::PostMessage(writer.WriteMessage(message, state_->parent_port(),
- Message::kNormalPriority));
+ PortMap::PostMessage(WriteMessage(/* can_send_any_object */ false,
+ message, state_->parent_port(),
+ Message::kNormalPriority));
}
return true;
@@ -852,9 +866,9 @@
// serializable this will throw an exception.
SerializedObjectBuffer message_buffer;
{
- MessageWriter writer(/* can_send_any_object = */ true);
- message_buffer.set_message(writer.WriteMessage(
- message, ILLEGAL_PORT, Message::kNormalPriority));
+ message_buffer.set_message(WriteMessage(
+ /* can_send_any_object */ true, message, ILLEGAL_PORT,
+ Message::kNormalPriority));
}
const char* utf8_package_config =
@@ -937,14 +951,14 @@
SerializedObjectBuffer arguments_buffer;
SerializedObjectBuffer message_buffer;
{
- MessageWriter writer(/* can_send_any_object = */ false);
- arguments_buffer.set_message(
- writer.WriteMessage(args, ILLEGAL_PORT, Message::kNormalPriority));
+ arguments_buffer.set_message(WriteMessage(/* can_send_any_object */ false,
+ args, ILLEGAL_PORT,
+ Message::kNormalPriority));
}
{
- MessageWriter writer(/* can_send_any_object = */ false);
- message_buffer.set_message(
- writer.WriteMessage(message, ILLEGAL_PORT, Message::kNormalPriority));
+ message_buffer.set_message(WriteMessage(/* can_send_any_object */ false,
+ message, ILLEGAL_PORT,
+ Message::kNormalPriority));
}
// Canonicalize the uri with respect to the current isolate.
@@ -1017,9 +1031,8 @@
// Ensure message writer (and it's resources, e.g. forwarding tables) are
// cleaned up before handling interrupts.
{
- MessageWriter writer(false);
- PortMap::PostMessage(
- writer.WriteMessage(msg, port.Id(), Message::kOOBPriority));
+ PortMap::PostMessage(WriteMessage(/* can_send_any_object */ false, msg,
+ port.Id(), Message::kOOBPriority));
}
// Drain interrupts before running so any IMMEDIATE operations on the current
diff --git a/runtime/lib/object.cc b/runtime/lib/object.cc
index 129caeb..10fc93a 100644
--- a/runtime/lib/object.cc
+++ b/runtime/lib/object.cc
@@ -6,6 +6,7 @@
#include "lib/invocation_mirror.h"
#include "vm/code_patcher.h"
+#include "vm/dart_entry.h"
#include "vm/exceptions.h"
#include "vm/heap/heap.h"
#include "vm/native_entry.h"
@@ -91,57 +92,56 @@
return instance.GetType(Heap::kNew);
}
-DEFINE_NATIVE_ENTRY(Object_haveSameRuntimeType, 0, 2) {
- const Instance& left =
- Instance::CheckedHandle(zone, arguments->NativeArgAt(0));
- const Instance& right =
- Instance::CheckedHandle(zone, arguments->NativeArgAt(1));
-
+static bool HaveSameRuntimeTypeHelper(Zone* zone,
+ const Instance& left,
+ const Instance& right) {
const intptr_t left_cid = left.GetClassId();
const intptr_t right_cid = right.GetClassId();
if (left_cid != right_cid) {
if (IsIntegerClassId(left_cid)) {
- return Bool::Get(IsIntegerClassId(right_cid)).ptr();
- } else if (IsStringClassId(left_cid)) {
- return Bool::Get(IsStringClassId(right_cid)).ptr();
- } else if (IsTypeClassId(left_cid)) {
- return Bool::Get(IsTypeClassId(right_cid)).ptr();
- } else {
- return Bool::False().ptr();
+ return IsIntegerClassId(right_cid);
}
+ if (IsStringClassId(left_cid)) {
+ return IsStringClassId(right_cid);
+ }
+ if (IsTypeClassId(left_cid)) {
+ return IsTypeClassId(right_cid);
+ }
+ return false;
}
- const Class& cls = Class::Handle(left.clazz());
- if (cls.IsClosureClass()) {
- const Function& left_function =
- Function::Handle(zone, Closure::Cast(left).function());
- const Function& right_function =
- Function::Handle(zone, Closure::Cast(right).function());
- if (left_function.signature() == right_function.signature() &&
- Closure::Cast(left).function_type_arguments() ==
- Closure::Cast(right).function_type_arguments() &&
- Closure::Cast(left).delayed_type_arguments() ==
- Closure::Cast(right).delayed_type_arguments() &&
- Closure::Cast(left).instantiator_type_arguments() ==
- Closure::Cast(right).instantiator_type_arguments()) {
- return Bool::True().ptr();
+ if (left_cid == kClosureCid) {
+ const auto& left_closure = Closure::Cast(left);
+ const auto& right_closure = Closure::Cast(right);
+ // If all the components that make up the instantiated signature are equal,
+ // then no need to instantiate.
+ if (left_closure.function_type_arguments() ==
+ right_closure.function_type_arguments() &&
+ left_closure.delayed_type_arguments() ==
+ right_closure.delayed_type_arguments() &&
+ left_closure.instantiator_type_arguments() ==
+ right_closure.instantiator_type_arguments()) {
+ const auto& left_fun = Function::Handle(zone, left_closure.function());
+ const auto& right_fun = Function::Handle(zone, right_closure.function());
+ if (left_fun.signature() == right_fun.signature()) {
+ return true;
+ }
}
const AbstractType& left_type =
AbstractType::Handle(zone, left.GetType(Heap::kNew));
const AbstractType& right_type =
AbstractType::Handle(zone, right.GetType(Heap::kNew));
- return Bool::Get(
- left_type.IsEquivalent(right_type, TypeEquality::kSyntactical))
- .ptr();
+ return left_type.IsEquivalent(right_type, TypeEquality::kSyntactical);
}
+ const Class& cls = Class::Handle(zone, left.clazz());
if (!cls.IsGeneric()) {
- return Bool::True().ptr();
+ return true;
}
if (left.GetTypeArguments() == right.GetTypeArguments()) {
- return Bool::True().ptr();
+ return true;
}
const TypeArguments& left_type_arguments =
TypeArguments::Handle(zone, left.GetTypeArguments());
@@ -149,10 +149,17 @@
TypeArguments::Handle(zone, right.GetTypeArguments());
const intptr_t num_type_args = cls.NumTypeArguments();
const intptr_t num_type_params = cls.NumTypeParameters();
- return Bool::Get(left_type_arguments.IsSubvectorEquivalent(
- right_type_arguments, num_type_args - num_type_params,
- num_type_params, TypeEquality::kSyntactical))
- .ptr();
+ return left_type_arguments.IsSubvectorEquivalent(
+ right_type_arguments, num_type_args - num_type_params, num_type_params,
+ TypeEquality::kSyntactical);
+}
+
+DEFINE_NATIVE_ENTRY(Object_haveSameRuntimeType, 0, 2) {
+ const Instance& left =
+ Instance::CheckedHandle(zone, arguments->NativeArgAt(0));
+ const Instance& right =
+ Instance::CheckedHandle(zone, arguments->NativeArgAt(1));
+ return Bool::Get(HaveSameRuntimeTypeHelper(zone, left, right)).ptr();
}
DEFINE_NATIVE_ENTRY(Object_instanceOf, 0, 4) {
@@ -308,6 +315,11 @@
return Object::null();
}
+DEFINE_NATIVE_ENTRY(Internal_deoptimizeFunctionsOnStack, 0, 0) {
+ DeoptimizeFunctionsOnStack();
+ return Object::null();
+}
+
static bool ExtractInterfaceTypeArgs(Zone* zone,
const Class& instance_cls,
const TypeArguments& instance_type_args,
@@ -457,6 +469,7 @@
const Closure& closure =
Closure::CheckedHandle(zone, arguments->NativeArgAt(0));
const Function& target = Function::Handle(zone, closure.function());
+ ASSERT(target.IsGeneric()); // No need to check bounds for non-generics.
const TypeParameters& type_params =
TypeParameters::Handle(zone, target.type_parameters());
if (type_params.IsNull() || type_params.AllDynamicBounds()) {
diff --git a/runtime/lib/vmservice.cc b/runtime/lib/vmservice.cc
index 44d6148..51ff5ea 100644
--- a/runtime/lib/vmservice.cc
+++ b/runtime/lib/vmservice.cc
@@ -11,6 +11,7 @@
#include "vm/kernel_isolate.h"
#include "vm/message.h"
#include "vm/message_handler.h"
+#include "vm/message_snapshot.h"
#include "vm/native_entry.h"
#include "vm/object.h"
#include "vm/port.h"
@@ -59,10 +60,10 @@
Smi::Handle(thread->zone(), Smi::New(Message::kServiceOOBMsg)));
// Serialize message.
- MessageWriter writer(false);
// TODO(turnidge): Throw an exception when the return value is false?
- bool result = PortMap::PostMessage(
- writer.WriteMessage(message, sp.Id(), Message::kOOBPriority));
+ bool result = PortMap::PostMessage(WriteMessage(
+ /* can_send_any_object */ false, message, sp.Id(),
+ Message::kOOBPriority));
return Bool::Get(result).ptr();
#else
return Object::null();
diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart
index f3a26e7..7d83c71 100644
--- a/runtime/observatory/lib/src/service/object.dart
+++ b/runtime/observatory/lib/src/service/object.dart
@@ -4774,8 +4774,8 @@
for (var i = 0; i < list.length; i++) {
var v = list[i];
- if ((v is Map) && _isServiceMap(v)) {
- list[i] = owner!.getFromMap(v);
+ if ((v is Map) && owner != null && _isServiceMap(v)) {
+ list[i] = owner.getFromMap(v);
} else if (v is List) {
_upgradeList(v, owner);
} else if (v is Map) {
diff --git a/runtime/observatory/tests/service/break_on_function_child_isolate_test.dart b/runtime/observatory/tests/service/break_on_function_child_isolate_test.dart
index bd471ac..3922aa6 100644
--- a/runtime/observatory/tests/service/break_on_function_child_isolate_test.dart
+++ b/runtime/observatory/tests/service/break_on_function_child_isolate_test.dart
@@ -1,7 +1,7 @@
// 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.
-// VMOptions=--verbose_debug --enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--verbose_debug --enable-isolate-groups
import 'break_on_function_many_child_isolates_test.dart';
diff --git a/runtime/observatory/tests/service/break_on_function_many_child_isolates_test.dart b/runtime/observatory/tests/service/break_on_function_many_child_isolates_test.dart
index 916e6f9..b0e75a8 100644
--- a/runtime/observatory/tests/service/break_on_function_many_child_isolates_test.dart
+++ b/runtime/observatory/tests/service/break_on_function_many_child_isolates_test.dart
@@ -1,7 +1,7 @@
// 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.
-// VMOptions=--verbose_debug --enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--verbose_debug --enable-isolate-groups
//
// Tests breakpoint pausing and resuming with many isolates running and pausing
// simultaneously.
diff --git a/runtime/observatory/tests/service/get_object_rpc_test.dart b/runtime/observatory/tests/service/get_object_rpc_test.dart
index 9a3eab8..d553138 100644
--- a/runtime/observatory/tests/service/get_object_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_object_rpc_test.dart
@@ -14,15 +14,20 @@
class _DummyClass {
static var dummyVar = 11;
final List<String> dummyList = new List<String>.filled(20, '');
- void dummyFunction() {}
+ void dummyFunction(int a, [bool b = false]) {}
+ void dummyGenericFunction<K, V>(K a, {required V param}) {}
}
class _DummySubClass extends _DummyClass {}
+class _DummyGenericSubClass<T> extends _DummyClass {}
+
void warmup() {
// Silence analyzer.
new _DummySubClass();
- new _DummyClass().dummyFunction();
+ new _DummyGenericSubClass<Object>();
+ new _DummyClass().dummyFunction(0);
+ new _DummyClass().dummyGenericFunction<Object, dynamic>(0, param: 0);
}
@pragma("vm:entry-point")
@@ -43,6 +48,9 @@
@pragma("vm:entry-point")
getDummyClass() => new _DummyClass();
+@pragma("vm:entry-point")
+getDummyGenericSubClass() => new _DummyGenericSubClass<Object>();
+
invoke(Isolate isolate, String selector) async {
Map params = {
'targetId': isolate.rootLibrary.id,
@@ -766,6 +774,7 @@
expect(result['_finalized'], equals(true));
expect(result['_implemented'], equals(false));
expect(result['_patch'], equals(false));
+ expect(result['typeParameters'], isNull);
expect(result['library']['type'], equals('@Library'));
expect(result['location']['type'], equals('SourceLocation'));
expect(result['super']['type'], equals('@Class'));
@@ -778,6 +787,30 @@
expect(result['subclasses'][0]['type'], equals('@Class'));
},
+ // generic class
+ (Isolate isolate) async {
+ // Call eval to get a class id.
+ var evalResult = await invoke(isolate, 'getDummyGenericSubClass');
+ var params = {
+ 'objectId': evalResult['class']['id'],
+ };
+ var result = await isolate.invokeRpcNoUpgrade('getObject', params);
+ expect(result['type'], equals('Class'));
+ expect(result['id'], startsWith('classes/'));
+ expect(result['name'], equals('_DummyGenericSubClass'));
+ expect(result['_vmName'], startsWith('_DummyGenericSubClass@'));
+ expect(result['abstract'], equals(false));
+ expect(result['const'], equals(false));
+ expect(result['_finalized'], equals(true));
+ expect(result['_implemented'], equals(false));
+ expect(result['_patch'], equals(false));
+ expect(result['typeParameters'].length, equals(1));
+ expect(result['library']['type'], equals('@Library'));
+ expect(result['location']['type'], equals('SourceLocation'));
+ expect(result['super']['type'], equals('@Class'));
+ expect(result['interfaces'].length, isZero);
+ },
+
// invalid class.
(Isolate isolate) async {
var params = {
@@ -851,6 +884,52 @@
expect(result['_kind'], equals('RegularFunction'));
expect(result['static'], equals(false));
expect(result['const'], equals(false));
+ expect(result['implicit'], equals(false));
+ expect(result['signature']['typeParameters'], isNull);
+ expect(result['signature']['returnType'], isNotNull);
+ expect(result['signature']['parameters'].length, 3);
+ expect(result['signature']['parameters'][1]['parameterType']['name'],
+ equals('int'));
+ expect(result['signature']['parameters'][1]['fixed'], isTrue);
+ expect(result['signature']['parameters'][2]['parameterType']['name'],
+ equals('bool'));
+ expect(result['signature']['parameters'][2]['fixed'], isFalse);
+ expect(result['location']['type'], equals('SourceLocation'));
+ expect(result['code']['type'], equals('@Code'));
+ expect(result['_optimizable'], equals(true));
+ expect(result['_inlinable'], equals(true));
+ expect(result['_usageCounter'], isPositive);
+ expect(result['_optimizedCallSiteCount'], isZero);
+ expect(result['_deoptimizations'], isZero);
+ },
+
+ // generic function.
+ (Isolate isolate) async {
+ // Call eval to get a class id.
+ var evalResult = await invoke(isolate, 'getDummyClass');
+ var id = "${evalResult['class']['id']}/functions/dummyGenericFunction";
+ var params = {
+ 'objectId': id,
+ };
+ var result = await isolate.invokeRpcNoUpgrade('getObject', params);
+ expect(result['type'], equals('Function'));
+ expect(result['id'], equals(id));
+ expect(result['name'], equals('dummyGenericFunction'));
+ expect(result['_kind'], equals('RegularFunction'));
+ expect(result['static'], equals(false));
+ expect(result['const'], equals(false));
+ expect(result['implicit'], equals(false));
+ expect(result['signature']['typeParameters'].length, 2);
+ expect(result['signature']['returnType'], isNotNull);
+ expect(result['signature']['parameters'].length, 3);
+ expect(result['signature']['parameters'][1]['parameterType']['name'],
+ isNotNull);
+ expect(result['signature']['parameters'][1]['fixed'], isTrue);
+ expect(result['signature']['parameters'][2]['parameterType']['name'],
+ isNotNull);
+ expect(result['signature']['parameters'][2]['name'], 'param');
+ expect(result['signature']['parameters'][2]['fixed'], isFalse);
+ expect(result['signature']['parameters'][2]['required'], isTrue);
expect(result['location']['type'], equals('SourceLocation'));
expect(result['code']['type'], equals('@Code'));
expect(result['_optimizable'], equals(true));
diff --git a/runtime/observatory/tests/service/get_version_rpc_test.dart b/runtime/observatory/tests/service/get_version_rpc_test.dart
index 75d1743..6bec5f1 100644
--- a/runtime/observatory/tests/service/get_version_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_version_rpc_test.dart
@@ -12,7 +12,7 @@
final result = await vm.invokeRpcNoUpgrade('getVersion', {});
expect(result['type'], 'Version');
expect(result['major'], 3);
- expect(result['minor'], 48);
+ expect(result['minor'], 50);
expect(result['_privateMajor'], 0);
expect(result['_privateMinor'], 0);
},
diff --git a/runtime/observatory_2/lib/src/service/object.dart b/runtime/observatory_2/lib/src/service/object.dart
index 2baf6d5..14d72c2 100644
--- a/runtime/observatory_2/lib/src/service/object.dart
+++ b/runtime/observatory_2/lib/src/service/object.dart
@@ -4784,7 +4784,7 @@
for (var i = 0; i < list.length; i++) {
var v = list[i];
- if ((v is Map) && _isServiceMap(v)) {
+ if ((v is Map) && owner != null && _isServiceMap(v)) {
list[i] = owner.getFromMap(v);
} else if (v is List) {
_upgradeList(v, owner);
diff --git a/runtime/observatory_2/tests/service_2/break_on_function_child_isolate_test.dart b/runtime/observatory_2/tests/service_2/break_on_function_child_isolate_test.dart
index bd471ac..3922aa6 100644
--- a/runtime/observatory_2/tests/service_2/break_on_function_child_isolate_test.dart
+++ b/runtime/observatory_2/tests/service_2/break_on_function_child_isolate_test.dart
@@ -1,7 +1,7 @@
// 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.
-// VMOptions=--verbose_debug --enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--verbose_debug --enable-isolate-groups
import 'break_on_function_many_child_isolates_test.dart';
diff --git a/runtime/observatory_2/tests/service_2/break_on_function_many_child_isolates_test.dart b/runtime/observatory_2/tests/service_2/break_on_function_many_child_isolates_test.dart
index b527cb54..e5b6b56 100644
--- a/runtime/observatory_2/tests/service_2/break_on_function_many_child_isolates_test.dart
+++ b/runtime/observatory_2/tests/service_2/break_on_function_many_child_isolates_test.dart
@@ -1,7 +1,7 @@
// 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.
-// VMOptions=--verbose_debug --enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--verbose_debug --enable-isolate-groups
//
// Tests breakpoint pausing and resuming with many isolates running and pausing
// simultaneously.
diff --git a/runtime/observatory_2/tests/service_2/get_object_rpc_test.dart b/runtime/observatory_2/tests/service_2/get_object_rpc_test.dart
index 36b9c61..44912b3 100644
--- a/runtime/observatory_2/tests/service_2/get_object_rpc_test.dart
+++ b/runtime/observatory_2/tests/service_2/get_object_rpc_test.dart
@@ -14,15 +14,20 @@
class _DummyClass {
static var dummyVar = 11;
final List<String> dummyList = new List<String>.filled(20, null);
- void dummyFunction() {}
+ void dummyFunction(int a, [bool b = false]) {}
+ void dummyGenericFunction<K, V>(K a, {V param}) {}
}
class _DummySubClass extends _DummyClass {}
+class _DummyGenericSubClass<T> extends _DummyClass {}
+
void warmup() {
// Silence analyzer.
new _DummySubClass();
- new _DummyClass().dummyFunction();
+ new _DummyGenericSubClass<Object>();
+ new _DummyClass().dummyFunction(0);
+ new _DummyClass().dummyGenericFunction<Object, dynamic>(0, param: 0);
}
@pragma("vm:entry-point")
@@ -43,6 +48,9 @@
@pragma("vm:entry-point")
getDummyClass() => new _DummyClass();
+@pragma("vm:entry-point")
+getDummyGenericSubClass() => new _DummyGenericSubClass<Object>();
+
invoke(Isolate isolate, String selector) async {
Map params = {
'targetId': isolate.rootLibrary.id,
@@ -778,6 +786,30 @@
expect(result['subclasses'][0]['type'], equals('@Class'));
},
+ // generic class
+ (Isolate isolate) async {
+ // Call eval to get a class id.
+ var evalResult = await invoke(isolate, 'getDummyGenericSubClass');
+ var params = {
+ 'objectId': evalResult['class']['id'],
+ };
+ var result = await isolate.invokeRpcNoUpgrade('getObject', params);
+ expect(result['type'], equals('Class'));
+ expect(result['id'], startsWith('classes/'));
+ expect(result['name'], equals('_DummyGenericSubClass'));
+ expect(result['_vmName'], startsWith('_DummyGenericSubClass@'));
+ expect(result['abstract'], equals(false));
+ expect(result['const'], equals(false));
+ expect(result['_finalized'], equals(true));
+ expect(result['_implemented'], equals(false));
+ expect(result['_patch'], equals(false));
+ expect(result['typeParameters'].length, equals(1));
+ expect(result['library']['type'], equals('@Library'));
+ expect(result['location']['type'], equals('SourceLocation'));
+ expect(result['super']['type'], equals('@Class'));
+ expect(result['interfaces'].length, isZero);
+ },
+
// invalid class.
(Isolate isolate) async {
var params = {
@@ -851,6 +883,52 @@
expect(result['_kind'], equals('RegularFunction'));
expect(result['static'], equals(false));
expect(result['const'], equals(false));
+ expect(result['implicit'], equals(false));
+ expect(result['signature']['typeParameters'], isNull);
+ expect(result['signature']['returnType'], isNotNull);
+ expect(result['signature']['parameters'].length, 3);
+ expect(result['signature']['parameters'][1]['parameterType']['name'],
+ equals('int'));
+ expect(result['signature']['parameters'][1]['fixed'], isTrue);
+ expect(result['signature']['parameters'][2]['parameterType']['name'],
+ equals('bool'));
+ expect(result['signature']['parameters'][2]['fixed'], isFalse);
+ expect(result['location']['type'], equals('SourceLocation'));
+ expect(result['code']['type'], equals('@Code'));
+ expect(result['_optimizable'], equals(true));
+ expect(result['_inlinable'], equals(true));
+ expect(result['_usageCounter'], isPositive);
+ expect(result['_optimizedCallSiteCount'], isZero);
+ expect(result['_deoptimizations'], isZero);
+ },
+
+ // generic function.
+ (Isolate isolate) async {
+ // Call eval to get a class id.
+ var evalResult = await invoke(isolate, 'getDummyClass');
+ var id = "${evalResult['class']['id']}/functions/dummyGenericFunction";
+ var params = {
+ 'objectId': id,
+ };
+ var result = await isolate.invokeRpcNoUpgrade('getObject', params);
+ expect(result['type'], equals('Function'));
+ expect(result['id'], equals(id));
+ expect(result['name'], equals('dummyGenericFunction'));
+ expect(result['_kind'], equals('RegularFunction'));
+ expect(result['static'], equals(false));
+ expect(result['const'], equals(false));
+ expect(result['implicit'], equals(false));
+ expect(result['signature']['typeParameters'].length, 2);
+ expect(result['signature']['returnType'], isNotNull);
+ expect(result['signature']['parameters'].length, 3);
+ expect(result['signature']['parameters'][1]['parameterType']['name'],
+ isNotNull);
+ expect(result['signature']['parameters'][1]['fixed'], isTrue);
+ expect(result['signature']['parameters'][2]['parameterType']['name'],
+ isNotNull);
+ expect(result['signature']['parameters'][2]['name'], 'param');
+ expect(result['signature']['parameters'][2]['fixed'], isFalse);
+ expect(result['signature']['parameters'][2]['required'], isFalse);
expect(result['location']['type'], equals('SourceLocation'));
expect(result['code']['type'], equals('@Code'));
expect(result['_optimizable'], equals(true));
diff --git a/runtime/observatory_2/tests/service_2/get_version_rpc_test.dart b/runtime/observatory_2/tests/service_2/get_version_rpc_test.dart
index 443f8bb..31490bf 100644
--- a/runtime/observatory_2/tests/service_2/get_version_rpc_test.dart
+++ b/runtime/observatory_2/tests/service_2/get_version_rpc_test.dart
@@ -12,7 +12,7 @@
final result = await vm.invokeRpcNoUpgrade('getVersion', {});
expect(result['type'], equals('Version'));
expect(result['major'], equals(3));
- expect(result['minor'], equals(48));
+ expect(result['minor'], equals(50));
expect(result['_privateMajor'], equals(0));
expect(result['_privateMinor'], equals(0));
},
diff --git a/runtime/platform/atomic.h b/runtime/platform/atomic.h
index 98bc900..390aa62 100644
--- a/runtime/platform/atomic.h
+++ b/runtime/platform/atomic.h
@@ -21,9 +21,16 @@
T load(std::memory_order order = std::memory_order_relaxed) const {
return value_.load(order);
}
+ T load(std::memory_order order = std::memory_order_relaxed) const volatile {
+ return value_.load(order);
+ }
void store(T arg, std::memory_order order = std::memory_order_relaxed) {
value_.store(arg, order);
}
+ void store(T arg,
+ std::memory_order order = std::memory_order_relaxed) volatile {
+ value_.store(arg, order);
+ }
T fetch_add(T arg, std::memory_order order = std::memory_order_relaxed) {
return value_.fetch_add(arg, order);
@@ -38,12 +45,22 @@
return value_.fetch_and(arg, order);
}
+ T exchange(T arg, std::memory_order order = std::memory_order_relaxed) {
+ return value_.exchange(arg, order);
+ }
+
bool compare_exchange_weak(
T& expected, // NOLINT
T desired,
std::memory_order order = std::memory_order_relaxed) {
return value_.compare_exchange_weak(expected, desired, order, order);
}
+ bool compare_exchange_weak(
+ T& expected, // NOLINT
+ T desired,
+ std::memory_order order = std::memory_order_relaxed) volatile {
+ return value_.compare_exchange_weak(expected, desired, order, order);
+ }
bool compare_exchange_strong(
T& expected, // NOLINT
T desired,
@@ -63,6 +80,10 @@
}
T operator+=(T arg) { return fetch_add(arg) + arg; }
T operator-=(T arg) { return fetch_sub(arg) - arg; }
+ T& operator++() { return fetch_add(1) + 1; }
+ T& operator--() { return fetch_sub(1) - 1; }
+ T operator++(int) { return fetch_add(1); }
+ T operator--(int) { return fetch_sub(1); }
private:
std::atomic<T> value_;
diff --git a/runtime/platform/globals.h b/runtime/platform/globals.h
index 42edc70..ed20219 100644
--- a/runtime/platform/globals.h
+++ b/runtime/platform/globals.h
@@ -334,6 +334,10 @@
#error Automatic target architecture detection failed.
#endif
+#if defined(TARGET_ARCH_IS_64_BIT) && !defined(DART_COMPRESSED_POINTERS)
+#define HAS_SMI_63_BITS 1
+#endif
+
// Verify that host and target architectures match, we cannot
// have a 64 bit Dart VM generating 32 bit code or vice-versa.
#if defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_ARM64)
diff --git a/runtime/platform/growable_array.h b/runtime/platform/growable_array.h
index c568862..34ad019 100644
--- a/runtime/platform/growable_array.h
+++ b/runtime/platform/growable_array.h
@@ -188,6 +188,10 @@
// The content is uninitialized after calling it.
void SetLength(intptr_t new_length);
+ // The content (if expanded) is uninitialized after calling it.
+ // The backing store (if expanded) will grow with by a power-of-2.
+ void Resize(intptr_t new_length);
+
// Sort the array in place.
inline void Sort(int compare(const T*, const T*));
@@ -211,9 +215,6 @@
T* data_;
Allocator* allocator_; // Used to (re)allocate the array.
- // Used for growing the array.
- void Resize(intptr_t new_length);
-
DISALLOW_COPY_AND_ASSIGN(BaseGrowableArray);
};
diff --git a/runtime/platform/thread_sanitizer.h b/runtime/platform/thread_sanitizer.h
index e8c4fcf..baff130 100644
--- a/runtime/platform/thread_sanitizer.h
+++ b/runtime/platform/thread_sanitizer.h
@@ -15,6 +15,8 @@
#if defined(USING_THREAD_SANITIZER)
#define NO_SANITIZE_THREAD __attribute__((no_sanitize("thread")))
+extern "C" void __tsan_acquire(void* addr);
+extern "C" void __tsan_release(void* addr);
#else
#define NO_SANITIZE_THREAD
#endif
diff --git a/runtime/platform/utils.h b/runtime/platform/utils.h
index a1d6b1b..84366eb 100644
--- a/runtime/platform/utils.h
+++ b/runtime/platform/utils.h
@@ -417,34 +417,26 @@
return ((-0x20000000000000LL <= value) && (value <= 0x20000000000000LL));
}
- static constexpr uword NBitMaskUnsafe(uint32_t n) {
- static_assert((sizeof(uword) * kBitsPerByte) == kBitsPerWord,
- "Unexpected uword size");
- return n == kBitsPerWord ? std::numeric_limits<uword>::max()
- : (static_cast<uword>(1) << n) - 1;
- }
-
// The lowest n bits are 1, the others are 0.
- static uword NBitMask(uint32_t n) {
- ASSERT(n <= kBitsPerWord);
- return NBitMaskUnsafe(n);
- }
-
- static word SignedNBitMask(uint32_t n) {
- uword mask = NBitMask(n);
- return bit_cast<word>(mask);
+ template <typename T = uword>
+ static constexpr T NBitMask(size_t n) {
+ using Unsigned = typename std::make_unsigned<T>::type;
+ constexpr size_t kBitsPerT = sizeof(T) * kBitsPerByte;
+ assert(n <= sizeof(T) * kBitsPerT);
+ return static_cast<T>(n == kBitsPerT ? std::numeric_limits<Unsigned>::max()
+ : (static_cast<Unsigned>(1) << n) - 1);
}
template <typename T = uword>
- static T Bit(uint32_t n) {
+ static constexpr T Bit(size_t n) {
ASSERT(n < sizeof(T) * kBitsPerByte);
T bit = 1;
return bit << n;
}
template <typename T>
- DART_FORCE_INLINE static bool TestBit(T mask, intptr_t position) {
- ASSERT(position < static_cast<intptr_t>(sizeof(T) * kBitsPerByte));
+ static constexpr bool TestBit(T mask, size_t position) {
+ ASSERT(position < sizeof(T) * kBitsPerByte);
return ((mask >> position) & 1) != 0;
}
diff --git a/runtime/tests/concurrency/run_stress_test_shards.dart b/runtime/tests/concurrency/run_stress_test_shards.dart
index 5b3d001..2d31d15 100644
--- a/runtime/tests/concurrency/run_stress_test_shards.dart
+++ b/runtime/tests/concurrency/run_stress_test_shards.dart
@@ -78,14 +78,12 @@
'--disable-dart-dev',
'--no-sound-null-safety',
'--enable-isolate-groups',
- '--experimental-enable-isolate-groups-jit',
'runtime/tests/concurrency/generated_stress_test.dart.jit.dill',
]),
JitTestRunner('out/ReleaseX64', [
'--disable-dart-dev',
'--no-sound-null-safety',
'--enable-isolate-groups',
- '--experimental-enable-isolate-groups-jit',
'--no-inline-alloc',
'--use-slow-path',
'--deoptimize-on-runtime-call-every=3',
@@ -99,7 +97,6 @@
'-Dshards=$tsanShards',
'--no-sound-null-safety',
'--enable-isolate-groups',
- '--experimental-enable-isolate-groups-jit',
'runtime/tests/concurrency/generated_stress_test.dart.jit.dill',
]),
AotTestRunner('out/ReleaseX64', [
diff --git a/runtime/tests/concurrency/stress_test_list.json b/runtime/tests/concurrency/stress_test_list.json
index b8f2ae6..7981ebb 100644
--- a/runtime/tests/concurrency/stress_test_list.json
+++ b/runtime/tests/concurrency/stress_test_list.json
@@ -3061,7 +3061,6 @@
"../../../tests/lib/async/stream_error_test.dart",
"../../../tests/lib/async/stream_event_transformed_test.dart",
"../../../tests/lib/async/stream_from_futures_test.dart",
- "../../../tests/lib/async/stream_from_iterable_test.dart",
"../../../tests/lib/async/stream_iterator_double_cancel_test.dart",
"../../../tests/lib/async/stream_iterator_test.dart",
"../../../tests/lib/async/stream_join_test.dart",
@@ -3260,7 +3259,6 @@
"../../../tests/standalone/io/file_constructor_test.dart",
"../../../tests/standalone/io/file_copy_test.dart",
"../../../tests/standalone/io/file_create_test.dart",
- "../../../tests/standalone/io/file_fuzz_test.dart",
"../../../tests/standalone/io/file_non_ascii_sync_test.dart",
"../../../tests/standalone/io/file_non_ascii_test.dart",
"../../../tests/standalone/io/file_output_stream_test.dart",
@@ -3274,7 +3272,6 @@
"../../../tests/standalone/io/file_system_uri_test.dart",
"../../../tests/standalone/io/file_typed_data_test.dart",
"../../../tests/standalone/io/file_windows_test.dart",
- "../../../tests/standalone/io/file_write_as_test.dart",
"../../../tests/standalone/io/file_write_only_test.dart",
"../../../tests/standalone/io/gzip_format_exception_test.dart",
"../../../tests/standalone/io/http_100_continue_test.dart",
@@ -3371,7 +3368,6 @@
"../../../tests/standalone/io/stdin_has_terminal_test.dart",
"../../../tests/standalone/io/stdout_stderr_terminal_test.dart",
"../../../tests/standalone/io/system_encoding_test.dart",
- "../../../tests/standalone/io/unix_socket_test.dart",
"../../../tests/standalone/io/unknown_host_test.dart",
"../../../tests/standalone/io/uri_platform_test.dart",
"../../../tests/standalone/io/web_socket_compression_test.dart",
@@ -6408,7 +6404,6 @@
"../../../tests/lib_2/async/stream_error_test.dart",
"../../../tests/lib_2/async/stream_event_transformed_test.dart",
"../../../tests/lib_2/async/stream_from_futures_test.dart",
- "../../../tests/lib_2/async/stream_from_iterable_test.dart",
"../../../tests/lib_2/async/stream_iterator_double_cancel_test.dart",
"../../../tests/lib_2/async/stream_iterator_test.dart",
"../../../tests/lib_2/async/stream_join_test.dart",
@@ -6595,7 +6590,6 @@
"../../../tests/standalone_2/io/file_copy_test.dart",
"../../../tests/standalone_2/io/file_create_test.dart",
"../../../tests/standalone_2/io/file_error_test.dart",
- "../../../tests/standalone_2/io/file_fuzz_test.dart",
"../../../tests/standalone_2/io/file_non_ascii_sync_test.dart",
"../../../tests/standalone_2/io/file_non_ascii_test.dart",
"../../../tests/standalone_2/io/file_output_stream_test.dart",
@@ -6609,7 +6603,6 @@
"../../../tests/standalone_2/io/file_system_uri_test.dart",
"../../../tests/standalone_2/io/file_typed_data_test.dart",
"../../../tests/standalone_2/io/file_windows_test.dart",
- "../../../tests/standalone_2/io/file_write_as_test.dart",
"../../../tests/standalone_2/io/file_write_only_test.dart",
"../../../tests/standalone_2/io/gzip_format_exception_test.dart",
"../../../tests/standalone_2/io/http_100_continue_test.dart",
@@ -6705,7 +6698,6 @@
"../../../tests/standalone_2/io/stdin_has_terminal_test.dart",
"../../../tests/standalone_2/io/stdout_stderr_terminal_test.dart",
"../../../tests/standalone_2/io/system_encoding_test.dart",
- "../../../tests/standalone_2/io/unix_socket_test.dart",
"../../../tests/standalone_2/io/unknown_host_test.dart",
"../../../tests/standalone_2/io/uri_platform_test.dart",
"../../../tests/standalone_2/io/web_socket_compression_test.dart",
diff --git a/runtime/tests/vm/dart/deferred_isolate_test.dart b/runtime/tests/vm/dart/deferred_isolate_test.dart
index d056b31..94be755 100644
--- a/runtime/tests/vm/dart/deferred_isolate_test.dart
+++ b/runtime/tests/vm/dart/deferred_isolate_test.dart
@@ -4,7 +4,7 @@
// Verify deferred library status is per-isolate, not per-isolate-group.
-// VMOptions=--enable_isolate_groups --experimental_enable_isolate_groups_jit
+// VMOptions=--enable-isolate-groups
import 'dart:async';
import 'dart:isolate';
diff --git a/runtime/tests/vm/dart/isolates/dart_api_create_lightweight_isolate_test.dart b/runtime/tests/vm/dart/isolates/dart_api_create_lightweight_isolate_test.dart
index 83b7cc5..2fa4962 100644
--- a/runtime/tests/vm/dart/isolates/dart_api_create_lightweight_isolate_test.dart
+++ b/runtime/tests/vm/dart/isolates/dart_api_create_lightweight_isolate_test.dart
@@ -4,7 +4,7 @@
// SharedObjects=ffi_test_functions
// VMOptions=
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit --disable-heap-verification
+// VMOptions=--enable-isolate-groups --disable-heap-verification
import 'dart:async';
import 'dart:ffi';
@@ -14,13 +14,14 @@
import 'package:expect/expect.dart';
import 'package:ffi/ffi.dart';
+import 'test_utils.dart' show isArtificialReloadMode;
import '../../../../../tests/ffi/dylib_utils.dart';
-final bool isAOT = Platform.executable.contains('dart_precompiled_runtime');
final bool isolateGroupsEnabled =
Platform.executableArguments.contains('--enable-isolate-groups');
-final bool isolateGroupsEnabledInJIT = Platform.executableArguments
- .contains('--experimental-enable-isolate-groups-jit');
+final bool usesDwarfStackTraces = Platform.executableArguments
+ .any((entry) => RegExp('--dwarf[-_]stack[-_]traces').hasMatch(entry));
+final bool hasSymbolicStackTraces = !usesDwarfStackTraces;
final sdkRoot = Platform.script.resolve('../../../../../');
class Isolate extends Opaque {}
@@ -173,8 +174,10 @@
Expect.equals(10, accumulatedErrors.length);
for (int i = 0; i < 10; ++i) {
Expect.equals('error-$i', accumulatedErrors[i][0]);
- Expect.isTrue(
- accumulatedErrors[i][1].contains('childTestMultipleErrors'));
+ if (hasSymbolicStackTraces) {
+ Expect.isTrue(
+ accumulatedErrors[i][1].contains('childTestMultipleErrors'));
+ }
}
exit.close();
@@ -204,7 +207,9 @@
await exit.first;
Expect.equals(1, accumulatedErrors.length);
Expect.equals('error-0', accumulatedErrors[0][0]);
- Expect.contains('childTestFatalError', accumulatedErrors[0][1]);
+ if (hasSymbolicStackTraces) {
+ Expect.contains('childTestFatalError', accumulatedErrors[0][1]);
+ }
exit.close();
errors.close();
@@ -212,7 +217,7 @@
});
}
-Future testAot() async {
+Future testJitOrAot() async {
await testIsolateData();
await testMultipleErrors();
await testFatalError();
@@ -226,34 +231,20 @@
exception = e;
}
Expect.contains(
- 'Lightweight isolates are only implemented in AOT mode and need to be '
- 'explicitly enabled by passing --enable-isolate-groups.',
+ 'Lightweight isolates need to be explicitly enabled by passing '
+ '--enable-isolate-groups.',
exception.toString());
}
-Future testJit() async {
- dynamic exception;
- try {
- FfiBindings.createLightweightIsolate('debug-name', Pointer.fromAddress(0));
- } catch (e) {
- exception = e;
- }
- Expect.contains(
- 'Lightweight isolates are not yet ready in JIT mode', exception);
-}
-
Future main(args) async {
if (!isolateGroupsEnabled) {
await testNotSupported();
return;
}
- if (isAOT) {
- await testAot();
- } else {
- if (isolateGroupsEnabledInJIT) {
- await testJit();
- } else {
- await testNotSupported();
- }
- }
+
+ // This test should not run in hot-reload because of the way it is written
+ // (embedder related code written in Dart instead of C)
+ if (isArtificialReloadMode) return;
+
+ await testJitOrAot();
}
diff --git a/runtime/tests/vm/dart/isolates/fast_object_copy2_test.dart b/runtime/tests/vm/dart/isolates/fast_object_copy2_test.dart
new file mode 100644
index 0000000..dc684dc
--- /dev/null
+++ b/runtime/tests/vm/dart/isolates/fast_object_copy2_test.dart
@@ -0,0 +1,75 @@
+// 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.
+
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy --gc-on-foc-slow-path --force-evacuation
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy --gc-on-foc-slow-path --force-evacuation
+
+// The tests in this file will only succeed when isolate groups are enabled
+// (hence the VMOptions above).
+
+import 'dart:async';
+import 'dart:isolate';
+import 'dart:typed_data';
+
+import 'package:expect/expect.dart';
+
+import 'fast_object_copy_test.dart'
+ show UserObject, SendReceiveTestBase, notAllocatableInTLAB;
+
+// When running with isolate groups enabled, we can share all of the following
+// objects.
+final sharableObjects = [
+ 1,
+ 0xffffffffffffffff,
+ 'foobar',
+ const UserObject(1, 1.2, ''),
+ (() {
+ final rp = ReceivePort();
+ final sp = rp.sendPort;
+ rp.close();
+ return sp;
+ })(),
+ const [1, 2, 3],
+ const {1: 1, 2: 2, 3: 2},
+ const {1, 2, 3},
+ RegExp('a'),
+ Isolate.current.pauseCapability,
+ Int32x4(1, 2, 3, 4),
+];
+
+class SendReceiveTest extends SendReceiveTestBase {
+ Future runTests() async {
+ await testSharable();
+ await testSharable2();
+ }
+
+ Future testSharable() async {
+ final sharableObjectsCopy = await sendReceive([
+ ...sharableObjects,
+ ]);
+ Expect.notIdentical(sharableObjects, sharableObjectsCopy);
+ for (int i = 0; i < sharableObjects.length; ++i) {
+ Expect.identical(sharableObjects[i], sharableObjectsCopy[i]);
+ }
+ }
+
+ Future testSharable2() async {
+ final sharableObjectsCopy = await sendReceive([
+ notAllocatableInTLAB,
+ ...sharableObjects,
+ ]);
+ Expect.notIdentical(sharableObjects, sharableObjectsCopy);
+ Expect.equals(
+ notAllocatableInTLAB[0], (sharableObjectsCopy[0] as Uint8List)[0]);
+ for (int i = 0; i < sharableObjects.length; ++i) {
+ Expect.identical(sharableObjects[i], sharableObjectsCopy[i + 1]);
+ }
+ }
+}
+
+main() async {
+ await SendReceiveTest().run();
+}
diff --git a/runtime/tests/vm/dart/isolates/fast_object_copy_test.dart b/runtime/tests/vm/dart/isolates/fast_object_copy_test.dart
index 00297e1..dda2b0f 100644
--- a/runtime/tests/vm/dart/isolates/fast_object_copy_test.dart
+++ b/runtime/tests/vm/dart/isolates/fast_object_copy_test.dart
@@ -3,7 +3,10 @@
// BSD-style license that can be found in the LICENSE file.
// VMOptions=
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy --gc-on-foc-slow-path --force-evacuation --verify-store-buffer
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy --gc-on-foc-slow-path --force-evacuation --verify-store-buffer
// The tests in this file are particularly for an implementation that tries to
// allocate the entire graph in BFS order using a fast new space allocation
@@ -28,7 +31,7 @@
final Uint8List largeInternalTypedData = Uint8List(20 * 1024 * 1024)..[0] = 42;
final Uint8List smallExternalTypedData =
- File(Platform.script.toFilePath()).readAsBytesSync();
+ File(Platform.script.toFilePath()).readAsBytesSync()..[0] = 21;
final Uint8List smallExternalTypedDataView =
Uint8List.view(smallExternalTypedData.buffer, 1, 1);
@@ -110,6 +113,17 @@
}
return;
}
+ if (a is Set) {
+ final cb = b as Set;
+ Expect.equals(a.length, cb.length);
+ final aKeys = a.toList();
+ final cbKeys = cb.toList();
+ for (int i = 0; i < a.length; ++i) {
+ expectGraphsMatch(aKeys[i], cbKeys[i]);
+ }
+ return;
+ }
+
throw 'Unexpected object encountered when matching object graphs $a / $b';
}
@@ -126,6 +140,8 @@
class HashIncrementer {
static int counter = 1;
+ const HashIncrementer();
+
int get hashCode => counter++;
bool operator ==(other) => identical(this, other);
}
@@ -135,21 +151,39 @@
final double unboxedDouble;
final dynamic slot;
- UserObject(this.unboxedInt, this.unboxedDouble, this.slot);
+ const UserObject(this.unboxedInt, this.unboxedDouble, this.slot);
}
-class SendReceiveTest {
+abstract class SendReceiveTestBase {
late final ReceivePort receivePort;
late final SendPort sendPort;
late final StreamIterator si;
- SendReceiveTest();
+ SendReceiveTestBase();
Future run() async {
receivePort = ReceivePort();
sendPort = receivePort.sendPort;
si = StreamIterator(receivePort);
+ await runTests();
+
+ si.cancel();
+ receivePort.close();
+ print('done');
+ }
+
+ Future runTests();
+
+ Future<T> sendReceive<T>(T graph) async {
+ sendPort.send(graph);
+ Expect.isTrue(await si.moveNext());
+ return si.current as T;
+ }
+}
+
+class SendReceiveTest extends SendReceiveTestBase {
+ Future runTests() async {
await testTransferrable();
await testTransferrable2();
await testTransferrable3();
@@ -161,6 +195,7 @@
await testExternalTypedData3();
await testExternalTypedData4();
await testExternalTypedData5();
+ await testExternalTypedData6();
await testInternalTypedDataView();
await testInternalTypedDataView2();
@@ -172,16 +207,18 @@
await testExternalTypedDataView3();
await testExternalTypedDataView4();
+ await testArray();
+
await testMapRehash();
await testMapRehash2();
await testMapRehash3();
+ await testSetRehash();
+ await testSetRehash2();
+ await testSetRehash3();
+
await testFastOnly();
await testSlowOnly();
-
- si.cancel();
- receivePort.close();
- print('done');
}
Future testTransferrable() async {
@@ -293,6 +330,16 @@
}
}
+ Future testExternalTypedData6() async {
+ print('testExternalTypedData6');
+ final etd = await sendReceive([
+ smallExternalTypedData,
+ largeExternalTypedData,
+ ]);
+ Expect.equals(21, etd[0][0]);
+ Expect.equals(42, etd[1][0]);
+ }
+
Future testInternalTypedDataView() async {
print('testInternalTypedDataView');
final graph = [
@@ -401,6 +448,18 @@
expectGraphsMatch(graph, copiedGraph);
}
+ Future testArray() async {
+ print('testArray');
+ final oldSpace = List<dynamic>.filled(1024 * 1024, null);
+ final newSpace = UserObject(1, 1.1, 'foobar');
+ oldSpace[0] = newSpace;
+ final oldSpaceCopy = await sendReceive(oldSpace);
+ final newSpaceCopy = oldSpaceCopy[0] as UserObject;
+ Expect.equals(newSpaceCopy.unboxedInt, 1);
+ Expect.equals(newSpaceCopy.unboxedDouble, 1.1);
+ Expect.equals(newSpaceCopy.slot, 'foobar');
+ }
+
Future testMapRehash() async {
print('testMapRehash');
final obj = Object();
@@ -437,7 +496,7 @@
Future testMapRehash3() async {
print('testMapRehash3');
- final obj = HashIncrementer();
+ final obj = const HashIncrementer();
final graph = [
{obj: 42},
notAllocatableInTLAB,
@@ -448,6 +507,57 @@
Expect.equals(before + 1, after);
}
+ Future testSetRehash() async {
+ print('testSetRehash');
+ final obj = Object();
+ final graph = <dynamic>[
+ <dynamic>{42, obj},
+ notAllocatableInTLAB,
+ ];
+ final result = await sendReceive(graph);
+ final setCopy = result[0] as Set<dynamic>;
+ Expect.equals(2, setCopy.length);
+ Expect.equals(42, setCopy.toList()[0]);
+ Expect.equals(obj.runtimeType, setCopy.toList()[1].runtimeType);
+ Expect.notIdentical(obj, setCopy.toList()[1]);
+ Expect.notEquals(
+ identityHashCode(obj), identityHashCode(setCopy.toList()[1]));
+ Expect.isFalse(setCopy.contains(obj));
+ Expect.isTrue(setCopy.contains(setCopy.toList()[1]));
+ }
+
+ Future testSetRehash2() async {
+ print('testSetRehash2');
+ final obj = Object();
+ final graph = <dynamic>[
+ notAllocatableInTLAB,
+ <dynamic>{42, obj},
+ ];
+ final result = await sendReceive(graph);
+ final setCopy = result[1] as Set<dynamic>;
+ Expect.equals(2, setCopy.length);
+ Expect.equals(42, setCopy.toList()[0]);
+ Expect.equals(obj.runtimeType, setCopy.toList()[1].runtimeType);
+ Expect.notIdentical(obj, setCopy.toList()[1]);
+ Expect.notEquals(
+ identityHashCode(obj), identityHashCode(setCopy.toList()[1]));
+ Expect.isFalse(setCopy.contains(obj));
+ Expect.isTrue(setCopy.contains(setCopy.toList()[1]));
+ }
+
+ Future testSetRehash3() async {
+ print('testSetRehash3');
+ final obj = const HashIncrementer();
+ final graph = [
+ {42, obj},
+ notAllocatableInTLAB,
+ ];
+ final int before = HashIncrementer.counter;
+ await sendReceive(graph);
+ final int after = HashIncrementer.counter;
+ Expect.equals(before + 1, after);
+ }
+
Future testFastOnly() async {
print('testFastOnly');
for (final smallPrimitive in smallPrimitives) {
@@ -469,12 +579,6 @@
await sendReceive([notAllocatableInTLAB, smallContainer]));
}
}
-
- Future<T> sendReceive<T>(T graph) async {
- sendPort.send(graph);
- Expect.isTrue(await si.moveNext());
- return si.current as T;
- }
}
main() async {
diff --git a/runtime/tests/vm/dart/isolates/fibonacci_call_ig_test.dart b/runtime/tests/vm/dart/isolates/fibonacci_call_ig_test.dart
index 61acb3f..946cbf9 100644
--- a/runtime/tests/vm/dart/isolates/fibonacci_call_ig_test.dart
+++ b/runtime/tests/vm/dart/isolates/fibonacci_call_ig_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit --disable-heap-verification
+// VMOptions=--enable-isolate-groups --disable-heap-verification
import 'dart:isolate';
@@ -12,6 +12,12 @@
import 'test_utils.dart';
main(args) async {
+ // We don't run this test in our artificial hot reload mode, because it would
+ // create too many threads during the reload (one per isolate), which can
+ // cause this test or other concurrently executing tests to Crash due to
+ // unability of `pthread_create` to create a new thread.
+ if (isArtificialReloadMode) return;
+
final rp = ReceivePort();
final int n = 18;
await spawnInDetachedGroup(fibonacciRecursive, [rp.sendPort, n]);
diff --git a/runtime/tests/vm/dart/isolates/fibonacci_call_test.dart b/runtime/tests/vm/dart/isolates/fibonacci_call_test.dart
index a8ba640..daf66e0 100644
--- a/runtime/tests/vm/dart/isolates/fibonacci_call_test.dart
+++ b/runtime/tests/vm/dart/isolates/fibonacci_call_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit --disable-heap-verification
+// VMOptions=--enable-isolate-groups --disable-heap-verification
import 'dart:isolate';
@@ -11,6 +11,12 @@
import 'test_utils.dart';
main(args) async {
+ // We don't run this test in our artificial hot reload mode, because it would
+ // create too many threads during the reload (one per isolate), which can
+ // cause this test or other concurrently executing tests to Crash due to
+ // unability of `pthread_create` to create a new thread.
+ if (isArtificialReloadMode) return;
+
final rp = ReceivePort();
final int n = 18;
await Isolate.spawn(fibonacciRecursive, [rp.sendPort, n]);
diff --git a/runtime/tests/vm/dart/isolates/limited_active_mutator_test.dart b/runtime/tests/vm/dart/isolates/limited_active_mutator_test.dart
index 147dfdc..f56e9ee 100644
--- a/runtime/tests/vm/dart/isolates/limited_active_mutator_test.dart
+++ b/runtime/tests/vm/dart/isolates/limited_active_mutator_test.dart
@@ -2,8 +2,7 @@
// 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.
-// SharedObjects=ffi_test_functions
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit --disable-heap-verification --disable-thread-pool-limit
+// VMOptions=--enable-isolate-groups --disable-heap-verification --disable-thread-pool-limit
import 'dart:async';
import 'dart:math' as math;
diff --git a/runtime/tests/vm/dart/isolates/regress_46539_test.dart b/runtime/tests/vm/dart/isolates/regress_46539_test.dart
new file mode 100644
index 0000000..0814f0d
--- /dev/null
+++ b/runtime/tests/vm/dart/isolates/regress_46539_test.dart
@@ -0,0 +1,83 @@
+// 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.
+
+// VMOptions=--optimization-filter=foo --enable-isolate-groups --no-use-osr --optimization-counter-threshold=1 --deterministic
+
+// Important: This is a regression test for a concurrency issue, if this test
+// is flaky it is essentially failing!
+
+import 'dart:async';
+import 'dart:io';
+import 'dart:isolate';
+import 'dart:_internal' show VMInternalsForTesting;
+
+import 'package:expect/expect.dart';
+
+const int isolateCount = 3;
+const int deoptIsolateId = 0;
+const int polyIsolateId = 1;
+
+final bool isAOT = Platform.executable.contains('dart_precompiled_runtime');
+
+main() async {
+ // This test will cause deoptimizations (via helper in `dart:_internal`) and
+ // does therefore not run in AOT.
+ if (isAOT) return;
+
+ final onExit = ReceivePort();
+ final onError = ReceivePort()
+ ..listen((error) {
+ print('Error: $error');
+ exitCode = 250;
+ });
+ for (int i = 0; i < isolateCount; ++i) {
+ await Isolate.spawn(isolate, i,
+ onExit: onExit.sendPort, onError: onError.sendPort);
+ }
+ final onExits = StreamIterator(onExit);
+ for (int i = 0; i < isolateCount; ++i) {
+ Expect.isTrue(await onExits.moveNext());
+ }
+ onExits.cancel();
+ onError.close();
+}
+
+final globalA = A();
+final globalB = B();
+
+isolate(int isolateId) {
+ final A a = isolateId == polyIsolateId ? globalB : globalA;
+ if (isolateId == polyIsolateId) {
+ // We start deopting after 1 second.
+ sleep(500000);
+ }
+
+ // This runs in unoptimized mode and will therefore do switchable calls.
+ final sw = Stopwatch()..start();
+ while (sw.elapsedMicroseconds < 2000000) {
+ a.foo(isolateId);
+ a.foo(isolateId);
+ a.foo(isolateId);
+ a.foo(isolateId);
+ }
+}
+
+class A {
+ @pragma('vm:never-inline')
+ foo(int isolateId) {
+ if (isolateId == deoptIsolateId) {
+ VMInternalsForTesting.deoptimizeFunctionsOnStack();
+ }
+ }
+}
+
+class B implements A {
+ @pragma('vm:never-inline')
+ foo(int isolateId) {}
+}
+
+void sleep(int us) {
+ final sw = Stopwatch()..start();
+ while (sw.elapsedMicroseconds < us);
+}
diff --git a/runtime/tests/vm/dart/isolates/ring_gc_sendAndExit_test.dart b/runtime/tests/vm/dart/isolates/ring_gc_sendAndExit_test.dart
index e461273..74b6820 100644
--- a/runtime/tests/vm/dart/isolates/ring_gc_sendAndExit_test.dart
+++ b/runtime/tests/vm/dart/isolates/ring_gc_sendAndExit_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit --disable-heap-verification
+// VMOptions=--enable-isolate-groups --disable-heap-verification
import 'dart:math' as math;
@@ -12,6 +12,12 @@
import 'test_utils.dart';
main(args) async {
+ // We don't run this test in our artificial hot reload mode, because it would
+ // create too many threads during the reload (one per isolate), which can
+ // cause this test or other concurrently executing tests to Crash due to
+ // unability of `pthread_create` to create a new thread.
+ if (isArtificialReloadMode) return;
+
final int numIsolates = (isDebugMode || isSimulator) ? 100 : 5000;
// Spawn ring of 1k isolates.
diff --git a/runtime/tests/vm/dart/isolates/ring_gc_test.dart b/runtime/tests/vm/dart/isolates/ring_gc_test.dart
index f0ecbc1..c27cd6c 100644
--- a/runtime/tests/vm/dart/isolates/ring_gc_test.dart
+++ b/runtime/tests/vm/dart/isolates/ring_gc_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit --disable-heap-verification
+// VMOptions=--enable-isolate-groups --disable-heap-verification
import 'dart:async';
import 'dart:math' as math;
@@ -31,6 +31,12 @@
}
main(args) async {
+ // We don't run this test in our artificial hot reload mode, because it would
+ // create too many threads during the reload (one per isolate), which can
+ // cause this test or other concurrently executing tests to Crash due to
+ // unability of `pthread_create` to create a new thread.
+ if (isArtificialReloadMode) return;
+
final int numIsolates = (isDebugMode || isSimulator) ? 100 : 1000;
// Spawn ring of 1k isolates.
diff --git a/runtime/tests/vm/dart/isolates/spawn_function_test.dart b/runtime/tests/vm/dart/isolates/spawn_function_test.dart
index bbbb2f5..f2a85ea 100644
--- a/runtime/tests/vm/dart/isolates/spawn_function_test.dart
+++ b/runtime/tests/vm/dart/isolates/spawn_function_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import 'dart:isolate';
diff --git a/runtime/tests/vm/dart/isolates/sum_recursive_call_ig_test.dart b/runtime/tests/vm/dart/isolates/sum_recursive_call_ig_test.dart
index 6b7eecb..915c102 100644
--- a/runtime/tests/vm/dart/isolates/sum_recursive_call_ig_test.dart
+++ b/runtime/tests/vm/dart/isolates/sum_recursive_call_ig_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit --disable-heap-verification
+// VMOptions=--enable-isolate-groups --disable-heap-verification
import 'dart:isolate';
diff --git a/runtime/tests/vm/dart/isolates/sum_recursive_call_test.dart b/runtime/tests/vm/dart/isolates/sum_recursive_call_test.dart
index 3b18008..89bcc58 100644
--- a/runtime/tests/vm/dart/isolates/sum_recursive_call_test.dart
+++ b/runtime/tests/vm/dart/isolates/sum_recursive_call_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit --disable-heap-verification
+// VMOptions=--enable-isolate-groups --disable-heap-verification
import 'dart:isolate';
diff --git a/runtime/tests/vm/dart/isolates/sum_recursive_tail_call_ig_test.dart b/runtime/tests/vm/dart/isolates/sum_recursive_tail_call_ig_test.dart
index bf1d165..a3fb967 100644
--- a/runtime/tests/vm/dart/isolates/sum_recursive_tail_call_ig_test.dart
+++ b/runtime/tests/vm/dart/isolates/sum_recursive_tail_call_ig_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit --disable-heap-verification
+// VMOptions=--enable-isolate-groups --disable-heap-verification
import 'dart:isolate';
diff --git a/runtime/tests/vm/dart/isolates/sum_recursive_tail_call_test.dart b/runtime/tests/vm/dart/isolates/sum_recursive_tail_call_test.dart
index a98cc91..866b8f3 100644
--- a/runtime/tests/vm/dart/isolates/sum_recursive_tail_call_test.dart
+++ b/runtime/tests/vm/dart/isolates/sum_recursive_tail_call_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit --disable-heap-verification
+// VMOptions=--enable-isolate-groups --disable-heap-verification
import 'dart:isolate';
diff --git a/runtime/tests/vm/dart/isolates/test_utils.dart b/runtime/tests/vm/dart/isolates/test_utils.dart
index b2ffa76..4e1d929 100644
--- a/runtime/tests/vm/dart/isolates/test_utils.dart
+++ b/runtime/tests/vm/dart/isolates/test_utils.dart
@@ -10,6 +10,10 @@
final bool isDebugMode = Platform.script.path.contains('Debug');
final bool isSimulator = Platform.script.path.contains('SIM');
+final bool isArtificialReloadMode = Platform.executableArguments.any((arg) => [
+ '--hot-reload-rollback-test-mode',
+ '--hot-reload-test-mode'
+ ].contains(arg));
// Implements recursive summation:
// sum(n) => n == 0 ? 0
diff --git a/runtime/tests/vm/dart/isolates/thread_pool_test.dart b/runtime/tests/vm/dart/isolates/thread_pool_test.dart
index aadf1f6..3d689ca 100644
--- a/runtime/tests/vm/dart/isolates/thread_pool_test.dart
+++ b/runtime/tests/vm/dart/isolates/thread_pool_test.dart
@@ -3,7 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
// SharedObjects=ffi_test_functions
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit --disable-heap-verification
+// VMOptions=--enable-isolate-groups --disable-heap-verification
import 'dart:async';
import 'dart:ffi';
diff --git a/runtime/tests/vm/dart/issue_31959_31960_test.dart b/runtime/tests/vm/dart/issue_31959_31960_test.dart
index 5cb830f..3ca1be2 100644
--- a/runtime/tests/vm/dart/issue_31959_31960_test.dart
+++ b/runtime/tests/vm/dart/issue_31959_31960_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import 'dart:async';
diff --git a/runtime/tests/vm/dart/sendandexit_test.dart b/runtime/tests/vm/dart/sendandexit_test.dart
index 91d2bac..58e02c6 100644
--- a/runtime/tests/vm/dart/sendandexit_test.dart
+++ b/runtime/tests/vm/dart/sendandexit_test.dart
@@ -2,7 +2,7 @@
// 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.
//
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
//
// Validates functionality of sendAndExit.
diff --git a/runtime/tests/vm/dart/spawn_infinite_loop_test.dart b/runtime/tests/vm/dart/spawn_infinite_loop_test.dart
index 79409e0..3a89e80 100644
--- a/runtime/tests/vm/dart/spawn_infinite_loop_test.dart
+++ b/runtime/tests/vm/dart/spawn_infinite_loop_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import 'dart:isolate';
diff --git a/runtime/tests/vm/dart/transferable_test.dart b/runtime/tests/vm/dart/transferable_test.dart
index 6a9c4f0..2f5155a 100644
--- a/runtime/tests/vm/dart/transferable_test.dart
+++ b/runtime/tests/vm/dart/transferable_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// Test that validates that transferables are faster than regular typed data.
diff --git a/runtime/tests/vm/dart/transferable_throws_test.dart b/runtime/tests/vm/dart/transferable_throws_test.dart
index 67cba0a..201c020 100644
--- a/runtime/tests/vm/dart/transferable_throws_test.dart
+++ b/runtime/tests/vm/dart/transferable_throws_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// Test that ensures correct exceptions are thrown when misusing
@@ -11,7 +11,6 @@
import 'dart:async';
import 'dart:collection';
import 'dart:core';
-import 'dart:io';
import 'dart:isolate';
import 'dart:typed_data';
import 'dart:math';
diff --git a/runtime/tests/vm/dart_2/deferred_isolate_test.dart b/runtime/tests/vm/dart_2/deferred_isolate_test.dart
index d056b31..94be755 100644
--- a/runtime/tests/vm/dart_2/deferred_isolate_test.dart
+++ b/runtime/tests/vm/dart_2/deferred_isolate_test.dart
@@ -4,7 +4,7 @@
// Verify deferred library status is per-isolate, not per-isolate-group.
-// VMOptions=--enable_isolate_groups --experimental_enable_isolate_groups_jit
+// VMOptions=--enable-isolate-groups
import 'dart:async';
import 'dart:isolate';
diff --git a/runtime/tests/vm/dart_2/isolates/dart_api_create_lightweight_isolate_test.dart b/runtime/tests/vm/dart_2/isolates/dart_api_create_lightweight_isolate_test.dart
index 4611883..8b92de1 100644
--- a/runtime/tests/vm/dart_2/isolates/dart_api_create_lightweight_isolate_test.dart
+++ b/runtime/tests/vm/dart_2/isolates/dart_api_create_lightweight_isolate_test.dart
@@ -4,7 +4,7 @@
// SharedObjects=ffi_test_functions
// VMOptions=
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit --disable-heap-verification
+// VMOptions=--enable-isolate-groups --disable-heap-verification
import 'dart:async';
import 'dart:ffi';
@@ -14,13 +14,14 @@
import 'package:expect/expect.dart';
import 'package:ffi/ffi.dart';
+import 'test_utils.dart' show isArtificialReloadMode;
import '../../../../../tests/ffi/dylib_utils.dart';
-final bool isAOT = Platform.executable.contains('dart_precompiled_runtime');
final bool isolateGroupsEnabled =
Platform.executableArguments.contains('--enable-isolate-groups');
-final bool isolateGroupsEnabledInJIT = Platform.executableArguments
- .contains('--experimental-enable-isolate-groups-jit');
+final bool usesDwarfStackTraces = Platform.executableArguments
+ .any((entry) => RegExp('--dwarf[-_]stack[-_]traces').hasMatch(entry));
+final bool hasSymbolicStackTraces = !usesDwarfStackTraces;
final sdkRoot = Platform.script.resolve('../../../../../');
class Isolate extends Opaque {}
@@ -173,8 +174,10 @@
Expect.equals(10, accumulatedErrors.length);
for (int i = 0; i < 10; ++i) {
Expect.equals('error-$i', accumulatedErrors[i][0]);
- Expect.isTrue(
- accumulatedErrors[i][1].contains('childTestMultipleErrors'));
+ if (hasSymbolicStackTraces) {
+ Expect.isTrue(
+ accumulatedErrors[i][1].contains('childTestMultipleErrors'));
+ }
}
exit.close();
@@ -204,7 +207,9 @@
await exit.first;
Expect.equals(1, accumulatedErrors.length);
Expect.equals('error-0', accumulatedErrors[0][0]);
- Expect.contains('childTestFatalError', accumulatedErrors[0][1]);
+ if (hasSymbolicStackTraces) {
+ Expect.contains('childTestFatalError', accumulatedErrors[0][1]);
+ }
exit.close();
errors.close();
@@ -212,7 +217,7 @@
});
}
-Future testAot() async {
+Future testJitOrAot() async {
await testIsolateData();
await testMultipleErrors();
await testFatalError();
@@ -226,34 +231,20 @@
exception = e;
}
Expect.contains(
- 'Lightweight isolates are only implemented in AOT mode and need to be '
- 'explicitly enabled by passing --enable-isolate-groups.',
+ 'Lightweight isolates need to be explicitly enabled by passing '
+ '--enable-isolate-groups.',
exception.toString());
}
-Future testJit() async {
- dynamic exception;
- try {
- FfiBindings.createLightweightIsolate('debug-name', Pointer.fromAddress(0));
- } catch (e) {
- exception = e;
- }
- Expect.contains(
- 'Lightweight isolates are not yet ready in JIT mode', exception);
-}
-
Future main(args) async {
if (!isolateGroupsEnabled) {
await testNotSupported();
return;
}
- if (isAOT) {
- await testAot();
- } else {
- if (isolateGroupsEnabledInJIT) {
- await testJit();
- } else {
- await testNotSupported();
- }
- }
+
+ // This test should not run in hot-reload because of the way it is written
+ // (embedder related code written in Dart instead of C)
+ if (isArtificialReloadMode) return;
+
+ await testJitOrAot();
}
diff --git a/runtime/tests/vm/dart_2/isolates/fast_object_copy2_test.dart b/runtime/tests/vm/dart_2/isolates/fast_object_copy2_test.dart
new file mode 100644
index 0000000..dc684dc
--- /dev/null
+++ b/runtime/tests/vm/dart_2/isolates/fast_object_copy2_test.dart
@@ -0,0 +1,75 @@
+// 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.
+
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy --gc-on-foc-slow-path --force-evacuation
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy --gc-on-foc-slow-path --force-evacuation
+
+// The tests in this file will only succeed when isolate groups are enabled
+// (hence the VMOptions above).
+
+import 'dart:async';
+import 'dart:isolate';
+import 'dart:typed_data';
+
+import 'package:expect/expect.dart';
+
+import 'fast_object_copy_test.dart'
+ show UserObject, SendReceiveTestBase, notAllocatableInTLAB;
+
+// When running with isolate groups enabled, we can share all of the following
+// objects.
+final sharableObjects = [
+ 1,
+ 0xffffffffffffffff,
+ 'foobar',
+ const UserObject(1, 1.2, ''),
+ (() {
+ final rp = ReceivePort();
+ final sp = rp.sendPort;
+ rp.close();
+ return sp;
+ })(),
+ const [1, 2, 3],
+ const {1: 1, 2: 2, 3: 2},
+ const {1, 2, 3},
+ RegExp('a'),
+ Isolate.current.pauseCapability,
+ Int32x4(1, 2, 3, 4),
+];
+
+class SendReceiveTest extends SendReceiveTestBase {
+ Future runTests() async {
+ await testSharable();
+ await testSharable2();
+ }
+
+ Future testSharable() async {
+ final sharableObjectsCopy = await sendReceive([
+ ...sharableObjects,
+ ]);
+ Expect.notIdentical(sharableObjects, sharableObjectsCopy);
+ for (int i = 0; i < sharableObjects.length; ++i) {
+ Expect.identical(sharableObjects[i], sharableObjectsCopy[i]);
+ }
+ }
+
+ Future testSharable2() async {
+ final sharableObjectsCopy = await sendReceive([
+ notAllocatableInTLAB,
+ ...sharableObjects,
+ ]);
+ Expect.notIdentical(sharableObjects, sharableObjectsCopy);
+ Expect.equals(
+ notAllocatableInTLAB[0], (sharableObjectsCopy[0] as Uint8List)[0]);
+ for (int i = 0; i < sharableObjects.length; ++i) {
+ Expect.identical(sharableObjects[i], sharableObjectsCopy[i + 1]);
+ }
+ }
+}
+
+main() async {
+ await SendReceiveTest().run();
+}
diff --git a/runtime/tests/vm/dart_2/isolates/fast_object_copy_test.dart b/runtime/tests/vm/dart_2/isolates/fast_object_copy_test.dart
index 9737462..87bbc26 100644
--- a/runtime/tests/vm/dart_2/isolates/fast_object_copy_test.dart
+++ b/runtime/tests/vm/dart_2/isolates/fast_object_copy_test.dart
@@ -3,7 +3,10 @@
// BSD-style license that can be found in the LICENSE file.
// VMOptions=
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy --gc-on-foc-slow-path --force-evacuation --verify-store-buffer
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy --gc-on-foc-slow-path --force-evacuation --verify-store-buffer
// The tests in this file are particularly for an implementation that tries to
// allocate the entire graph in BFS order using a fast new space allocation
@@ -28,7 +31,7 @@
final Uint8List largeInternalTypedData = Uint8List(20 * 1024 * 1024)..[0] = 42;
final Uint8List smallExternalTypedData =
- File(Platform.script.toFilePath()).readAsBytesSync();
+ File(Platform.script.toFilePath()).readAsBytesSync()..[0] = 21;
final Uint8List smallExternalTypedDataView =
Uint8List.view(smallExternalTypedData.buffer, 1, 1);
@@ -110,6 +113,17 @@
}
return;
}
+ if (a is Set) {
+ final cb = b as Set;
+ Expect.equals(a.length, cb.length);
+ final aKeys = a.toList();
+ final cbKeys = cb.toList();
+ for (int i = 0; i < a.length; ++i) {
+ expectGraphsMatch(aKeys[i], cbKeys[i]);
+ }
+ return;
+ }
+
throw 'Unexpected object encountered when matching object graphs $a / $b';
}
@@ -126,6 +140,8 @@
class HashIncrementer {
static int counter = 1;
+ const HashIncrementer();
+
int get hashCode => counter++;
bool operator ==(other) => identical(this, other);
}
@@ -135,21 +151,39 @@
final double unboxedDouble;
final dynamic slot;
- UserObject(this.unboxedInt, this.unboxedDouble, this.slot);
+ const UserObject(this.unboxedInt, this.unboxedDouble, this.slot);
}
-class SendReceiveTest {
+abstract class SendReceiveTestBase {
ReceivePort receivePort;
SendPort sendPort;
StreamIterator si;
- SendReceiveTest();
+ SendReceiveTestBase();
Future run() async {
receivePort = ReceivePort();
sendPort = receivePort.sendPort;
si = StreamIterator(receivePort);
+ await runTests();
+
+ si.cancel();
+ receivePort.close();
+ print('done');
+ }
+
+ Future runTests();
+
+ Future<T> sendReceive<T>(T graph) async {
+ sendPort.send(graph);
+ Expect.isTrue(await si.moveNext());
+ return si.current as T;
+ }
+}
+
+class SendReceiveTest extends SendReceiveTestBase {
+ Future runTests() async {
await testTransferrable();
await testTransferrable2();
await testTransferrable3();
@@ -161,6 +195,7 @@
await testExternalTypedData3();
await testExternalTypedData4();
await testExternalTypedData5();
+ await testExternalTypedData6();
await testInternalTypedDataView();
await testInternalTypedDataView2();
@@ -172,16 +207,18 @@
await testExternalTypedDataView3();
await testExternalTypedDataView4();
+ await testArray();
+
await testMapRehash();
await testMapRehash2();
await testMapRehash3();
+ await testSetRehash();
+ await testSetRehash2();
+ await testSetRehash3();
+
await testFastOnly();
await testSlowOnly();
-
- si.cancel();
- receivePort.close();
- print('done');
}
Future testTransferrable() async {
@@ -293,6 +330,16 @@
}
}
+ Future testExternalTypedData6() async {
+ print('testExternalTypedData6');
+ final etd = await sendReceive([
+ smallExternalTypedData,
+ largeExternalTypedData,
+ ]);
+ Expect.equals(21, etd[0][0]);
+ Expect.equals(42, etd[1][0]);
+ }
+
Future testInternalTypedDataView() async {
print('testInternalTypedDataView');
final graph = [
@@ -401,6 +448,18 @@
expectGraphsMatch(graph, copiedGraph);
}
+ Future testArray() async {
+ print('testArray');
+ final oldSpace = List<dynamic>.filled(1024 * 1024, null);
+ final newSpace = UserObject(1, 1.1, 'foobar');
+ oldSpace[0] = newSpace;
+ final oldSpaceCopy = await sendReceive(oldSpace);
+ final newSpaceCopy = oldSpaceCopy[0] as UserObject;
+ Expect.equals(newSpaceCopy.unboxedInt, 1);
+ Expect.equals(newSpaceCopy.unboxedDouble, 1.1);
+ Expect.equals(newSpaceCopy.slot, 'foobar');
+ }
+
Future testMapRehash() async {
print('testMapRehash');
final obj = Object();
@@ -437,7 +496,7 @@
Future testMapRehash3() async {
print('testMapRehash3');
- final obj = HashIncrementer();
+ final obj = const HashIncrementer();
final graph = [
{obj: 42},
notAllocatableInTLAB,
@@ -448,6 +507,57 @@
Expect.equals(before + 1, after);
}
+ Future testSetRehash() async {
+ print('testSetRehash');
+ final obj = Object();
+ final graph = <dynamic>[
+ <dynamic>{42, obj},
+ notAllocatableInTLAB,
+ ];
+ final result = await sendReceive(graph);
+ final setCopy = result[0] as Set<dynamic>;
+ Expect.equals(2, setCopy.length);
+ Expect.equals(42, setCopy.toList()[0]);
+ Expect.equals(obj.runtimeType, setCopy.toList()[1].runtimeType);
+ Expect.notIdentical(obj, setCopy.toList()[1]);
+ Expect.notEquals(
+ identityHashCode(obj), identityHashCode(setCopy.toList()[1]));
+ Expect.isFalse(setCopy.contains(obj));
+ Expect.isTrue(setCopy.contains(setCopy.toList()[1]));
+ }
+
+ Future testSetRehash2() async {
+ print('testSetRehash2');
+ final obj = Object();
+ final graph = <dynamic>[
+ notAllocatableInTLAB,
+ <dynamic>{42, obj},
+ ];
+ final result = await sendReceive(graph);
+ final setCopy = result[1] as Set<dynamic>;
+ Expect.equals(2, setCopy.length);
+ Expect.equals(42, setCopy.toList()[0]);
+ Expect.equals(obj.runtimeType, setCopy.toList()[1].runtimeType);
+ Expect.notIdentical(obj, setCopy.toList()[1]);
+ Expect.notEquals(
+ identityHashCode(obj), identityHashCode(setCopy.toList()[1]));
+ Expect.isFalse(setCopy.contains(obj));
+ Expect.isTrue(setCopy.contains(setCopy.toList()[1]));
+ }
+
+ Future testSetRehash3() async {
+ print('testSetRehash3');
+ final obj = const HashIncrementer();
+ final graph = [
+ {42, obj},
+ notAllocatableInTLAB,
+ ];
+ final int before = HashIncrementer.counter;
+ await sendReceive(graph);
+ final int after = HashIncrementer.counter;
+ Expect.equals(before + 1, after);
+ }
+
Future testFastOnly() async {
print('testFastOnly');
for (final smallPrimitive in smallPrimitives) {
@@ -469,12 +579,6 @@
await sendReceive([notAllocatableInTLAB, smallContainer]));
}
}
-
- Future<T> sendReceive<T>(T graph) async {
- sendPort.send(graph);
- Expect.isTrue(await si.moveNext());
- return si.current as T;
- }
}
main() async {
diff --git a/runtime/tests/vm/dart_2/isolates/fibonacci_call_ig_test.dart b/runtime/tests/vm/dart_2/isolates/fibonacci_call_ig_test.dart
index 61acb3f..946cbf9 100644
--- a/runtime/tests/vm/dart_2/isolates/fibonacci_call_ig_test.dart
+++ b/runtime/tests/vm/dart_2/isolates/fibonacci_call_ig_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit --disable-heap-verification
+// VMOptions=--enable-isolate-groups --disable-heap-verification
import 'dart:isolate';
@@ -12,6 +12,12 @@
import 'test_utils.dart';
main(args) async {
+ // We don't run this test in our artificial hot reload mode, because it would
+ // create too many threads during the reload (one per isolate), which can
+ // cause this test or other concurrently executing tests to Crash due to
+ // unability of `pthread_create` to create a new thread.
+ if (isArtificialReloadMode) return;
+
final rp = ReceivePort();
final int n = 18;
await spawnInDetachedGroup(fibonacciRecursive, [rp.sendPort, n]);
diff --git a/runtime/tests/vm/dart_2/isolates/fibonacci_call_test.dart b/runtime/tests/vm/dart_2/isolates/fibonacci_call_test.dart
index a8ba640..daf66e0 100644
--- a/runtime/tests/vm/dart_2/isolates/fibonacci_call_test.dart
+++ b/runtime/tests/vm/dart_2/isolates/fibonacci_call_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit --disable-heap-verification
+// VMOptions=--enable-isolate-groups --disable-heap-verification
import 'dart:isolate';
@@ -11,6 +11,12 @@
import 'test_utils.dart';
main(args) async {
+ // We don't run this test in our artificial hot reload mode, because it would
+ // create too many threads during the reload (one per isolate), which can
+ // cause this test or other concurrently executing tests to Crash due to
+ // unability of `pthread_create` to create a new thread.
+ if (isArtificialReloadMode) return;
+
final rp = ReceivePort();
final int n = 18;
await Isolate.spawn(fibonacciRecursive, [rp.sendPort, n]);
diff --git a/runtime/tests/vm/dart_2/isolates/limited_active_mutator_test.dart b/runtime/tests/vm/dart_2/isolates/limited_active_mutator_test.dart
index 147dfdc..f56e9ee 100644
--- a/runtime/tests/vm/dart_2/isolates/limited_active_mutator_test.dart
+++ b/runtime/tests/vm/dart_2/isolates/limited_active_mutator_test.dart
@@ -2,8 +2,7 @@
// 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.
-// SharedObjects=ffi_test_functions
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit --disable-heap-verification --disable-thread-pool-limit
+// VMOptions=--enable-isolate-groups --disable-heap-verification --disable-thread-pool-limit
import 'dart:async';
import 'dart:math' as math;
diff --git a/runtime/tests/vm/dart_2/isolates/regress_46539_test.dart b/runtime/tests/vm/dart_2/isolates/regress_46539_test.dart
new file mode 100644
index 0000000..0814f0d
--- /dev/null
+++ b/runtime/tests/vm/dart_2/isolates/regress_46539_test.dart
@@ -0,0 +1,83 @@
+// 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.
+
+// VMOptions=--optimization-filter=foo --enable-isolate-groups --no-use-osr --optimization-counter-threshold=1 --deterministic
+
+// Important: This is a regression test for a concurrency issue, if this test
+// is flaky it is essentially failing!
+
+import 'dart:async';
+import 'dart:io';
+import 'dart:isolate';
+import 'dart:_internal' show VMInternalsForTesting;
+
+import 'package:expect/expect.dart';
+
+const int isolateCount = 3;
+const int deoptIsolateId = 0;
+const int polyIsolateId = 1;
+
+final bool isAOT = Platform.executable.contains('dart_precompiled_runtime');
+
+main() async {
+ // This test will cause deoptimizations (via helper in `dart:_internal`) and
+ // does therefore not run in AOT.
+ if (isAOT) return;
+
+ final onExit = ReceivePort();
+ final onError = ReceivePort()
+ ..listen((error) {
+ print('Error: $error');
+ exitCode = 250;
+ });
+ for (int i = 0; i < isolateCount; ++i) {
+ await Isolate.spawn(isolate, i,
+ onExit: onExit.sendPort, onError: onError.sendPort);
+ }
+ final onExits = StreamIterator(onExit);
+ for (int i = 0; i < isolateCount; ++i) {
+ Expect.isTrue(await onExits.moveNext());
+ }
+ onExits.cancel();
+ onError.close();
+}
+
+final globalA = A();
+final globalB = B();
+
+isolate(int isolateId) {
+ final A a = isolateId == polyIsolateId ? globalB : globalA;
+ if (isolateId == polyIsolateId) {
+ // We start deopting after 1 second.
+ sleep(500000);
+ }
+
+ // This runs in unoptimized mode and will therefore do switchable calls.
+ final sw = Stopwatch()..start();
+ while (sw.elapsedMicroseconds < 2000000) {
+ a.foo(isolateId);
+ a.foo(isolateId);
+ a.foo(isolateId);
+ a.foo(isolateId);
+ }
+}
+
+class A {
+ @pragma('vm:never-inline')
+ foo(int isolateId) {
+ if (isolateId == deoptIsolateId) {
+ VMInternalsForTesting.deoptimizeFunctionsOnStack();
+ }
+ }
+}
+
+class B implements A {
+ @pragma('vm:never-inline')
+ foo(int isolateId) {}
+}
+
+void sleep(int us) {
+ final sw = Stopwatch()..start();
+ while (sw.elapsedMicroseconds < us);
+}
diff --git a/runtime/tests/vm/dart_2/isolates/reload_active_stack_test.dart b/runtime/tests/vm/dart_2/isolates/reload_active_stack_test.dart
index 22cdd91..615941f 100644
--- a/runtime/tests/vm/dart_2/isolates/reload_active_stack_test.dart
+++ b/runtime/tests/vm/dart_2/isolates/reload_active_stack_test.dart
@@ -2,11 +2,6 @@
// 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.
-import 'dart:async';
-import 'dart:io';
-import 'dart:convert';
-
-import 'package:path/path.dart' as path;
import 'package:expect/expect.dart';
import 'reload_utils.dart';
diff --git a/runtime/tests/vm/dart_2/isolates/reload_many_isolates_live_and_die_test.dart b/runtime/tests/vm/dart_2/isolates/reload_many_isolates_live_and_die_test.dart
index 335bbb5..7cfcbf6 100644
--- a/runtime/tests/vm/dart_2/isolates/reload_many_isolates_live_and_die_test.dart
+++ b/runtime/tests/vm/dart_2/isolates/reload_many_isolates_live_and_die_test.dart
@@ -3,10 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
-import 'dart:io';
-import 'dart:convert';
-import 'package:path/path.dart' as path;
import 'package:expect/expect.dart';
import 'reload_utils.dart';
diff --git a/runtime/tests/vm/dart_2/isolates/reload_many_isolates_test.dart b/runtime/tests/vm/dart_2/isolates/reload_many_isolates_test.dart
index 67fe65c..70ff30c 100644
--- a/runtime/tests/vm/dart_2/isolates/reload_many_isolates_test.dart
+++ b/runtime/tests/vm/dart_2/isolates/reload_many_isolates_test.dart
@@ -2,11 +2,6 @@
// 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.
-import 'dart:async';
-import 'dart:io';
-import 'dart:convert';
-
-import 'package:path/path.dart' as path;
import 'package:expect/expect.dart';
import 'reload_utils.dart';
diff --git a/runtime/tests/vm/dart_2/isolates/reload_no_active_stack_test.dart b/runtime/tests/vm/dart_2/isolates/reload_no_active_stack_test.dart
index 93f06de2..a681d0a 100644
--- a/runtime/tests/vm/dart_2/isolates/reload_no_active_stack_test.dart
+++ b/runtime/tests/vm/dart_2/isolates/reload_no_active_stack_test.dart
@@ -2,11 +2,6 @@
// 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.
-import 'dart:async';
-import 'dart:io';
-import 'dart:convert';
-
-import 'package:path/path.dart' as path;
import 'package:expect/expect.dart';
import 'reload_utils.dart';
diff --git a/runtime/tests/vm/dart_2/isolates/reload_utils.dart b/runtime/tests/vm/dart_2/isolates/reload_utils.dart
index f296c4c..4a664b7 100644
--- a/runtime/tests/vm/dart_2/isolates/reload_utils.dart
+++ b/runtime/tests/vm/dart_2/isolates/reload_utils.dart
@@ -124,7 +124,6 @@
'--disable-dart-dev',
'--disable-service-auth-codes',
'--enable-isolate-groups',
- '--experimental-enable-isolate-groups-jit',
file
];
final env = Platform.environment;
diff --git a/runtime/tests/vm/dart_2/isolates/ring_gc_sendAndExit_test.dart b/runtime/tests/vm/dart_2/isolates/ring_gc_sendAndExit_test.dart
index e461273..74b6820 100644
--- a/runtime/tests/vm/dart_2/isolates/ring_gc_sendAndExit_test.dart
+++ b/runtime/tests/vm/dart_2/isolates/ring_gc_sendAndExit_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit --disable-heap-verification
+// VMOptions=--enable-isolate-groups --disable-heap-verification
import 'dart:math' as math;
@@ -12,6 +12,12 @@
import 'test_utils.dart';
main(args) async {
+ // We don't run this test in our artificial hot reload mode, because it would
+ // create too many threads during the reload (one per isolate), which can
+ // cause this test or other concurrently executing tests to Crash due to
+ // unability of `pthread_create` to create a new thread.
+ if (isArtificialReloadMode) return;
+
final int numIsolates = (isDebugMode || isSimulator) ? 100 : 5000;
// Spawn ring of 1k isolates.
diff --git a/runtime/tests/vm/dart_2/isolates/ring_gc_test.dart b/runtime/tests/vm/dart_2/isolates/ring_gc_test.dart
index f0ecbc1..c27cd6c 100644
--- a/runtime/tests/vm/dart_2/isolates/ring_gc_test.dart
+++ b/runtime/tests/vm/dart_2/isolates/ring_gc_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit --disable-heap-verification
+// VMOptions=--enable-isolate-groups --disable-heap-verification
import 'dart:async';
import 'dart:math' as math;
@@ -31,6 +31,12 @@
}
main(args) async {
+ // We don't run this test in our artificial hot reload mode, because it would
+ // create too many threads during the reload (one per isolate), which can
+ // cause this test or other concurrently executing tests to Crash due to
+ // unability of `pthread_create` to create a new thread.
+ if (isArtificialReloadMode) return;
+
final int numIsolates = (isDebugMode || isSimulator) ? 100 : 1000;
// Spawn ring of 1k isolates.
diff --git a/runtime/tests/vm/dart_2/isolates/spawn_function_test.dart b/runtime/tests/vm/dart_2/isolates/spawn_function_test.dart
index bbbb2f5..f2a85ea 100644
--- a/runtime/tests/vm/dart_2/isolates/spawn_function_test.dart
+++ b/runtime/tests/vm/dart_2/isolates/spawn_function_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import 'dart:isolate';
diff --git a/runtime/tests/vm/dart_2/isolates/sum_recursive_call_ig_test.dart b/runtime/tests/vm/dart_2/isolates/sum_recursive_call_ig_test.dart
index 6b7eecb..915c102 100644
--- a/runtime/tests/vm/dart_2/isolates/sum_recursive_call_ig_test.dart
+++ b/runtime/tests/vm/dart_2/isolates/sum_recursive_call_ig_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit --disable-heap-verification
+// VMOptions=--enable-isolate-groups --disable-heap-verification
import 'dart:isolate';
diff --git a/runtime/tests/vm/dart_2/isolates/sum_recursive_call_test.dart b/runtime/tests/vm/dart_2/isolates/sum_recursive_call_test.dart
index 3b18008..89bcc58 100644
--- a/runtime/tests/vm/dart_2/isolates/sum_recursive_call_test.dart
+++ b/runtime/tests/vm/dart_2/isolates/sum_recursive_call_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit --disable-heap-verification
+// VMOptions=--enable-isolate-groups --disable-heap-verification
import 'dart:isolate';
diff --git a/runtime/tests/vm/dart_2/isolates/sum_recursive_tail_call_ig_test.dart b/runtime/tests/vm/dart_2/isolates/sum_recursive_tail_call_ig_test.dart
index bf1d165..a3fb967 100644
--- a/runtime/tests/vm/dart_2/isolates/sum_recursive_tail_call_ig_test.dart
+++ b/runtime/tests/vm/dart_2/isolates/sum_recursive_tail_call_ig_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit --disable-heap-verification
+// VMOptions=--enable-isolate-groups --disable-heap-verification
import 'dart:isolate';
diff --git a/runtime/tests/vm/dart_2/isolates/sum_recursive_tail_call_test.dart b/runtime/tests/vm/dart_2/isolates/sum_recursive_tail_call_test.dart
index a98cc91..866b8f3 100644
--- a/runtime/tests/vm/dart_2/isolates/sum_recursive_tail_call_test.dart
+++ b/runtime/tests/vm/dart_2/isolates/sum_recursive_tail_call_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit --disable-heap-verification
+// VMOptions=--enable-isolate-groups --disable-heap-verification
import 'dart:isolate';
diff --git a/runtime/tests/vm/dart_2/isolates/test_utils.dart b/runtime/tests/vm/dart_2/isolates/test_utils.dart
index 67b84d8..fdf47d7 100644
--- a/runtime/tests/vm/dart_2/isolates/test_utils.dart
+++ b/runtime/tests/vm/dart_2/isolates/test_utils.dart
@@ -10,6 +10,10 @@
final bool isDebugMode = Platform.script.path.contains('Debug');
final bool isSimulator = Platform.script.path.contains('SIM');
+final bool isArtificialReloadMode = Platform.executableArguments.any((arg) => [
+ '--hot-reload-rollback-test-mode',
+ '--hot-reload-test-mode'
+ ].contains(arg));
// Implements recursive summation:
// sum(n) => n == 0 ? 0
diff --git a/runtime/tests/vm/dart_2/isolates/thread_pool_test.dart b/runtime/tests/vm/dart_2/isolates/thread_pool_test.dart
index b0de784..695fda2 100644
--- a/runtime/tests/vm/dart_2/isolates/thread_pool_test.dart
+++ b/runtime/tests/vm/dart_2/isolates/thread_pool_test.dart
@@ -3,7 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
// SharedObjects=ffi_test_functions
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit --disable-heap-verification
+// VMOptions=--enable-isolate-groups --disable-heap-verification
import 'dart:async';
import 'dart:ffi';
diff --git a/runtime/tests/vm/dart_2/issue_31959_31960_test.dart b/runtime/tests/vm/dart_2/issue_31959_31960_test.dart
index b70bb0d..d63a16f 100644
--- a/runtime/tests/vm/dart_2/issue_31959_31960_test.dart
+++ b/runtime/tests/vm/dart_2/issue_31959_31960_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import 'dart:async';
diff --git a/runtime/tests/vm/dart_2/sendandexit_test.dart b/runtime/tests/vm/dart_2/sendandexit_test.dart
index 91d2bac..58e02c6 100644
--- a/runtime/tests/vm/dart_2/sendandexit_test.dart
+++ b/runtime/tests/vm/dart_2/sendandexit_test.dart
@@ -2,7 +2,7 @@
// 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.
//
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
//
// Validates functionality of sendAndExit.
diff --git a/runtime/tests/vm/dart_2/spawn_infinite_loop_test.dart b/runtime/tests/vm/dart_2/spawn_infinite_loop_test.dart
index 79409e0..3a89e80 100644
--- a/runtime/tests/vm/dart_2/spawn_infinite_loop_test.dart
+++ b/runtime/tests/vm/dart_2/spawn_infinite_loop_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import 'dart:isolate';
diff --git a/runtime/tests/vm/dart_2/transferable_test.dart b/runtime/tests/vm/dart_2/transferable_test.dart
index 48ea0ec..8daf5a0 100644
--- a/runtime/tests/vm/dart_2/transferable_test.dart
+++ b/runtime/tests/vm/dart_2/transferable_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// Test that validates that transferables are faster than regular typed data.
diff --git a/runtime/tests/vm/dart_2/transferable_throws_test.dart b/runtime/tests/vm/dart_2/transferable_throws_test.dart
index 95d1e09..fcb5bf7 100644
--- a/runtime/tests/vm/dart_2/transferable_throws_test.dart
+++ b/runtime/tests/vm/dart_2/transferable_throws_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// Test that ensures correct exceptions are thrown when misusing
@@ -11,7 +11,6 @@
import 'dart:async';
import 'dart:collection';
import 'dart:core';
-import 'dart:io';
import 'dart:isolate';
import 'dart:typed_data';
import 'dart:math';
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index 2cd1ed4..41a7490 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -15,6 +15,8 @@
dart/data_uri_import_test/none: SkipByDesign
dart/emit_aot_size_info_flag_test: Pass, Slow # Spawns several subprocesses
dart/isolates/*: Pass, Slow # Tests use many isolates and take a longer time.
+dart/isolates/concurrency_stress_sanity_test: Pass, Slow # Spawns subprocesses
+dart/isolates/fast_object_copy_test: Pass, Slow # Slow due to doing a lot of transitive object copies.
dart/minimal_kernel_test: Pass, Slow # Spawns several subprocesses
dart/null_safety_autodetection_in_kernel_compiler_test: Pass, Slow # Spawns several subprocesses
dart/slow_path_shared_stub_test: Pass, Slow # Uses --shared-slow-path-triggers-gc flag.
@@ -25,6 +27,8 @@
dart_2/data_uri_import_test/none: SkipByDesign
dart_2/emit_aot_size_info_flag_test: Pass, Slow # Spawns several subprocesses
dart_2/isolates/*: Pass, Slow # Tests use many isolates and take a longer time.
+dart_2/isolates/concurrency_stress_sanity_test: Pass, Slow # Spawns subprocesses
+dart_2/isolates/fast_object_copy_test: Pass, Slow # Slow due to doing a lot of transitive object copies.
dart_2/minimal_kernel_test: Pass, Slow # Spawns several subprocesses
dart_2/null_safety_autodetection_in_kernel_compiler_test: Pass, Slow # Spawns several subprocesses
dart_2/slow_path_shared_stub_test: Pass, Slow # Uses --shared-slow-path-triggers-gc flag.
@@ -144,20 +148,6 @@
[ $nnbd == legacy ]
dart/*: SkipByDesign # Migrated tests are not supposed to run on non-NNBD bots.
-[ $runtime == vm ]
-dart/isolates/*: Pass, Slow # https://dartbug.com/36097: Slower while isolate groups are being gradually enabled in JIT mode.
-dart/issue_31959_31960_test: Pass, Slow # https://dartbug.com/36097: Slower while isolate groups are being gradually enabled in JIT mode.
-dart/sendandexit_test: Pass, Slow # https://dartbug.com/36097: Slower while isolate groups are being gradually enabled in JIT mode.
-dart/spawn_infinite_loop_test: Pass, Slow # https://dartbug.com/36097: Slower while isolate groups are being gradually enabled in JIT mode.
-dart/transferable_test: Pass, Slow # https://dartbug.com/36097: Slower while isolate groups are being gradually enabled in JIT mode.
-dart/transferable_throws_test: Pass, Slow # https://dartbug.com/36097: Slower while isolate groups are being gradually enabled in JIT mode.
-dart_2/isolates/*: Pass, Slow # https://dartbug.com/36097: Slower while isolate groups are being gradually enabled in JIT mode.
-dart_2/issue_31959_31960_test: Pass, Slow # https://dartbug.com/36097: Slower while isolate groups are being gradually enabled in JIT mode.
-dart_2/sendandexit_test: Pass, Slow # https://dartbug.com/36097: Slower while isolate groups are being gradually enabled in JIT mode.
-dart_2/spawn_infinite_loop_test: Pass, Slow # https://dartbug.com/36097: Slower while isolate groups are being gradually enabled in JIT mode.
-dart_2/transferable_test: Pass, Slow # https://dartbug.com/36097: Slower while isolate groups are being gradually enabled in JIT mode.
-dart_2/transferable_throws_test: Pass, Slow # https://dartbug.com/36097: Slower while isolate groups are being gradually enabled in JIT mode.
-
[ $system == android ]
dart/isolates/dart_api_create_lightweight_isolate_test: SkipByDesign # On android this test does not work due to not being able to identify library uri.
dart/sdk_hash_test: SkipByDesign # The test doesn't know location of cross-platform gen_snapshot
@@ -436,34 +426,11 @@
[ $runtime != dart_precompiled || $system == android ]
dart/bare_instructions_trampolines_test: SkipByDesign # This test is for VM AOT only (android fails due to listing interfaces).
-dart/isolates/fibonacci_call_ig_test: Skip # Only AOT has lightweight enough isolates to run those tests, JIT work is pending.
-dart/isolates/fibonacci_call_test: Skip # Only AOT has lightweight enough isolates to run those tests.
-dart/isolates/internal: Skip # Only AOT has lightweight enough isolates to run those tests.
-dart/isolates/limited_active_mutator_test: Skip # Only AOT has lightweight enough isolates to run those tests.
-dart/isolates/ring_gc_sendAndExit_test: Skip # Only AOT has lightweight enough isolates to run those tests.
-dart/isolates/ring_gc_test: Skip # Only AOT has lightweight enough isolates to run those tests.
-dart/isolates/sum_recursive_call_ig_test: Skip # Only AOT has lightweight enough isolates to run those tests.
-dart/isolates/sum_recursive_call_test: Skip # Only AOT has lightweight enough isolates to run those tests.
-dart/isolates/sum_recursive_tail_call_ig_test: Skip # Only AOT has lightweight enough isolates to run those tests.
-dart/isolates/sum_recursive_tail_call_test: Skip # Only AOT has lightweight enough isolates to run those tests.
-dart/isolates/thread_pool_test: Skip # Only AOT has lightweight enough isolates to run those tests.
dart_2/bare_instructions_trampolines_test: SkipByDesign # This test is for VM AOT only (android fails due to listing interfaces).
-dart_2/isolates/fibonacci_call_ig_test: Skip # Only AOT has lightweight enough isolates to run those tests, JIT work is pending.
-dart_2/isolates/fibonacci_call_test: Skip # Only AOT has lightweight enough isolates to run those tests.
-dart_2/isolates/internal: Skip # Only AOT has lightweight enough isolates to run those tests.
-dart_2/isolates/limited_active_mutator_test: Skip # Only AOT has lightweight enough isolates to run those tests.
-dart_2/isolates/ring_gc_sendAndExit_test: Skip # Only AOT has lightweight enough isolates to run those tests.
-dart_2/isolates/ring_gc_test: Skip # Only AOT has lightweight enough isolates to run those tests.
-dart_2/isolates/sum_recursive_call_ig_test: Skip # Only AOT has lightweight enough isolates to run those tests.
-dart_2/isolates/sum_recursive_call_test: Skip # Only AOT has lightweight enough isolates to run those tests.
-dart_2/isolates/sum_recursive_tail_call_ig_test: Skip # Only AOT has lightweight enough isolates to run those tests.
-dart_2/isolates/sum_recursive_tail_call_test: Skip # Only AOT has lightweight enough isolates to run those tests.
-dart_2/isolates/thread_pool_test: Skip # Only AOT has lightweight enough isolates to run those tests.
[ $hot_reload || $hot_reload_rollback ]
dart/appjit*: SkipByDesign # Cannot reload with URI pointing to app snapshot.
dart/disassemble_determinism_test: SkipSlow # Runs expensive fibonacci(32) computation in 2 subprocesses
-dart/isolates/spawn_function_test: Skip # This test explicitly enables isolate groups (off-by-default atm). It will be enabled once full IG reloading is implemented.
dart/issue_31959_31960_test: SkipSlow
dart/minimal_kernel_test: SkipSlow # gen_kernel is too slow in hot reload testing mode
dart/null_safety_autodetection_in_kernel_compiler_test: SkipSlow # gen_kernel is too slow in hot reload testing mode
@@ -475,7 +442,6 @@
dart/stack_overflow_shared_test: SkipSlow # Too slow with --shared-slow-path-triggers-gc flag and not relevant outside precompiled.
dart_2/appjit*: SkipByDesign # Cannot reload with URI pointing to app snapshot.
dart_2/disassemble_determinism_test: SkipSlow # Runs expensive fibonacci(32) computation in 2 subprocesses
-dart_2/isolates/spawn_function_test: Skip # This test explicitly enables isolate groups (off-by-default atm). It will be enabled once full IG reloading is implemented.
dart_2/issue_31959_31960_test: SkipSlow
dart_2/minimal_kernel_test: SkipSlow # gen_kernel is too slow in hot reload testing mode
dart_2/null_safety_autodetection_in_kernel_compiler_test: SkipSlow # gen_kernel is too slow in hot reload testing mode
diff --git a/runtime/tools/dartfuzz/dartfuzz_test.dart b/runtime/tools/dartfuzz/dartfuzz_test.dart
index 639935b..fb826ff 100644
--- a/runtime/tools/dartfuzz/dartfuzz_test.dart
+++ b/runtime/tools/dartfuzz/dartfuzz_test.dart
@@ -420,7 +420,6 @@
timeoutSeeds.add(seed);
break;
default:
- reportDivergence(result1, result2);
// Both had an error.
numSkipped++;
skippedSeeds.add(seed);
@@ -472,9 +471,7 @@
var report = generateReport(result1, result2);
print('\n$isolate: !DIVERGENCE! $version:$seed ($report)');
if (result1.exitCode == result2.exitCode) {
- if (result1.exitCode == 254) {
- print('\ncompile-time error:\n${result1.output}\n${result1.stderr}\n');
- } else if (numOutputLines > 0) {
+ if (numOutputLines > 0) {
// Only report the actual output divergence details up to
// numOutputLines, since this output may be lengthy and should be
// reproducable anyway.
diff --git a/runtime/tools/dartfuzz/gen_api_table.dart b/runtime/tools/dartfuzz/gen_api_table.dart
index 869bfc3..365a50a 100644
--- a/runtime/tools/dartfuzz/gen_api_table.dart
+++ b/runtime/tools/dartfuzz/gen_api_table.dart
@@ -348,7 +348,7 @@
final libPath = session.uriConverter.uriToPath(Uri.parse(uri));
var result = await session.getResolvedLibrary2(libPath!);
if (result is ResolvedLibraryResult) {
- visitLibrary(result.element!);
+ visitLibrary(result.element);
} else {
throw StateError('Unable to resolve "$uri"');
}
diff --git a/runtime/tools/dartfuzz/gen_type_table.dart b/runtime/tools/dartfuzz/gen_type_table.dart
index ea2ac48..0f2599a 100644
--- a/runtime/tools/dartfuzz/gen_type_table.dart
+++ b/runtime/tools/dartfuzz/gen_type_table.dart
@@ -1342,7 +1342,7 @@
var libPath = session.uriConverter.uriToPath(Uri.parse(uri));
var result = await session.getResolvedLibrary2(libPath!);
if (result is ResolvedLibraryResult) {
- visitLibrary(result.element!, allTypes);
+ visitLibrary(result.element, allTypes);
} else {
throw StateError('Unable to resolve "$uri"');
}
diff --git a/runtime/vm/allocation.cc b/runtime/vm/allocation.cc
index aa36221..4239026 100644
--- a/runtime/vm/allocation.cc
+++ b/runtime/vm/allocation.cc
@@ -24,7 +24,6 @@
}
void* ZoneAllocated::operator new(uword size, Zone* zone) {
- ASSERT(Thread::Current()->ZoneIsOwnedByThread(zone));
return Allocate(size, zone);
}
diff --git a/runtime/vm/benchmark_test.cc b/runtime/vm/benchmark_test.cc
index ee64cc5..2b5683b 100644
--- a/runtime/vm/benchmark_test.cc
+++ b/runtime/vm/benchmark_test.cc
@@ -18,6 +18,7 @@
#include "vm/clustered_snapshot.h"
#include "vm/dart_api_impl.h"
#include "vm/datastream.h"
+#include "vm/message_snapshot.h"
#include "vm/stack_frame.h"
#include "vm/timer.h"
@@ -256,8 +257,8 @@
// Measure compile of all kernel Service(CFE) functions.
//
BENCHMARK(KernelServiceCompileAll) {
- if (FLAG_sound_null_safety == kNullSafetyOptionStrong) {
- // TODO(bkonyi): remove this check when we build the CFE in strong mode.
+ // kernel_service.dill is built with sound null safety.
+ if (FLAG_sound_null_safety != kNullSafetyOptionStrong) {
return;
}
bin::Builtin::SetNativeResolver(bin::Builtin::kBuiltinLibrary);
@@ -517,13 +518,12 @@
timer.Start();
for (intptr_t i = 0; i < kLoopCount; i++) {
StackZone zone(thread);
- MessageWriter writer(true);
- std::unique_ptr<Message> message = writer.WriteMessage(
- null_object, ILLEGAL_PORT, Message::kNormalPriority);
+ std::unique_ptr<Message> message =
+ WriteMessage(/* can_send_any_object */ true, null_object, ILLEGAL_PORT,
+ Message::kNormalPriority);
// Read object back from the snapshot.
- MessageSnapshotReader reader(message.get(), thread);
- reader.ReadObject();
+ ReadMessage(thread, message.get());
}
timer.Stop();
int64_t elapsed_time = timer.TotalElapsedTime();
@@ -540,13 +540,12 @@
timer.Start();
for (intptr_t i = 0; i < kLoopCount; i++) {
StackZone zone(thread);
- MessageWriter writer(true);
std::unique_ptr<Message> message =
- writer.WriteMessage(smi_object, ILLEGAL_PORT, Message::kNormalPriority);
+ WriteMessage(/* can_send_any_object */ true, smi_object, ILLEGAL_PORT,
+ Message::kNormalPriority);
// Read object back from the snapshot.
- MessageSnapshotReader reader(message.get(), thread);
- reader.ReadObject();
+ ReadMessage(thread, message.get());
}
timer.Stop();
int64_t elapsed_time = timer.TotalElapsedTime();
@@ -565,13 +564,12 @@
timer.Start();
for (intptr_t i = 0; i < kLoopCount; i++) {
StackZone zone(thread);
- MessageWriter writer(true);
- std::unique_ptr<Message> message = writer.WriteMessage(
- array_object, ILLEGAL_PORT, Message::kNormalPriority);
+ std::unique_ptr<Message> message = WriteMessage(
+ /* can_send_any_object */ true, array_object, ILLEGAL_PORT,
+ Message::kNormalPriority);
// Read object back from the snapshot.
- MessageSnapshotReader reader(message.get(), thread);
- reader.ReadObject();
+ ReadMessage(thread, message.get());
}
timer.Stop();
int64_t elapsed_time = timer.TotalElapsedTime();
@@ -599,13 +597,12 @@
timer.Start();
for (intptr_t i = 0; i < kLoopCount; i++) {
StackZone zone(thread);
- MessageWriter writer(true);
std::unique_ptr<Message> message =
- writer.WriteMessage(map, ILLEGAL_PORT, Message::kNormalPriority);
+ WriteMessage(/* can_send_any_object */ true, map, ILLEGAL_PORT,
+ Message::kNormalPriority);
// Read object back from the snapshot.
- MessageSnapshotReader reader(message.get(), thread);
- reader.ReadObject();
+ ReadMessage(thread, message.get());
}
timer.Stop();
int64_t elapsed_time = timer.TotalElapsedTime();
diff --git a/runtime/vm/bitfield.h b/runtime/vm/bitfield.h
index f96a34e..d6f60c7 100644
--- a/runtime/vm/bitfield.h
+++ b/runtime/vm/bitfield.h
@@ -226,22 +226,6 @@
void>::type>
: public BitField<typename S::ContainedType, T, position, size, false> {};
-template <typename S, typename T, int position>
-class BitField<S,
- T,
- position,
- (sizeof(S) * kBitsPerByte) - position,
- false,
- typename std::enable_if<
- std::is_base_of<AtomicBitFieldContainerBase, S>::value,
- void>::type>
- : public BitField<typename S::ContainedType,
- T,
- position,
- (sizeof(typename S::ContainedType) * kBitsPerByte) -
- position,
- false> {};
-
} // namespace dart
#endif // RUNTIME_VM_BITFIELD_H_
diff --git a/runtime/vm/bitmap.h b/runtime/vm/bitmap.h
index 186f1e6..74c4c5b 100644
--- a/runtime/vm/bitmap.h
+++ b/runtime/vm/bitmap.h
@@ -22,7 +22,9 @@
}
BitmapBuilder(const BitmapBuilder& other)
- : length_(other.length_), data_size_in_bytes_(other.data_size_in_bytes_) {
+ : ZoneAllocated(),
+ length_(other.length_),
+ data_size_in_bytes_(other.data_size_in_bytes_) {
if (data_size_in_bytes_ == kInlineCapacityInBytes) {
memmove(data_.inline_, other.data_.inline_, kInlineCapacityInBytes);
} else {
diff --git a/runtime/vm/bootstrap.cc b/runtime/vm/bootstrap.cc
index 5e3ddd7..20d63d2 100644
--- a/runtime/vm/bootstrap.cc
+++ b/runtime/vm/bootstrap.cc
@@ -128,6 +128,8 @@
// Finish bootstrapping, including class finalization.
Finish(thread);
+ isolate_group->object_store()->InitKnownObjects();
+
// The platform binary may contain other libraries (e.g., dart:_builtin or
// dart:io) that will not be bundled with application. Load them now.
const Object& result = Object::Handle(zone, loader.LoadProgram());
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index 7eb3452..e9710df6 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -344,6 +344,7 @@
V(Internal_allocateTwoByteString, 1) \
V(Internal_writeIntoOneByteString, 3) \
V(Internal_writeIntoTwoByteString, 3) \
+ V(Internal_deoptimizeFunctionsOnStack, 0) \
V(InvocationMirror_unpackTypeArguments, 2) \
V(NoSuchMethodError_existingMethodSignature, 3) \
V(WeakProperty_getKey, 1) \
diff --git a/runtime/vm/canonical_tables.h b/runtime/vm/canonical_tables.h
index b0e25b5..ba9297e 100644
--- a/runtime/vm/canonical_tables.h
+++ b/runtime/vm/canonical_tables.h
@@ -131,7 +131,8 @@
return concat.ToSymbol();
}
};
-typedef UnorderedHashSet<SymbolTraits> CanonicalStringSet;
+
+typedef UnorderedHashSet<SymbolTraits, AcqRelStorageTraits> CanonicalStringSet;
class CanonicalTypeKey {
public:
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index d296cc7cb..8e2fb4b 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -239,33 +239,35 @@
#if defined(DEBUG)
// Basic checking.
cls = object_store->object_class();
- ASSERT(Instance::InstanceSize() == cls.host_instance_size());
+ ASSERT_EQUAL(Instance::InstanceSize(), cls.host_instance_size());
cls = object_store->integer_implementation_class();
- ASSERT(Integer::InstanceSize() == cls.host_instance_size());
+ ASSERT_EQUAL(Integer::InstanceSize(), cls.host_instance_size());
cls = object_store->smi_class();
- ASSERT(Smi::InstanceSize() == cls.host_instance_size());
+ ASSERT_EQUAL(Smi::InstanceSize(), cls.host_instance_size());
cls = object_store->mint_class();
- ASSERT(Mint::InstanceSize() == cls.host_instance_size());
+ ASSERT_EQUAL(Mint::InstanceSize(), cls.host_instance_size());
cls = object_store->one_byte_string_class();
- ASSERT(OneByteString::InstanceSize() == cls.host_instance_size());
+ ASSERT_EQUAL(OneByteString::InstanceSize(), cls.host_instance_size());
cls = object_store->two_byte_string_class();
- ASSERT(TwoByteString::InstanceSize() == cls.host_instance_size());
+ ASSERT_EQUAL(TwoByteString::InstanceSize(), cls.host_instance_size());
cls = object_store->external_one_byte_string_class();
- ASSERT(ExternalOneByteString::InstanceSize() == cls.host_instance_size());
+ ASSERT_EQUAL(ExternalOneByteString::InstanceSize(), cls.host_instance_size());
cls = object_store->external_two_byte_string_class();
- ASSERT(ExternalTwoByteString::InstanceSize() == cls.host_instance_size());
+ ASSERT_EQUAL(ExternalTwoByteString::InstanceSize(), cls.host_instance_size());
cls = object_store->double_class();
- ASSERT(Double::InstanceSize() == cls.host_instance_size());
+ ASSERT_EQUAL(Double::InstanceSize(), cls.host_instance_size());
cls = object_store->bool_class();
- ASSERT(Bool::InstanceSize() == cls.host_instance_size());
+ ASSERT_EQUAL(Bool::InstanceSize(), cls.host_instance_size());
cls = object_store->array_class();
- ASSERT(Array::InstanceSize() == cls.host_instance_size());
+ ASSERT_EQUAL(Array::InstanceSize(), cls.host_instance_size());
cls = object_store->immutable_array_class();
- ASSERT(ImmutableArray::InstanceSize() == cls.host_instance_size());
+ ASSERT_EQUAL(ImmutableArray::InstanceSize(), cls.host_instance_size());
cls = object_store->weak_property_class();
- ASSERT(WeakProperty::InstanceSize() == cls.host_instance_size());
+ ASSERT_EQUAL(WeakProperty::InstanceSize(), cls.host_instance_size());
cls = object_store->linked_hash_map_class();
- ASSERT(LinkedHashMap::InstanceSize() == cls.host_instance_size());
+ ASSERT_EQUAL(LinkedHashMap::InstanceSize(), cls.host_instance_size());
+ cls = object_store->linked_hash_set_class();
+ ASSERT_EQUAL(LinkedHashMap::InstanceSize(), cls.host_instance_size());
#endif // defined(DEBUG)
// Remember the currently pending classes.
@@ -1455,10 +1457,6 @@
RemapClassIds(old_to_new_cid.get());
RehashTypes(); // Types use cid's as part of their hashes.
IG->RehashConstants(); // Const objects use cid's as part of their hashes.
-
- // Ensure any newly spawned isolate will apply this permutation map right
- // after kernel loading.
- IG->source()->cid_permutation_map = std::move(old_to_new_cid);
}
class CidRewriteVisitor : public ObjectVisitor {
@@ -1759,7 +1757,8 @@
if (including_nonchanging_cids) {
auto object_store = isolate_group->object_store();
auto& null_code = Code::Handle(zone);
- object_store->set_build_method_extractor_code(null_code);
+ object_store->set_build_generic_method_extractor_code(null_code);
+ object_store->set_build_nongeneric_method_extractor_code(null_code);
}
}
diff --git a/runtime/vm/class_id.h b/runtime/vm/class_id.h
index 2fbc03f..5a41a68 100644
--- a/runtime/vm/class_id.h
+++ b/runtime/vm/class_id.h
@@ -17,7 +17,7 @@
// Size of the class-id part of the object header. See UntaggedObject.
typedef uint16_t ClassIdTagType;
-#define CLASS_LIST_NO_OBJECT_NOR_STRING_NOR_ARRAY(V) \
+#define CLASS_LIST_NO_OBJECT_NOR_STRING_NOR_ARRAY_NOR_MAP(V) \
V(Class) \
V(PatchClass) \
V(Function) \
@@ -88,11 +88,16 @@
V(RegExp) \
V(WeakProperty) \
V(MirrorReference) \
- V(LinkedHashMap) \
V(FutureOr) \
V(UserTag) \
V(TransferableTypedData)
+// TODO(http://dartbug.com/45908): Add ImmutableLinkedHashMap.
+#define CLASS_LIST_MAPS(V) V(LinkedHashMap)
+
+// TODO(http://dartbug.com/45908): Add ImmutableLinkedHashSet.
+#define CLASS_LIST_SETS(V) V(LinkedHashSet)
+
#define CLASS_LIST_ARRAYS(V) \
V(Array) \
V(ImmutableArray)
@@ -163,12 +168,16 @@
V(Float64x2)
#define CLASS_LIST_FOR_HANDLES(V) \
- CLASS_LIST_NO_OBJECT_NOR_STRING_NOR_ARRAY(V) \
+ CLASS_LIST_NO_OBJECT_NOR_STRING_NOR_ARRAY_NOR_MAP(V) \
+ V(LinkedHashMap) \
+ V(LinkedHashSet) \
V(Array) \
V(String)
#define CLASS_LIST_NO_OBJECT(V) \
- CLASS_LIST_NO_OBJECT_NOR_STRING_NOR_ARRAY(V) \
+ CLASS_LIST_NO_OBJECT_NOR_STRING_NOR_ARRAY_NOR_MAP(V) \
+ CLASS_LIST_MAPS(V) \
+ CLASS_LIST_SETS(V) \
CLASS_LIST_ARRAYS(V) \
CLASS_LIST_STRINGS(V)
diff --git a/runtime/vm/class_table.cc b/runtime/vm/class_table.cc
index ccba236..b5491bb 100644
--- a/runtime/vm/class_table.cc
+++ b/runtime/vm/class_table.cc
@@ -519,10 +519,17 @@
// This is called by snapshot reader and class finalizer.
ASSERT(cid < capacity_);
+ UpdateClassSize(cid, raw_cls);
+ table_.load()[cid] = raw_cls;
+}
+
+void ClassTable::UpdateClassSize(intptr_t cid, ClassPtr raw_cls) {
+ ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
+ ASSERT(!IsTopLevelCid(cid)); // "top-level" classes don't get instantiated
+ ASSERT(cid < capacity_);
const intptr_t size =
raw_cls == nullptr ? 0 : Class::host_instance_size(raw_cls);
shared_class_table_->SetSizeAt(cid, size);
- table_.load()[cid] = raw_cls;
}
#ifndef PRODUCT
diff --git a/runtime/vm/class_table.h b/runtime/vm/class_table.h
index 5ef0df1..e89b978 100644
--- a/runtime/vm/class_table.h
+++ b/runtime/vm/class_table.h
@@ -354,6 +354,7 @@
}
void SetAt(intptr_t index, ClassPtr raw_cls);
+ void UpdateClassSize(intptr_t cid, ClassPtr raw_cls);
bool IsValidIndex(intptr_t cid) const {
if (IsTopLevelCid(cid)) {
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index 55d5b84..b3beb4d 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -16,6 +16,7 @@
#include "vm/compiler/api/print_filter.h"
#include "vm/compiler/assembler/disassembler.h"
#include "vm/dart.h"
+#include "vm/dart_entry.h"
#include "vm/dispatch_table.h"
#include "vm/flag_list.h"
#include "vm/growable_array.h"
@@ -114,6 +115,14 @@
}
static bool IsImmutable(const ArrayHandle& handle) { return false; }
+
+ static ObjectPtr At(ArrayHandle* array, intptr_t index) {
+ return array->At(index);
+ }
+
+ static void SetAt(ArrayHandle* array, intptr_t index, const Object& value) {
+ array->SetAt(index, value);
+ }
};
} // namespace
@@ -3245,25 +3254,6 @@
cache->untag()->filled_entry_count_ = d->Read<int32_t>();
}
}
-
-#if defined(DART_PRECOMPILED_RUNTIME)
- void PostLoad(Deserializer* d, const Array& refs, bool primary) {
- if (FLAG_use_bare_instructions) {
- // By default, every megamorphic call site will load the target
- // [Function] from the hash table and call indirectly via loading the
- // entrypoint from the function.
- //
- // In --use-bare-instruction we reduce the extra indirection via the
- // [Function] object by storing the entry point directly into the hashmap.
- //
- auto& cache = MegamorphicCache::Handle(d->zone());
- for (intptr_t i = start_index_; i < stop_index_; ++i) {
- cache ^= refs.At(i);
- cache.SwitchToBareInstructions();
- }
- }
- }
-#endif // defined(DART_PRECOMPILED_RUNTIME)
};
#if !defined(DART_PRECOMPILED_RUNTIME)
@@ -5600,6 +5590,10 @@
OBJECT_STORE_FIELD_LIST(DECLARE_OBJECT_STORE_FIELD,
DECLARE_OBJECT_STORE_FIELD,
DECLARE_OBJECT_STORE_FIELD,
+ DECLARE_OBJECT_STORE_FIELD,
+ DECLARE_OBJECT_STORE_FIELD,
+ DECLARE_OBJECT_STORE_FIELD,
+ DECLARE_OBJECT_STORE_FIELD,
DECLARE_OBJECT_STORE_FIELD)
#undef DECLARE_OBJECT_STORE_FIELD
};
@@ -5743,7 +5737,10 @@
void PostLoad(Deserializer* d, const Array& refs) {
auto isolate_group = d->isolate_group();
- isolate_group->class_table()->CopySizesFromClassObjects();
+ {
+ SafepointWriteRwLocker ml(d->thread(), isolate_group->program_lock());
+ isolate_group->class_table()->CopySizesFromClassObjects();
+ }
d->heap()->old_space()->EvaluateAfterLoading();
const Array& units =
@@ -6473,7 +6470,11 @@
case kWeakPropertyCid:
return new (Z) WeakPropertySerializationCluster();
case kLinkedHashMapCid:
- return new (Z) LinkedHashMapSerializationCluster();
+ // We do not have mutable hash maps in snapshots.
+ UNREACHABLE();
+ case kLinkedHashSetCid:
+ // We do not have mutable hash sets in snapshots.
+ UNREACHABLE();
case kArrayCid:
return new (Z) ArraySerializationCluster(is_canonical, kArrayCid);
case kImmutableArrayCid:
@@ -7113,6 +7114,7 @@
buffer.Printf(" %10s", "Cumulative");
buffer.Printf(" %8s", "HeapSize");
buffer.Printf(" %5s", "Cid");
+ buffer.Printf(" %9s", "Canonical");
buffer.AddString("\n");
GrowableArray<SerializationCluster*> clusters_by_size;
for (intptr_t cid = 1; cid < num_cids_; cid++) {
@@ -7179,6 +7181,11 @@
} else {
buffer.Printf(" %5s", "");
}
+ if (cluster->is_canonical()) {
+ buffer.Printf(" %9s", "canonical");
+ } else {
+ buffer.Printf(" %9s", "");
+ }
buffer.AddString("\n");
}
OS::PrintErr("%s", buffer.buffer());
@@ -7380,7 +7387,11 @@
ASSERT(!is_canonical);
return new (Z) WeakPropertyDeserializationCluster();
case kLinkedHashMapCid:
- return new (Z) LinkedHashMapDeserializationCluster(is_canonical);
+ // We do not have mutable hash maps in snapshots.
+ UNREACHABLE();
+ case kLinkedHashSetCid:
+ // We do not have mutable hash sets in snapshots.
+ UNREACHABLE();
case kArrayCid:
return new (Z) ArrayDeserializationCluster(is_canonical, kArrayCid);
case kImmutableArrayCid:
@@ -7805,6 +7816,7 @@
{
TIMELINE_DURATION(thread(), Isolate, "ReadFill");
+ SafepointWriteRwLocker ml(thread(), isolate_group()->program_lock());
for (intptr_t i = 0; i < num_clusters_; i++) {
TIMELINE_DURATION(thread(), Isolate, clusters_[i]->name());
clusters_[i]->ReadFill(this, primary);
diff --git a/runtime/vm/clustered_snapshot.h b/runtime/vm/clustered_snapshot.h
index 9dab2b8..d80cb7453 100644
--- a/runtime/vm/clustered_snapshot.h
+++ b/runtime/vm/clustered_snapshot.h
@@ -440,7 +440,7 @@
V8SnapshotProfileWriter* profile_writer() const { return profile_writer_; }
- // If the given [obj] was not included into the snaposhot and have not
+ // If the given [obj] was not included into the snapshot and have not
// yet gotten an artificial node created for it create an artificial node
// in the profile representing this object.
// Returns true if [obj] has an artificial profile node associated with it.
diff --git a/runtime/vm/code_descriptors.h b/runtime/vm/code_descriptors.h
index 0d15c38..ac29be7 100644
--- a/runtime/vm/code_descriptors.h
+++ b/runtime/vm/code_descriptors.h
@@ -209,7 +209,7 @@
using ArgField = BitField<int32_t, int32_t, OpField::kNextBit>;
static constexpr int32_t kMaxArgValue =
- Utils::NBitMaskUnsafe(ArgField::bitsize() - 1);
+ Utils::NBitMask<int32_t>(ArgField::bitsize() - 1);
static constexpr int32_t kMinArgValue = ~kMaxArgValue;
static constexpr int32_t kSignBits = static_cast<uint32_t>(kMinArgValue) << 1;
};
diff --git a/runtime/vm/compiler/aot/precompiler.cc b/runtime/vm/compiler/aot/precompiler.cc
index 99d4c22..35ca895 100644
--- a/runtime/vm/compiler/aot/precompiler.cc
+++ b/runtime/vm/compiler/aot/precompiler.cc
@@ -522,10 +522,18 @@
{
SafepointWriteRwLocker ml(T, T->isolate_group()->program_lock());
- stub_code = StubCode::GetBuildMethodExtractorStub(
+ stub_code = StubCode::GetBuildGenericMethodExtractorStub(
global_object_pool_builder());
}
- IG->object_store()->set_build_method_extractor_code(stub_code);
+ IG->object_store()->set_build_generic_method_extractor_code(stub_code);
+
+ {
+ SafepointWriteRwLocker ml(T, T->isolate_group()->program_lock());
+ stub_code = StubCode::GetBuildNonGenericMethodExtractorStub(
+ global_object_pool_builder());
+ }
+ IG->object_store()->set_build_nongeneric_method_extractor_code(
+ stub_code);
}
CollectDynamicFunctionNames();
@@ -604,7 +612,6 @@
IG->object_store()->set_pragma_name(null_field);
IG->object_store()->set_pragma_options(null_field);
IG->object_store()->set_completer_class(null_class);
- IG->object_store()->set_symbol_class(null_class);
IG->object_store()->set_compiletime_error_class(null_class);
IG->object_store()->set_growable_list_factory(null_function);
IG->object_store()->set_simple_instance_of_function(null_function);
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.cc b/runtime/vm/compiler/assembler/assembler_arm64.cc
index 7e9299f..3502a6e 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm64.cc
@@ -250,6 +250,22 @@
label->BindTo(bound_pc, lr_state());
}
+#if defined(USING_THREAD_SANITIZER)
+void Assembler::TsanLoadAcquire(Register addr) {
+ EnterCallRuntimeFrame(/*frame_size=*/0, /*is_leaf=*/true);
+ ASSERT(kTsanLoadAcquireRuntimeEntry.is_leaf());
+ CallRuntime(kTsanLoadAcquireRuntimeEntry, /*argument_count=*/1);
+ LeaveCallRuntimeFrame(/*is_leaf=*/true);
+}
+
+void Assembler::TsanStoreRelease(Register addr) {
+ EnterCallRuntimeFrame(/*frame_size=*/0, /*is_leaf=*/true);
+ ASSERT(kTsanStoreReleaseRuntimeEntry.is_leaf());
+ CallRuntime(kTsanStoreReleaseRuntimeEntry, /*argument_count=*/1);
+ LeaveCallRuntimeFrame(/*is_leaf=*/true);
+}
+#endif
+
static int CountLeadingZeros(uint64_t value, int width) {
if (width == 64) return Utils::CountLeadingZeros64(value);
if (width == 32) return Utils::CountLeadingZeros32(value);
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.h b/runtime/vm/compiler/assembler/assembler_arm64.h
index f99eb33..596ee9d 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.h
+++ b/runtime/vm/compiler/assembler/assembler_arm64.h
@@ -557,22 +557,56 @@
void StoreMemoryValue(Register src, Register base, int32_t offset) {
StoreToOffset(src, base, offset, kEightBytes);
}
+
+#if defined(USING_THREAD_SANITIZER)
+ void TsanLoadAcquire(Register addr);
+ void TsanStoreRelease(Register addr);
+#endif
+
void LoadAcquire(Register dst, Register address, int32_t offset = 0) {
if (offset != 0) {
AddImmediate(TMP2, address, offset);
ldar(dst, TMP2);
+#if defined(USING_THREAD_SANITIZER)
+ TsanLoadAcquire(TMP2);
+#endif
} else {
ldar(dst, address);
+#if defined(USING_THREAD_SANITIZER)
+ TsanLoadAcquire(address);
+#endif
}
}
+
void LoadAcquireCompressed(Register dst,
Register address,
int32_t offset = 0) {
if (offset != 0) {
AddImmediate(TMP2, address, offset);
ldar(dst, TMP2, kObjectBytes);
+#if defined(USING_THREAD_SANITIZER)
+ TsanLoadAcquire(TMP2);
+#endif
} else {
ldar(dst, address, kObjectBytes);
+#if defined(USING_THREAD_SANITIZER)
+ TsanLoadAcquire(address);
+#endif
+ }
+ }
+
+ void StoreRelease(Register dst, Register address, int32_t offset = 0) {
+ if (offset != 0) {
+ AddImmediate(TMP2, address, offset);
+ stlr(dst, TMP2);
+#if defined(USING_THREAD_SANITIZER)
+ TsanStoreRelease(TMP2);
+#endif
+ } else {
+ stlr(dst, address);
+#if defined(USING_THREAD_SANITIZER)
+ TsanStoreRelease(address);
+#endif
}
}
diff --git a/runtime/vm/compiler/assembler/assembler_arm64_test.cc b/runtime/vm/compiler/assembler/assembler_arm64_test.cc
index 53d2adf..03f8341 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64_test.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm64_test.cc
@@ -4737,8 +4737,8 @@
__ mov(THR, R2);
__ ldr(HEAP_BITS, Address(THR, Thread::write_barrier_mask_offset()));
__ LslImmediate(HEAP_BITS, HEAP_BITS, 32);
- __ StoreIntoObject(R1, FieldAddress(R1, GrowableObjectArray::data_offset()),
- R0);
+ __ StoreCompressedIntoObject(
+ R1, FieldAddress(R1, GrowableObjectArray::data_offset()), R0);
RESTORES_LR_FROM_FRAME(__ Pop(LR));
__ Pop(HEAP_BITS);
__ Pop(THR);
@@ -4855,6 +4855,54 @@
EXECUTE_TEST_CODE_INTPTR_INTPTR(IntPtrReturn, test->entry(), -511));
}
+#if !defined(USING_THREAD_SANITIZER)
+// can't call (tsan) runtime methods
+
+ASSEMBLER_TEST_GENERATE(StoreReleaseLoadAcquire, assembler) {
+ __ SetupDartSP();
+ __ Push(R1);
+ __ LoadImmediate(R1, 0);
+ __ Push(R1);
+ __ mov(R1, R0);
+ __ LoadImmediate(R0, 0);
+ __ StoreRelease(R1, SP, 0);
+ __ LoadAcquire(R0, SP, 0);
+ __ Pop(R1);
+ __ Pop(R1);
+ __ RestoreCSP();
+ __ ret();
+}
+
+ASSEMBLER_TEST_RUN(StoreReleaseLoadAcquire, test) {
+ typedef intptr_t (*StoreReleaseLoadAcquire)(intptr_t) DART_UNUSED;
+ EXPECT_EQ(123, EXECUTE_TEST_CODE_INTPTR_INTPTR(StoreReleaseLoadAcquire,
+ test->entry(), 123));
+}
+
+ASSEMBLER_TEST_GENERATE(StoreReleaseLoadAcquire1024, assembler) {
+ __ SetupDartSP();
+ __ Push(R1);
+ __ LoadImmediate(R1, 0);
+ __ Push(R1);
+ __ mov(R1, R0);
+ __ LoadImmediate(R0, 0);
+ __ sub(SP, SP, Operand(1024 * target::kWordSize));
+ __ StoreRelease(R1, SP, 1024);
+ __ LoadAcquire(R0, SP, 1024);
+ __ add(SP, SP, Operand(1024 * target::kWordSize));
+ __ Pop(R1);
+ __ Pop(R1);
+ __ RestoreCSP();
+ __ ret();
+}
+
+ASSEMBLER_TEST_RUN(StoreReleaseLoadAcquire1024, test) {
+ typedef intptr_t (*StoreReleaseLoadAcquire1024)(intptr_t) DART_UNUSED;
+ EXPECT_EQ(123, EXECUTE_TEST_CODE_INTPTR_INTPTR(StoreReleaseLoadAcquire1024,
+ test->entry(), 123));
+}
+#endif
+
} // namespace compiler
} // namespace dart
diff --git a/runtime/vm/compiler/assembler/assembler_base.h b/runtime/vm/compiler/assembler/assembler_base.h
index 55258dc..1f22998 100644
--- a/runtime/vm/compiler/assembler/assembler_base.h
+++ b/runtime/vm/compiler/assembler/assembler_base.h
@@ -193,7 +193,7 @@
// 64-bit ARM specific constants.
kQWord,
-#if defined(TARGET_ARCH_IS_64_BIT) && !defined(DART_COMPRESSED_POINTERS)
+#if defined(HAS_SMI_63_BITS)
kObjectBytes = kEightBytes,
#else
kObjectBytes = kFourBytes,
diff --git a/runtime/vm/compiler/assembler/assembler_test.cc b/runtime/vm/compiler/assembler/assembler_test.cc
index 8488eae..16342bd 100644
--- a/runtime/vm/compiler/assembler/assembler_test.cc
+++ b/runtime/vm/compiler/assembler/assembler_test.cc
@@ -38,7 +38,8 @@
for (int i = -128; i < 128; i++) {
smi = Smi::New(i);
TEST_CODE(smi.ptr(), grow_old_array.ptr(), thread);
- EXPECT(static_cast<ArrayPtr>(smi.ptr()) == grow_old_array.data());
+ EXPECT(static_cast<CompressedObjectPtr>(smi.ptr()) ==
+ static_cast<CompressedObjectPtr>(grow_old_array.data()));
EXPECT(!thread->StoreBufferContains(grow_old_array.ptr()));
}
diff --git a/runtime/vm/compiler/assembler/assembler_x64.cc b/runtime/vm/compiler/assembler/assembler_x64.cc
index 8bc3290..22b6673 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.cc
+++ b/runtime/vm/compiler/assembler/assembler_x64.cc
@@ -1876,6 +1876,24 @@
entry.Call(this, argument_count);
}
+#if defined(USING_THREAD_SANITIZER)
+void Assembler::TsanLoadAcquire(Address addr) {
+ PushRegisters(kVolatileRegisterSet);
+ leaq(CallingConventions::kArg1Reg, addr);
+ ASSERT(kTsanLoadAcquireRuntimeEntry.is_leaf());
+ CallRuntime(kTsanLoadAcquireRuntimeEntry, /*argument_count=*/1);
+ PopRegisters(kVolatileRegisterSet);
+}
+
+void Assembler::TsanStoreRelease(Address addr) {
+ PushRegisters(kVolatileRegisterSet);
+ leaq(CallingConventions::kArg1Reg, addr);
+ ASSERT(kTsanStoreReleaseRuntimeEntry.is_leaf());
+ CallRuntime(kTsanStoreReleaseRuntimeEntry, /*argument_count=*/1);
+ PopRegisters(kVolatileRegisterSet);
+}
+#endif
+
void Assembler::RestoreCodePointer() {
movq(CODE_REG,
Address(RBP, target::frame_layout.code_from_fp * target::kWordSize));
diff --git a/runtime/vm/compiler/assembler/assembler_x64.h b/runtime/vm/compiler/assembler/assembler_x64.h
index c9fb518..27b45dd 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.h
+++ b/runtime/vm/compiler/assembler/assembler_x64.h
@@ -1027,10 +1027,19 @@
void StoreMemoryValue(Register src, Register base, int32_t offset) {
movq(Address(base, offset), src);
}
+
+#if defined(USING_THREAD_SANITIZER)
+ void TsanLoadAcquire(Address addr);
+ void TsanStoreRelease(Address addr);
+#endif
+
void LoadAcquire(Register dst, Register address, int32_t offset = 0) {
// On intel loads have load-acquire behavior (i.e. loads are not re-ordered
// with other loads).
movq(dst, Address(address, offset));
+#if defined(USING_THREAD_SANITIZER)
+ TsanLoadAcquire(Address(address, offset));
+#endif
}
void LoadAcquireCompressed(Register dst,
Register address,
@@ -1038,11 +1047,17 @@
// On intel loads have load-acquire behavior (i.e. loads are not re-ordered
// with other loads).
LoadCompressed(dst, Address(address, offset));
+#if defined(USING_THREAD_SANITIZER)
+ TsanLoadAcquire(Address(address, offset));
+#endif
}
void StoreRelease(Register src, Register address, int32_t offset = 0) {
// On intel stores have store-release behavior (i.e. stores are not
// re-ordered with other stores).
movq(Address(address, offset), src);
+#if defined(USING_THREAD_SANITIZER)
+ TsanStoreRelease(Address(address, offset));
+#endif
}
void CompareWithFieldValue(Register value, FieldAddress address) {
diff --git a/runtime/vm/compiler/assembler/assembler_x64_test.cc b/runtime/vm/compiler/assembler/assembler_x64_test.cc
index 00eeead..3d2deb2 100644
--- a/runtime/vm/compiler/assembler/assembler_x64_test.cc
+++ b/runtime/vm/compiler/assembler/assembler_x64_test.cc
@@ -5309,10 +5309,10 @@
__ pushq(CODE_REG);
__ pushq(THR);
__ movq(THR, CallingConventions::kArg3Reg);
- __ StoreIntoObject(CallingConventions::kArg2Reg,
- FieldAddress(CallingConventions::kArg2Reg,
- GrowableObjectArray::data_offset()),
- CallingConventions::kArg1Reg);
+ __ StoreCompressedIntoObject(CallingConventions::kArg2Reg,
+ FieldAddress(CallingConventions::kArg2Reg,
+ GrowableObjectArray::data_offset()),
+ CallingConventions::kArg1Reg);
__ popq(THR);
__ popq(CODE_REG);
__ ret();
@@ -6167,6 +6167,110 @@
Address(RSP, 0),
__ popq(RAX))
+ASSEMBLER_TEST_GENERATE(StoreReleaseLoadAcquire, assembler) {
+ __ pushq(RCX);
+ __ xorq(RCX, RCX);
+ __ pushq(RCX);
+
+ for (intptr_t i = 0; i < kNumberOfXmmRegisters; ++i) {
+ XmmRegister xmm_reg = static_cast<XmmRegister>(i);
+ if ((CallingConventions::kVolatileXmmRegisters & (1 << xmm_reg)) != 0) {
+ __ movq(RCX, Immediate(bit_cast<int32_t, float>(12.34f + i)));
+ __ movd(xmm_reg, RCX);
+ }
+ }
+
+ for (intptr_t i = 0; i < kNumberOfCpuRegisters; ++i) {
+ Register reg = static_cast<Register>(i);
+ if (reg == CallingConventions::kArg3Reg) {
+ continue;
+ }
+ if ((CallingConventions::kVolatileCpuRegisters & (1 << reg)) != 0) {
+ __ movq(reg, Immediate(0xAABBCCDD + i));
+ }
+ }
+ __ StoreRelease(CallingConventions::kArg3Reg, RSP, 0);
+
+ __ pushq(TMP);
+
+ for (intptr_t i = 0; i < kNumberOfCpuRegisters; ++i) {
+ Register reg = static_cast<Register>(i);
+ if (reg == CallingConventions::kArg3Reg) {
+ continue;
+ }
+ if ((CallingConventions::kVolatileCpuRegisters & (1 << reg)) != 0) {
+ Label ok;
+ if (reg == TMP) {
+ __ popq(TMP);
+ // Use kArg3Reg to validate TMP because TMP is
+ // needed for 64-bit cmpq below.
+ __ pushq(CallingConventions::kArg3Reg);
+ __ movq(CallingConventions::kArg3Reg, TMP);
+ reg = CallingConventions::kArg3Reg;
+ }
+ __ cmpq(reg, Immediate(0xAABBCCDD + i));
+ __ j(EQUAL, &ok);
+ __ int3();
+ __ Bind(&ok);
+ if (reg == CallingConventions::kArg3Reg) {
+ __ popq(CallingConventions::kArg3Reg);
+ }
+ }
+ }
+
+ for (intptr_t i = 0; i < kNumberOfXmmRegisters; ++i) {
+ XmmRegister xmm_reg = static_cast<XmmRegister>(i);
+ if ((CallingConventions::kVolatileXmmRegisters & (1 << xmm_reg)) != 0) {
+ Label ok;
+ __ movq(RCX, xmm_reg);
+ __ cmpq(RCX, Immediate(bit_cast<int32_t, float>(12.34f + i)));
+ __ j(EQUAL, &ok);
+ __ int3();
+ __ Bind(&ok);
+ }
+ }
+ __ LoadAcquire(CallingConventions::kReturnReg, RSP, 0);
+ __ popq(RCX);
+ __ popq(RCX);
+ __ ret();
+}
+
+ASSEMBLER_TEST_RUN(StoreReleaseLoadAcquire, test) {
+ int res = test->InvokeWithCodeAndThread<int>(123);
+ EXPECT_EQ(123, res);
+}
+
+ASSEMBLER_TEST_GENERATE(StoreReleaseLoadAcquire1024, assembler) {
+ __ pushq(RCX);
+ __ xorq(RCX, RCX);
+ __ pushq(RCX);
+ __ subq(RSP, Immediate(1024));
+ __ StoreRelease(CallingConventions::kArg3Reg, RSP, 1024);
+ __ LoadAcquire(CallingConventions::kReturnReg, RSP, 1024);
+ __ addq(RSP, Immediate(1024));
+ __ popq(RCX);
+ __ popq(RCX);
+ __ ret();
+}
+
+ASSEMBLER_TEST_RUN(StoreReleaseLoadAcquire1024, test) {
+ int res = test->InvokeWithCodeAndThread<int>(123);
+ EXPECT_EQ(123, res);
+#if !defined(USING_THREAD_SANITIZER)
+ EXPECT_DISASSEMBLY_NOT_WINDOWS(
+ "push rcx\n"
+ "xorq rcx,rcx\n"
+ "push rcx\n"
+ "subq rsp,0x...\n"
+ "movq [rsp+0x...],rdx\n"
+ "movq rax,[rsp+0x...]\n"
+ "addq rsp,0x...\n"
+ "pop rcx\n"
+ "pop rcx\n"
+ "ret\n");
+#endif
+}
+
} // namespace compiler
} // namespace dart
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
index b71c702..2e5a194 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
@@ -252,8 +252,14 @@
ASSERT(!__ constant_pool_allowed());
ASSERT(extracted_method.IsZoneHandle());
- const Code& build_method_extractor = Code::ZoneHandle(
- isolate_group()->object_store()->build_method_extractor_code());
+ const Code& build_method_extractor =
+ Code::ZoneHandle(extracted_method.IsGeneric()
+ ? isolate_group()
+ ->object_store()
+ ->build_generic_method_extractor_code()
+ : isolate_group()
+ ->object_store()
+ ->build_nongeneric_method_extractor_code());
const intptr_t stub_index = __ object_pool_builder().AddObject(
build_method_extractor, ObjectPool::Patchability::kNotPatchable);
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
index 6f257d1..d7b3759 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
@@ -243,8 +243,14 @@
ASSERT(!__ constant_pool_allowed());
ASSERT(extracted_method.IsZoneHandle());
- const Code& build_method_extractor = Code::ZoneHandle(
- isolate_group()->object_store()->build_method_extractor_code());
+ const Code& build_method_extractor =
+ Code::ZoneHandle(extracted_method.IsGeneric()
+ ? isolate_group()
+ ->object_store()
+ ->build_generic_method_extractor_code()
+ : isolate_group()
+ ->object_store()
+ ->build_nongeneric_method_extractor_code());
const intptr_t stub_index = __ object_pool_builder().AddObject(
build_method_extractor, ObjectPool::Patchability::kNotPatchable);
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
index 3b5345d..6092741 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
@@ -252,8 +252,14 @@
ASSERT(!__ constant_pool_allowed());
ASSERT(extracted_method.IsZoneHandle());
- const Code& build_method_extractor = Code::ZoneHandle(
- isolate_group()->object_store()->build_method_extractor_code());
+ const Code& build_method_extractor =
+ Code::ZoneHandle(extracted_method.IsGeneric()
+ ? isolate_group()
+ ->object_store()
+ ->build_generic_method_extractor_code()
+ : isolate_group()
+ ->object_store()
+ ->build_nongeneric_method_extractor_code());
ASSERT(!build_method_extractor.IsNull());
const intptr_t stub_index = __ object_pool_builder().AddObject(
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index 45a70dc..527fa42 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -1156,7 +1156,7 @@
// Since new isolates will be spawned, the JITed code cannot depend on whether
// global field was initialized when running with --enable-isolate-groups.
- if (IsolateGroup::AreIsolateGroupsEnabled()) return false;
+ if (FLAG_enable_isolate_groups) return false;
const Field& field = this->field();
Isolate* only_isolate = IsolateGroup::Current()->FirstIsolate();
@@ -3736,7 +3736,7 @@
switch (from) {
case kUnboxedUint8:
case kUnboxedUint16:
-#if defined(TARGET_ARCH_IS_64_BIT) && !defined(DART_COMPRESSED_POINTERS)
+#if defined(HAS_SMI_63_BITS)
case kUnboxedInt32:
case kUnboxedUint32:
#endif
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index 1744e17..7699857 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -24,6 +24,7 @@
#include "vm/compiler/ffi/native_location.h"
#include "vm/compiler/ffi/native_type.h"
#include "vm/compiler/method_recognizer.h"
+#include "vm/dart_entry.h"
#include "vm/flags.h"
#include "vm/growable_array.h"
#include "vm/native_entry.h"
diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc
index 0c07ad2..5ede916 100644
--- a/runtime/vm/compiler/backend/il_arm.cc
+++ b/runtime/vm/compiler/backend/il_arm.cc
@@ -779,8 +779,8 @@
const intptr_t kCpuRegistersToPreserve =
kDartAvailableCpuRegs & ~kNonChangeableInputRegs;
const intptr_t kFpuRegistersToPreserve =
- Utils::SignedNBitMask(kNumberOfFpuRegisters) &
- ~(Utils::SignedNBitMask(kAbiPreservedFpuRegCount)
+ Utils::NBitMask<intptr_t>(kNumberOfFpuRegisters) &
+ ~(Utils::NBitMask<intptr_t>(kAbiPreservedFpuRegCount)
<< kAbiFirstPreservedFpuReg) &
~(1 << FpuTMP);
diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc
index 223b424..9484c260 100644
--- a/runtime/vm/compiler/backend/il_arm64.cc
+++ b/runtime/vm/compiler/backend/il_arm64.cc
@@ -699,7 +699,7 @@
const intptr_t kCpuRegistersToPreserve =
kDartAvailableCpuRegs & ~kNonChangeableInputRegs;
const intptr_t kFpuRegistersToPreserve =
- Utils::SignedNBitMask(kNumberOfFpuRegisters) & ~(1l << FpuTMP);
+ Utils::NBitMask<intptr_t>(kNumberOfFpuRegisters) & ~(1l << FpuTMP);
const intptr_t kNumTemps = (Utils::CountOneBits64(kCpuRegistersToPreserve) +
Utils::CountOneBits64(kFpuRegistersToPreserve));
@@ -1496,11 +1496,12 @@
// Load the code object.
__ LoadFromOffset(R0, THR, compiler::target::Thread::callback_code_offset());
- __ LoadFieldFromOffset(R0, R0,
- compiler::target::GrowableObjectArray::data_offset());
- __ LoadFieldFromOffset(CODE_REG, R0,
- compiler::target::Array::data_offset() +
- callback_id_ * compiler::target::kWordSize);
+ __ LoadCompressedFieldFromOffset(
+ R0, R0, compiler::target::GrowableObjectArray::data_offset());
+ __ LoadCompressedFieldFromOffset(
+ CODE_REG, R0,
+ compiler::target::Array::data_offset() +
+ callback_id_ * compiler::target::kCompressedWordSize);
// Put the code object in the reserved slot.
__ StoreToOffset(CODE_REG, FPREG,
diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc
index cb4c1be..bdde81c 100644
--- a/runtime/vm/compiler/backend/il_x64.cc
+++ b/runtime/vm/compiler/backend/il_x64.cc
@@ -1387,11 +1387,14 @@
// Load the code object.
__ movq(RAX, compiler::Address(
THR, compiler::target::Thread::callback_code_offset()));
- __ movq(RAX, compiler::FieldAddress(
- RAX, compiler::target::GrowableObjectArray::data_offset()));
- __ movq(CODE_REG, compiler::FieldAddress(
- RAX, compiler::target::Array::data_offset() +
- callback_id_ * compiler::target::kWordSize));
+ __ LoadCompressed(
+ RAX, compiler::FieldAddress(
+ RAX, compiler::target::GrowableObjectArray::data_offset()));
+ __ LoadCompressed(
+ CODE_REG,
+ compiler::FieldAddress(
+ RAX, compiler::target::Array::data_offset() +
+ callback_id_ * compiler::target::kCompressedWordSize));
// Put the code object in the reserved slot.
__ movq(compiler::Address(FPREG,
diff --git a/runtime/vm/compiler/backend/range_analysis.cc b/runtime/vm/compiler/backend/range_analysis.cc
index 5eec5a4..17a1c15 100644
--- a/runtime/vm/compiler/backend/range_analysis.cc
+++ b/runtime/vm/compiler/backend/range_analysis.cc
@@ -2804,6 +2804,7 @@
case Slot::Kind::kFunctionType_named_parameter_names:
case Slot::Kind::kFunctionType_parameter_types:
case Slot::Kind::kFunctionType_type_parameters:
+ case Slot::Kind::kInstance_native_fields_array:
case Slot::Kind::kPointerBase_data_field:
case Slot::Kind::kTypedDataView_data:
case Slot::Kind::kType_arguments:
diff --git a/runtime/vm/compiler/backend/slot.cc b/runtime/vm/compiler/backend/slot.cc
index cd8e80c..9f84201 100644
--- a/runtime/vm/compiler/backend/slot.cc
+++ b/runtime/vm/compiler/backend/slot.cc
@@ -210,6 +210,7 @@
case Slot::Kind::kArgumentsDescriptor_count:
case Slot::Kind::kArgumentsDescriptor_size:
case Slot::Kind::kArrayElement:
+ case Slot::Kind::kInstance_native_fields_array:
case Slot::Kind::kTypeArguments:
case Slot::Kind::kTypedDataView_offset_in_bytes:
case Slot::Kind::kTypedDataView_data:
diff --git a/runtime/vm/compiler/backend/slot.h b/runtime/vm/compiler/backend/slot.h
index 866e399..27adf00 100644
--- a/runtime/vm/compiler/backend/slot.h
+++ b/runtime/vm/compiler/backend/slot.h
@@ -61,6 +61,7 @@
V(Closure, UntaggedClosure, function_type_arguments, TypeArguments, FINAL) \
V(FunctionType, UntaggedFunctionType, type_parameters, TypeParameters, \
FINAL) \
+ V(Instance, UntaggedInstance, native_fields_array, Dynamic, VAR) \
V(Type, UntaggedType, arguments, TypeArguments, FINAL) \
V(TypeParameters, UntaggedTypeParameters, flags, Array, FINAL) \
V(TypeParameters, UntaggedTypeParameters, bounds, TypeArguments, FINAL) \
diff --git a/runtime/vm/compiler/backend/type_propagator.cc b/runtime/vm/compiler/backend/type_propagator.cc
index 9aecb2c..06edf78 100644
--- a/runtime/vm/compiler/backend/type_propagator.cc
+++ b/runtime/vm/compiler/backend/type_propagator.cc
@@ -699,7 +699,7 @@
}
CompileType CompileType::Int32() {
-#if defined(TARGET_ARCH_IS_64_BIT) && !defined(DART_COMPRESSED_POINTERS)
+#if defined(HAS_SMI_63_BITS)
return FromCid(kSmiCid);
#else
return Int();
diff --git a/runtime/vm/compiler/frontend/constant_reader.cc b/runtime/vm/compiler/frontend/constant_reader.cc
index f2c7656..6040fb1 100644
--- a/runtime/vm/compiler/frontend/constant_reader.cc
+++ b/runtime/vm/compiler/frontend/constant_reader.cc
@@ -353,6 +353,18 @@
instance = function.ImplicitStaticClosure();
break;
}
+ case kConstructorTearOffConstant: {
+ const NameIndex index = reader.ReadCanonicalNameReference();
+ Function& function = Function::Handle(Z);
+ if (H.IsConstructor(index)) {
+ function = H.LookupConstructorByKernelConstructor(index);
+ } else {
+ function = H.LookupStaticMethodByKernelProcedure(index);
+ }
+ function = function.ImplicitClosureFunction();
+ instance = function.ImplicitStaticClosure();
+ break;
+ }
case kTypeLiteralConstant: {
// Build type from the raw bytes (needs temporary translator).
// Const canonical type erasure is not applied to constant type literals.
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index 7a07552..257ee0e 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -230,7 +230,7 @@
bool has_field_initializers = false;
for (intptr_t i = 0; i < list_length; ++i) {
if (PeekTag() == kRedirectingInitializer ||
- PeekTag() == kRedirectingFactoryConstructor) {
+ PeekTag() == kRedirectingFactory) {
is_redirecting_constructor = true;
} else if (PeekTag() == kFieldInitializer) {
has_field_initializers = true;
@@ -2855,7 +2855,7 @@
// read flags.
const uint8_t flags = is_dynamic ? 0 : ReadFlags();
- const bool is_invariant = (flags & kMethodInvocationFlagInvariant) != 0;
+ const bool is_invariant = (flags & kInstanceInvocationFlagInvariant) != 0;
const TokenPosition position = ReadPosition(); // read position.
if (p != NULL) *p = position;
@@ -5299,7 +5299,9 @@
if (!closure_owner_.IsNull()) {
function = Function::NewClosureFunctionWithKind(
UntaggedFunction::kClosureFunction, *name,
- parsed_function()->function(), position, closure_owner_);
+ parsed_function()->function(),
+ parsed_function()->function().is_static(), position,
+ closure_owner_);
} else {
function = Function::NewClosureFunction(
*name, parsed_function()->function(), position);
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index 6968ff1..68cdb57 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -854,6 +854,7 @@
case MethodRecognizer::kFfiStorePointer:
case MethodRecognizer::kFfiFromAddress:
case MethodRecognizer::kFfiGetAddress:
+ case MethodRecognizer::kGetNativeField:
case MethodRecognizer::kObjectEquals:
case MethodRecognizer::kStringBaseLength:
case MethodRecognizer::kStringBaseIsEmpty:
@@ -1485,12 +1486,26 @@
body += Box(kUnboxedFfiIntPtr);
} break;
case MethodRecognizer::kHas63BitSmis: {
-#if defined(TARGET_ARCH_IS_64_BIT) && !defined(DART_COMPRESSED_POINTERS)
+#if defined(HAS_SMI_63_BITS)
body += Constant(Bool::True());
#else
body += Constant(Bool::False());
#endif // defined(ARCH_IS_64_BIT)
} break;
+ case MethodRecognizer::kGetNativeField: {
+ auto& name = String::ZoneHandle(Z, function.name());
+ // Note: This method is force optimized so we can push untagged, etc.
+ // Load TypedDataArray from Instance Handle implementing
+ // NativeFieldWrapper.
+ body += LoadLocal(parsed_function_->RawParameterVariable(0)); // Object.
+ body += CheckNullOptimized(TokenPosition::kNoSource, name);
+ body += LoadNativeField(Slot::Instance_native_fields_array()); // Fields.
+ body += CheckNullOptimized(TokenPosition::kNoSource, name);
+ // Load the native field at index.
+ body += IntConstant(0); // Index.
+ body += LoadIndexed(kIntPtrCid);
+ body += Box(kUnboxedIntPtr);
+ } break;
default: {
UNREACHABLE();
break;
@@ -3410,13 +3425,45 @@
intptr_t type_args_len = 0;
if (function.IsGeneric()) {
- type_args_len = function.NumTypeParameters();
- ASSERT(parsed_function_->function_type_arguments() != NULL);
- closure += LoadLocal(parsed_function_->function_type_arguments());
+ if (target.IsConstructor()) {
+ const auto& result_type = AbstractType::Handle(Z, function.result_type());
+ ASSERT(result_type.IsFinalized());
+ // Instantiate a flattened type arguments vector which
+ // includes type arguments corresponding to superclasses.
+ // TranslateInstantiatedTypeArguments is smart enough to
+ // avoid instantiation and resuse passed function type arguments
+ // if there are no extra type arguments in the flattened vector.
+ const auto& instantiated_type_arguments =
+ TypeArguments::ZoneHandle(Z, result_type.arguments());
+ closure +=
+ TranslateInstantiatedTypeArguments(instantiated_type_arguments);
+ } else {
+ type_args_len = function.NumTypeParameters();
+ ASSERT(parsed_function_->function_type_arguments() != NULL);
+ closure += LoadLocal(parsed_function_->function_type_arguments());
+ }
+ } else if (target.IsFactory()) {
+ // Factories always take an extra implicit argument for
+ // type arguments even if their classes don't have type parameters.
+ closure += NullConstant();
}
// Push receiver.
- if (!target.is_static()) {
+ if (target.IsGenerativeConstructor()) {
+ const Class& cls = Class::Handle(Z, target.Owner());
+ if (cls.NumTypeArguments() > 0) {
+ if (!function.IsGeneric()) {
+ Type& cls_type = Type::Handle(Z, cls.DeclarationType());
+ closure += Constant(TypeArguments::ZoneHandle(Z, cls_type.arguments()));
+ }
+ closure += AllocateObject(function.token_pos(), cls, 1);
+ } else {
+ ASSERT(!function.IsGeneric());
+ closure += AllocateObject(function.token_pos(), cls, 0);
+ }
+ LocalVariable* receiver = MakeTemporary();
+ closure += LoadLocal(receiver);
+ } else if (!target.is_static()) {
// The context has a fixed shape: a single variable which is the
// closed-over receiver.
closure += LoadLocal(parsed_function_->ParameterVariable(0));
@@ -3430,7 +3477,7 @@
// Forward parameters to the target.
intptr_t argument_count = function.NumParameters() -
function.NumImplicitParameters() +
- (target.is_static() ? 0 : 1);
+ target.NumImplicitParameters();
ASSERT(argument_count == target.NumParameters());
Array& argument_names =
@@ -3440,6 +3487,12 @@
argument_names, ICData::kNoRebind,
/* result_type = */ NULL, type_args_len);
+ if (target.IsGenerativeConstructor()) {
+ // Drop result of constructor invocation, leave receiver
+ // instance on the stack.
+ closure += Drop();
+ }
+
// Return the result.
closure += Return(function.end_token_pos());
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.cc b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
index 11b2fea..99a51ea 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.cc
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
@@ -3389,6 +3389,10 @@
ASSERT(parameterized_class.IsNull() != parameterized_signature.IsNull());
ASSERT(type_parameter_count >= 0);
if (type_parameter_count == 0) {
+ ASSERT(parameterized_class.IsNull() ||
+ parameterized_class.type_parameters() == TypeParameters::null());
+ ASSERT(parameterized_signature.IsNull() ||
+ parameterized_signature.type_parameters() == TypeParameters::null());
return;
}
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.h b/runtime/vm/compiler/frontend/kernel_translation_helper.h
index c8e3ca3..e9a4807 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.h
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.h
@@ -554,7 +554,7 @@
kConst = 1 << 3, // Only for external const factories.
// TODO(29841): Remove this line after the issue is resolved.
- kRedirectingFactoryConstructor = 1 << 4,
+ kRedirectingFactory = 1 << 4,
kExtensionMember = 1 << 5,
kSyntheticProcedure = 1 << 7,
};
@@ -579,8 +579,8 @@
return stub_kind_ == kAbstractForwardingStubKind ||
stub_kind_ == kConcreteForwardingStubKind;
}
- bool IsRedirectingFactoryConstructor() const {
- return (flags_ & kRedirectingFactoryConstructor) != 0;
+ bool IsRedirectingFactory() const {
+ return (flags_ & kRedirectingFactory) != 0;
}
bool IsNoSuchMethodForwarder() const {
return stub_kind_ == kNoSuchMethodForwarderStubKind;
diff --git a/runtime/vm/compiler/frontend/prologue_builder.cc b/runtime/vm/compiler/frontend/prologue_builder.cc
index 035bf63..635b3d9 100644
--- a/runtime/vm/compiler/frontend/prologue_builder.cc
+++ b/runtime/vm/compiler/frontend/prologue_builder.cc
@@ -68,6 +68,11 @@
if (expect_type_args) {
Fragment f = BuildTypeArgumentsHandling();
if (link) prologue += f;
+
+ if (function_.IsClosureFunction()) {
+ Fragment f = BuildClosureDelayedTypeArgumentsHandling();
+ if (!compiling_for_osr_) prologue += f;
+ }
}
const bool is_empty_prologue = prologue.entry == prologue.current;
@@ -372,29 +377,33 @@
handling += TestTypeArgsLen(store_null, store_type_args, 0);
- const auto& function = parsed_function_->function();
- if (function.IsClosureFunction()) {
- LocalVariable* closure = parsed_function_->ParameterVariable(0);
-
- // Currently, delayed type arguments can only be introduced through type
- // inference in the FE. So if they are present, we can assume they are
- // correct in number and bound.
- Fragment use_delayed_type_args;
- use_delayed_type_args += LoadLocal(closure);
- use_delayed_type_args +=
- LoadNativeField(Slot::Closure_delayed_type_arguments());
- use_delayed_type_args +=
- StoreLocal(TokenPosition::kNoSource, type_args_var);
- use_delayed_type_args += Drop();
-
- handling += TestDelayedTypeArgs(closure,
- /*present=*/use_delayed_type_args,
- /*absent=*/Fragment());
- }
-
return handling;
}
+Fragment PrologueBuilder::BuildClosureDelayedTypeArgumentsHandling() {
+ const auto& function = parsed_function_->function();
+ ASSERT(function.IsClosureFunction());
+ LocalVariable* const type_args_var =
+ parsed_function_->RawTypeArgumentsVariable();
+ ASSERT(type_args_var != nullptr);
+
+ LocalVariable* const closure = parsed_function_->ParameterVariable(0);
+
+ // Currently, delayed type arguments can only be introduced through type
+ // inference in the FE. So if they are present, we can assume they are
+ // correct in number and bound.
+ Fragment use_delayed_type_args;
+ use_delayed_type_args += LoadLocal(closure);
+ use_delayed_type_args +=
+ LoadNativeField(Slot::Closure_delayed_type_arguments());
+ use_delayed_type_args += StoreLocal(TokenPosition::kNoSource, type_args_var);
+ use_delayed_type_args += Drop();
+
+ return TestDelayedTypeArgs(closure,
+ /*present=*/use_delayed_type_args,
+ /*absent=*/Fragment());
+}
+
void PrologueBuilder::SortOptionalNamedParametersInto(int* opt_param_position,
int num_fixed_params,
int num_params) {
diff --git a/runtime/vm/compiler/frontend/prologue_builder.h b/runtime/vm/compiler/frontend/prologue_builder.h
index c8d629d..d474d72 100644
--- a/runtime/vm/compiler/frontend/prologue_builder.h
+++ b/runtime/vm/compiler/frontend/prologue_builder.h
@@ -61,6 +61,8 @@
Fragment BuildTypeArgumentsHandling();
+ Fragment BuildClosureDelayedTypeArgumentsHandling();
+
LocalVariable* ParameterVariable(intptr_t index) {
return parsed_function_->RawParameterVariable(index);
}
diff --git a/runtime/vm/compiler/frontend/scope_builder.cc b/runtime/vm/compiler/frontend/scope_builder.cc
index b2a6031..0205fe4 100644
--- a/runtime/vm/compiler/frontend/scope_builder.cc
+++ b/runtime/vm/compiler/frontend/scope_builder.cc
@@ -604,13 +604,11 @@
LocalVariable* future = scope_->LookupVariable(Symbols::_future(), true);
ASSERT(future != nullptr);
future->set_is_chained_future();
- future->set_expected_context_index(Context::kFutureTimeoutFutureIndex);
} else if (function.recognized_kind() == MethodRecognizer::kFutureWait &&
depth_.function_ == 1) {
LocalVariable* future = scope_->LookupVariable(Symbols::_future(), true);
ASSERT(future != nullptr);
future->set_is_chained_future();
- future->set_expected_context_index(Context::kFutureWaitFutureIndex);
}
}
@@ -1454,9 +1452,6 @@
void ScopeBuilder::VisitTypeParameterType() {
Function& function = Function::Handle(Z, parsed_function_->function().ptr());
- while (function.IsClosureFunction()) {
- function = function.parent_function();
- }
helper_.ReadNullability(); // read nullability.
@@ -1467,19 +1462,25 @@
intptr_t index = helper_.ReadUInt(); // read index for parameter.
- if (function.IsFactory()) {
- // The type argument vector is passed as the very first argument to the
- // factory constructor function.
- HandleSpecialLoad(&result_->type_arguments_variable,
- Symbols::TypeArgumentsParameter());
- } else {
- // If the type parameter is a parameter to this or an enclosing function, we
- // can read it directly from the function type arguments vector later.
- // Otherwise, the type arguments vector we need is stored on the instance
- // object, so we need to capture 'this'.
- Class& parent_class = Class::Handle(Z, function.Owner());
- if (index < parent_class.NumTypeParameters()) {
- HandleLoadReceiver();
+ if (!function.IsImplicitStaticClosureFunction()) {
+ while (function.IsClosureFunction()) {
+ function = function.parent_function();
+ }
+
+ if (function.IsFactory()) {
+ // The type argument vector is passed as the very first argument to the
+ // factory constructor function.
+ HandleSpecialLoad(&result_->type_arguments_variable,
+ Symbols::TypeArgumentsParameter());
+ } else {
+ // If the type parameter is a parameter to this or an enclosing function,
+ // we can read it directly from the function type arguments vector later.
+ // Otherwise, the type arguments vector we need is stored on the instance
+ // object, so we need to capture 'this'.
+ Class& parent_class = Class::Handle(Z, function.Owner());
+ if (index < parent_class.NumTypeParameters()) {
+ HandleLoadReceiver();
+ }
}
}
diff --git a/runtime/vm/compiler/jit/compiler.cc b/runtime/vm/compiler/jit/compiler.cc
index 0104e80..c9f4f86 100644
--- a/runtime/vm/compiler/jit/compiler.cc
+++ b/runtime/vm/compiler/jit/compiler.cc
@@ -212,7 +212,7 @@
ASSERT(thread->IsMutatorThread());
const Function& function = Function::CheckedHandle(zone, arguments.ArgAt(0));
- if (IsolateGroup::AreIsolateGroupsEnabled()) {
+ if (FLAG_enable_isolate_groups) {
// Another isolate's mutator thread may have created [function] and
// published it via an ICData, MegamorphicCache etc. Entering the lock below
// is an acquire operation that pairs with the release operation when the
@@ -225,7 +225,7 @@
// there's no existing code. In multi-isolate scenarios with shared JITed code
// we can end up in the lazy compile runtime entry here with code being
// installed.
- ASSERT(!function.HasCode() || IsolateGroup::AreIsolateGroupsEnabled());
+ ASSERT(!function.HasCode() || FLAG_enable_isolate_groups);
// Will throw if compilation failed (e.g. with compile-time error).
function.EnsureHasCode();
@@ -514,14 +514,6 @@
CompilerState::ShouldTrace(function));
{
- if (optimized()) {
- // In background compilation the deoptimization counter may have
- // already reached the limit.
- ASSERT(Compiler::IsBackgroundCompilation() ||
- (function.deoptimization_counter() <
- FLAG_max_deoptimization_counter_threshold));
- }
-
// Extract type feedback before the graph is built, as the graph
// builder uses it to attach it to nodes.
ic_data_array = new (zone) ZoneGrowableArray<const ICData*>();
diff --git a/runtime/vm/compiler/method_recognizer.cc b/runtime/vm/compiler/method_recognizer.cc
index 0c5a85a..af01254 100644
--- a/runtime/vm/compiler/method_recognizer.cc
+++ b/runtime/vm/compiler/method_recognizer.cc
@@ -290,6 +290,7 @@
libs->Add(&Library::ZoneHandle(Library::DeveloperLibrary()));
libs->Add(&Library::ZoneHandle(Library::AsyncLibrary()));
libs->Add(&Library::ZoneHandle(Library::FfiLibrary()));
+ libs->Add(&Library::ZoneHandle(Library::NativeWrappersLibrary()));
}
static Token::Kind RecognizeTokenKindHelper(const String& name) {
diff --git a/runtime/vm/compiler/recognized_methods_list.h b/runtime/vm/compiler/recognized_methods_list.h
index f45e224..9680f0b 100644
--- a/runtime/vm/compiler/recognized_methods_list.h
+++ b/runtime/vm/compiler/recognized_methods_list.h
@@ -197,6 +197,7 @@
V(::, _storePointer, FfiStorePointer, 0xea6b7751) \
V(::, _fromAddress, FfiFromAddress, 0xfd8cb1cc) \
V(Pointer, get:address, FfiGetAddress, 0x7cde87be) \
+ V(::, getNativeField, GetNativeField, 0x95b4ec94) \
V(::, reachabilityFence, ReachabilityFence, 0x619235c1) \
V(_Utf8Decoder, _scan, Utf8DecoderScan, 0x1dcaf73d) \
V(_Future, timeout, FutureTimeout, 0x73041520) \
diff --git a/runtime/vm/compiler/runtime_api.cc b/runtime/vm/compiler/runtime_api.cc
index c289e46..c8e499b 100644
--- a/runtime/vm/compiler/runtime_api.cc
+++ b/runtime/vm/compiler/runtime_api.cc
@@ -315,8 +315,8 @@
const word kOldPageMask = dart::kOldPageMask;
static word TranslateOffsetInWordsToHost(word offset) {
- RELEASE_ASSERT((offset % kWordSize) == 0);
- return (offset / kWordSize) * dart::kWordSize;
+ RELEASE_ASSERT((offset % kCompressedWordSize) == 0);
+ return (offset / kCompressedWordSize) * dart::kCompressedWordSize;
}
bool SizeFitsInSizeTag(uword instance_size) {
@@ -410,6 +410,8 @@
return TypedDataBase::InstanceSize();
case kLinkedHashMapCid:
return LinkedHashMap::InstanceSize();
+ case kLinkedHashSetCid:
+ return LinkedHashSet::InstanceSize();
case kUnhandledExceptionCid:
return UnhandledException::InstanceSize();
case kWeakPropertyCid:
@@ -475,6 +477,10 @@
return TranslateOffsetInWords(dart::Instance::NextFieldOffset());
}
+word Instance::native_fields_array_offset() {
+ return TranslateOffsetInWords(dart::Instance::NativeFieldsOffset());
+}
+
word Instance::DataOffsetFor(intptr_t cid) {
if (dart::IsExternalTypedDataClassId(cid) ||
dart::IsExternalStringClassId(cid)) {
@@ -960,243 +966,19 @@
return TranslateOffsetInWords(dart::Instance::NextFieldOffset());
}
-word Pointer::NextFieldOffset() {
- return TranslateOffsetInWords(dart::Pointer::NextFieldOffset());
-}
-
-word WeakSerializationReference::NextFieldOffset() {
- return -kWordSize;
-}
-
-word ObjectPool::NextFieldOffset() {
- return -kWordSize;
-}
-
-word Class::NextFieldOffset() {
- return -kWordSize;
-}
-
-word Function::NextFieldOffset() {
- return -kWordSize;
-}
-
-word ICData::NextFieldOffset() {
- return -kWordSize;
-}
-
-word MegamorphicCache::NextFieldOffset() {
- return -kWordSize;
-}
-
-word SingleTargetCache::NextFieldOffset() {
- return -kWordSize;
-}
-
-word Array::NextFieldOffset() {
- return -kWordSize;
-}
-
intptr_t Array::index_at_offset(intptr_t offset_in_bytes) {
return dart::Array::index_at_offset(
TranslateOffsetInWordsToHost(offset_in_bytes));
}
-word GrowableObjectArray::NextFieldOffset() {
- return -kWordSize;
-}
-
-word TypedDataBase::NextFieldOffset() {
- return -kWordSize;
-}
-
-word TypedData::NextFieldOffset() {
- return -kWordSize;
-}
-
-word ExternalTypedData::NextFieldOffset() {
- return -kWordSize;
-}
-
-word TypedDataView::NextFieldOffset() {
- return -kWordSize;
-}
-
-word LinkedHashMap::NextFieldOffset() {
- return -kWordSize;
-}
-
-word AbstractType::NextFieldOffset() {
- return -kWordSize;
-}
-
-word Type::NextFieldOffset() {
- return -kWordSize;
-}
-
-word FunctionType::NextFieldOffset() {
- return -kWordSize;
-}
-
-word TypeRef::NextFieldOffset() {
- return -kWordSize;
-}
-
-word Double::NextFieldOffset() {
- return -kWordSize;
-}
-
-word Mint::NextFieldOffset() {
- return -kWordSize;
-}
-
-word String::NextFieldOffset() {
- return -kWordSize;
-}
-
word String::InstanceSize(word payload_size) {
return RoundedAllocationSize(String::InstanceSize() + payload_size);
}
-word OneByteString::NextFieldOffset() {
- return -kWordSize;
-}
-
-word TwoByteString::NextFieldOffset() {
- return -kWordSize;
-}
-
-word ExternalOneByteString::NextFieldOffset() {
- return -kWordSize;
-}
-
-word ExternalTwoByteString::NextFieldOffset() {
- return -kWordSize;
-}
-
-word Int32x4::NextFieldOffset() {
- return -kWordSize;
-}
-
-word Float32x4::NextFieldOffset() {
- return -kWordSize;
-}
-
-word Float64x2::NextFieldOffset() {
- return -kWordSize;
-}
-
-word DynamicLibrary::NextFieldOffset() {
- return -kWordSize;
-}
-
-word PatchClass::NextFieldOffset() {
- return -kWordSize;
-}
-
-word FfiTrampolineData::NextFieldOffset() {
- return -kWordSize;
-}
-
-word Script::NextFieldOffset() {
- return -kWordSize;
-}
-
-word Library::NextFieldOffset() {
- return -kWordSize;
-}
-
-word Namespace::NextFieldOffset() {
- return -kWordSize;
-}
-
-word KernelProgramInfo::NextFieldOffset() {
- return -kWordSize;
-}
-
-word PcDescriptors::NextFieldOffset() {
- return -kWordSize;
-}
-
-word CodeSourceMap::NextFieldOffset() {
- return -kWordSize;
-}
-
-word CompressedStackMaps::NextFieldOffset() {
- return -kWordSize;
-}
-
word LocalVarDescriptors::InstanceSize() {
return 0;
}
-word LocalVarDescriptors::NextFieldOffset() {
- return -kWordSize;
-}
-
-word ExceptionHandlers::NextFieldOffset() {
- return -kWordSize;
-}
-
-word ContextScope::NextFieldOffset() {
- return -kWordSize;
-}
-
-word Sentinel::NextFieldOffset() {
- return -kWordSize;
-}
-
-word UnlinkedCall::NextFieldOffset() {
- return -kWordSize;
-}
-
-word ApiError::NextFieldOffset() {
- return -kWordSize;
-}
-
-word LanguageError::NextFieldOffset() {
- return -kWordSize;
-}
-
-word UnhandledException::NextFieldOffset() {
- return -kWordSize;
-}
-
-word UnwindError::NextFieldOffset() {
- return -kWordSize;
-}
-
-word Bool::NextFieldOffset() {
- return -kWordSize;
-}
-
-word TypeParameter::NextFieldOffset() {
- return -kWordSize;
-}
-
-word LibraryPrefix::NextFieldOffset() {
- return -kWordSize;
-}
-
-word Capability::NextFieldOffset() {
- return -kWordSize;
-}
-
-word ReceivePort::NextFieldOffset() {
- return -kWordSize;
-}
-
-word SendPort::NextFieldOffset() {
- return -kWordSize;
-}
-
-word TransferableTypedData::NextFieldOffset() {
- return -kWordSize;
-}
-
-word StackTrace::NextFieldOffset() {
- return -kWordSize;
-}
-
word Integer::NextFieldOffset() {
return TranslateOffsetInWords(dart::Integer::NextFieldOffset());
}
@@ -1205,94 +987,10 @@
return 0;
}
-word Smi::NextFieldOffset() {
- return -kWordSize;
-}
-
-word WeakProperty::NextFieldOffset() {
- return -kWordSize;
-}
-
-word MirrorReference::NextFieldOffset() {
- return -kWordSize;
-}
-
word Number::NextFieldOffset() {
return TranslateOffsetInWords(dart::Number::NextFieldOffset());
}
-word MonomorphicSmiableCall::NextFieldOffset() {
- return -kWordSize;
-}
-
-word InstructionsSection::NextFieldOffset() {
- return -kWordSize;
-}
-
-word InstructionsTable::NextFieldOffset() {
- return -kWordSize;
-}
-
-word Instructions::NextFieldOffset() {
- return -kWordSize;
-}
-
-word Code::NextFieldOffset() {
- return -kWordSize;
-}
-
-word SubtypeTestCache::NextFieldOffset() {
- return -kWordSize;
-}
-
-word LoadingUnit::NextFieldOffset() {
- return -kWordSize;
-}
-
-word Context::NextFieldOffset() {
- return -kWordSize;
-}
-
-word Closure::NextFieldOffset() {
- return -kWordSize;
-}
-
-word ClosureData::NextFieldOffset() {
- return -kWordSize;
-}
-
-word RegExp::NextFieldOffset() {
- return -kWordSize;
-}
-
-word UserTag::NextFieldOffset() {
- return -kWordSize;
-}
-
-word FutureOr::NextFieldOffset() {
- return -kWordSize;
-}
-
-word Field::NextFieldOffset() {
- return -kWordSize;
-}
-
-word TypeParameters::NextFieldOffset() {
- return -kWordSize;
-}
-
-word TypeArguments::NextFieldOffset() {
- return -kWordSize;
-}
-
-word FreeListElement::FakeInstance::NextFieldOffset() {
- return -kWordSize;
-}
-
-word ForwardingCorpse::FakeInstance::NextFieldOffset() {
- return -kWordSize;
-}
-
} // namespace target
} // namespace compiler
} // namespace dart
diff --git a/runtime/vm/compiler/runtime_api.h b/runtime/vm/compiler/runtime_api.h
index fb22d3b..52642b1 100644
--- a/runtime/vm/compiler/runtime_api.h
+++ b/runtime/vm/compiler/runtime_api.h
@@ -419,6 +419,9 @@
bool WillAllocateNewOrRememberedArray(intptr_t length);
+#define FINAL_CLASS() \
+ static word NextFieldOffset() { return -kWordSize; }
+
//
// Target specific offsets and constants.
//
@@ -461,7 +464,7 @@
static word element_offset(intptr_t index);
static word InstanceSize(intptr_t length);
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class Class : public AllStatic {
@@ -480,7 +483,7 @@
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
// Return class id of the given class on the target.
static classid_t GetId(const dart::Class& handle);
@@ -508,8 +511,8 @@
class Instance : public AllStatic {
public:
// Returns the offset to the first field of [UntaggedInstance].
- // Returns the offset to the first field of [UntaggedInstance].
static word first_field_offset();
+ static word native_fields_array_offset();
static word DataOffsetFor(intptr_t cid);
static word ElementSizeFor(intptr_t cid);
static word InstanceSize();
@@ -526,7 +529,7 @@
static word signature_offset();
static word usage_counter_offset();
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class CallSiteData : public AllStatic {
@@ -550,7 +553,7 @@
static word NumArgsTestedShift();
static word NumArgsTestedMask();
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class MegamorphicCache : public AllStatic {
@@ -559,7 +562,7 @@
static word mask_offset();
static word buckets_offset();
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class SingleTargetCache : public AllStatic {
@@ -569,7 +572,7 @@
static word entry_point_offset();
static word target_offset();
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class Array : public AllStatic {
@@ -583,7 +586,7 @@
static intptr_t index_at_offset(intptr_t offset_in_bytes);
static word InstanceSize(intptr_t length);
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
static const word kMaxElements;
static const word kMaxNewSpaceElements;
@@ -595,7 +598,7 @@
static word type_arguments_offset();
static word length_offset();
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class PointerBase : public AllStatic {
@@ -607,7 +610,7 @@
public:
static word length_offset();
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class TypedData : public AllStatic {
@@ -616,14 +619,14 @@
static word HeaderSize();
static word InstanceSize();
static word InstanceSize(word lengthInBytes);
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class ExternalTypedData : public AllStatic {
public:
static word data_offset();
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class TypedDataView : public AllStatic {
@@ -631,7 +634,7 @@
static word offset_in_bytes_offset();
static word data_offset();
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class LinkedHashBase : public AllStatic {
@@ -647,14 +650,19 @@
class LinkedHashMap : public LinkedHashBase {
public:
- static word NextFieldOffset();
+ FINAL_CLASS();
+};
+
+class LinkedHashSet : public LinkedHashBase {
+ public:
+ FINAL_CLASS();
};
class FutureOr : public AllStatic {
public:
static word type_arguments_offset();
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class ArgumentsDescriptor : public AllStatic {
@@ -678,14 +686,14 @@
public:
static word type_arguments_offset();
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class AbstractType : public AllStatic {
public:
static word type_test_stub_entry_point_offset();
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class Type : public AllStatic {
@@ -696,7 +704,7 @@
static word type_class_id_offset();
static word nullability_offset();
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class FunctionType : public AllStatic {
@@ -710,14 +718,14 @@
static word type_parameters_offset();
static word nullability_offset();
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class TypeRef : public AllStatic {
public:
static word type_offset();
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class Nullability : public AllStatic {
@@ -731,14 +739,14 @@
public:
static word value_offset();
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class Mint : public AllStatic {
public:
static word value_offset();
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class String : public AllStatic {
@@ -748,8 +756,8 @@
static word hash_offset();
static word length_offset();
static word InstanceSize();
- static word NextFieldOffset();
static word InstanceSize(word payload_size);
+ FINAL_CLASS();
};
class OneByteString : public AllStatic {
@@ -757,7 +765,7 @@
static word data_offset();
static word InstanceSize(intptr_t length);
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
private:
static word element_offset(intptr_t index);
@@ -768,7 +776,7 @@
static word data_offset();
static word InstanceSize(intptr_t length);
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
private:
static word element_offset(intptr_t index);
@@ -778,77 +786,77 @@
public:
static word external_data_offset();
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class ExternalTwoByteString : public AllStatic {
public:
static word external_data_offset();
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class Int32x4 : public AllStatic {
public:
static word value_offset();
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class Float32x4 : public AllStatic {
public:
static word value_offset();
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class Float64x2 : public AllStatic {
public:
static word value_offset();
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class DynamicLibrary : public AllStatic {
public:
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class PatchClass : public AllStatic {
public:
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class FfiTrampolineData : public AllStatic {
public:
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class Script : public AllStatic {
public:
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class Library : public AllStatic {
public:
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class Namespace : public AllStatic {
public:
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class KernelProgramInfo : public AllStatic {
public:
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class PcDescriptors : public AllStatic {
@@ -856,7 +864,7 @@
static word HeaderSize();
static word InstanceSize();
static word InstanceSize(word payload_size);
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class CodeSourceMap : public AllStatic {
@@ -864,7 +872,7 @@
static word HeaderSize();
static word InstanceSize();
static word InstanceSize(word payload_size);
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class CompressedStackMaps : public AllStatic {
@@ -872,13 +880,13 @@
static word HeaderSize();
static word InstanceSize();
static word InstanceSize(word payload_size);
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class LocalVarDescriptors : public AllStatic {
public:
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class ExceptionHandlers : public AllStatic {
@@ -886,7 +894,7 @@
static word element_offset(intptr_t index);
static word InstanceSize(intptr_t length);
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class ContextScope : public AllStatic {
@@ -894,31 +902,31 @@
static word element_offset(intptr_t index);
static word InstanceSize(intptr_t length);
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class Sentinel : public AllStatic {
public:
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class UnlinkedCall : public AllStatic {
public:
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class ApiError : public AllStatic {
public:
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class LanguageError : public AllStatic {
public:
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class UnhandledException : public AllStatic {
@@ -926,19 +934,19 @@
static word exception_offset();
static word stacktrace_offset();
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class UnwindError : public AllStatic {
public:
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class Bool : public AllStatic {
public:
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class TypeParameter : public AllStatic {
@@ -946,7 +954,7 @@
static word bound_offset();
static word flags_offset();
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
static word parameterized_class_id_offset();
static word index_offset();
static word nullability_offset();
@@ -955,37 +963,37 @@
class LibraryPrefix : public AllStatic {
public:
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class Capability : public AllStatic {
public:
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class ReceivePort : public AllStatic {
public:
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class SendPort : public AllStatic {
public:
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class TransferableTypedData : public AllStatic {
public:
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class StackTrace : public AllStatic {
public:
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class Integer : public AllStatic {
@@ -997,7 +1005,7 @@
class Smi : public AllStatic {
public:
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class WeakProperty : public AllStatic {
@@ -1005,13 +1013,13 @@
static word key_offset();
static word value_offset();
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class MirrorReference : public AllStatic {
public:
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class Number : public AllStatic {
@@ -1036,7 +1044,7 @@
static word entrypoint_offset();
static word target_offset();
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class Thread : public AllStatic {
@@ -1222,7 +1230,7 @@
static word HeaderSize();
static word InstanceSize();
static word InstanceSize(word payload_size);
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class InstructionsTable : public AllStatic {
@@ -1230,7 +1238,7 @@
static word HeaderSize();
static word InstanceSize();
static word InstanceSize(intptr_t length);
- static word NextFieldOffset();
+ FINAL_CLASS();
private:
static word element_offset(intptr_t index);
@@ -1248,7 +1256,7 @@
static word HeaderSize();
static word InstanceSize();
static word InstanceSize(word payload_size);
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class Code : public AllStatic {
@@ -1264,7 +1272,7 @@
static word HeaderSize();
static word InstanceSize();
static word InstanceSize(intptr_t length);
- static word NextFieldOffset();
+ FINAL_CLASS();
private:
static word element_offset(intptr_t index);
@@ -1273,7 +1281,7 @@
class WeakSerializationReference : public AllStatic {
public:
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class SubtypeTestCache : public AllStatic {
@@ -1290,13 +1298,13 @@
static const word kInstanceDelayedFunctionTypeArguments;
static const word kTestResult;
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class LoadingUnit : public AllStatic {
public:
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class Context : public AllStatic {
@@ -1307,7 +1315,7 @@
static word variable_offset(intptr_t index);
static word InstanceSize(intptr_t length);
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class Closure : public AllStatic {
@@ -1320,14 +1328,14 @@
static word instantiator_type_arguments_offset();
static word hash_offset();
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class ClosureData : public AllStatic {
public:
static word default_type_arguments_kind_offset();
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class OldPage : public AllStatic {
@@ -1363,14 +1371,14 @@
public:
static word function_offset(classid_t cid, bool sticky);
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class UserTag : public AllStatic {
public:
static word tag_offset();
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class Symbols : public AllStatic {
@@ -1391,7 +1399,7 @@
static word initializer_function_offset();
static word host_offset_or_field_id_offset();
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class TypeParameters : public AllStatic {
@@ -1401,7 +1409,7 @@
static word bounds_offset();
static word defaults_offset();
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
class TypeArguments : public AllStatic {
@@ -1413,7 +1421,7 @@
static word types_offset();
static word InstanceSize(intptr_t length);
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
static const word kMaxElements;
};
@@ -1423,7 +1431,7 @@
class FakeInstance : public AllStatic {
public:
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
};
@@ -1432,7 +1440,7 @@
class FakeInstance : public AllStatic {
public:
static word InstanceSize();
- static word NextFieldOffset();
+ FINAL_CLASS();
};
};
diff --git a/runtime/vm/compiler/runtime_offsets_extracted.h b/runtime/vm/compiler/runtime_offsets_extracted.h
index b57c17d..99f76c0 100644
--- a/runtime/vm/compiler/runtime_offsets_extracted.h
+++ b/runtime/vm/compiler/runtime_offsets_extracted.h
@@ -195,16 +195,16 @@
IsolateGroup_cached_class_table_table_offset = 16;
static constexpr dart::compiler::target::word Isolate_single_step_offset = 36;
static constexpr dart::compiler::target::word Isolate_user_tag_offset = 16;
-static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 16;
+static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 12;
static constexpr dart::compiler::target::word
- LinkedHashBase_deleted_keys_offset = 24;
+ LinkedHashBase_deleted_keys_offset = 20;
static constexpr dart::compiler::target::word LinkedHashBase_hash_mask_offset =
- 12;
-static constexpr dart::compiler::target::word LinkedHashBase_index_offset = 8;
+ 8;
+static constexpr dart::compiler::target::word LinkedHashBase_index_offset = 24;
static constexpr dart::compiler::target::word
LinkedHashBase_type_arguments_offset = 4;
static constexpr dart::compiler::target::word LinkedHashBase_used_data_offset =
- 20;
+ 16;
static constexpr dart::compiler::target::word LocalHandle_ptr_offset = 0;
static constexpr dart::compiler::target::word
MarkingStackBlock_pointers_offset = 8;
@@ -220,11 +220,12 @@
12;
static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
- 128;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 68;
+ 184;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 124;
static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
- 156;
-static constexpr dart::compiler::target::word ObjectStore_type_type_offset = 48;
+ 212;
+static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
+ 104;
static constexpr dart::compiler::target::word OneByteString_data_offset = 12;
static constexpr dart::compiler::target::word PointerBase_data_field_offset = 4;
static constexpr dart::compiler::target::word Pointer_type_arguments_offset = 8;
@@ -245,9 +246,9 @@
static constexpr dart::compiler::target::word
Thread_AllocateArray_entry_point_offset = 368;
static constexpr dart::compiler::target::word Thread_active_exception_offset =
- 724;
+ 732;
static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
- 728;
+ 736;
static constexpr dart::compiler::target::word
Thread_array_write_barrier_code_offset = 120;
static constexpr dart::compiler::target::word
@@ -272,7 +273,7 @@
Thread_allocate_object_slow_entry_point_offset = 288;
static constexpr dart::compiler::target::word
Thread_allocate_object_slow_stub_offset = 196;
-static constexpr dart::compiler::target::word Thread_api_top_scope_offset = 764;
+static constexpr dart::compiler::target::word Thread_api_top_scope_offset = 772;
static constexpr dart::compiler::target::word
Thread_auto_scope_native_wrapper_entry_point_offset = 332;
static constexpr dart::compiler::target::word Thread_bool_false_offset = 112;
@@ -283,7 +284,7 @@
Thread_call_to_runtime_entry_point_offset = 268;
static constexpr dart::compiler::target::word
Thread_call_to_runtime_stub_offset = 136;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 772;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 780;
static constexpr dart::compiler::target::word
Thread_dispatch_table_array_offset = 48;
static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
@@ -301,7 +302,7 @@
static constexpr dart::compiler::target::word
Thread_enter_safepoint_stub_offset = 248;
static constexpr dart::compiler::target::word Thread_execution_state_offset =
- 744;
+ 752;
static constexpr dart::compiler::target::word
Thread_exit_safepoint_stub_offset = 252;
static constexpr dart::compiler::target::word
@@ -321,13 +322,13 @@
static constexpr dart::compiler::target::word
Thread_float_zerow_address_offset = 364;
static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
- 732;
+ 740;
static constexpr dart::compiler::target::word
Thread_invoke_dart_code_stub_offset = 132;
static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
- 760;
+ 768;
static constexpr dart::compiler::target::word Thread_isolate_offset = 44;
-static constexpr dart::compiler::target::word Thread_isolate_group_offset = 776;
+static constexpr dart::compiler::target::word Thread_isolate_group_offset = 784;
static constexpr dart::compiler::target::word Thread_field_table_values_offset =
68;
static constexpr dart::compiler::target::word
@@ -369,11 +370,11 @@
static constexpr dart::compiler::target::word Thread_object_null_offset = 104;
static constexpr dart::compiler::target::word
Thread_predefined_symbols_address_offset = 336;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 736;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 744;
static constexpr dart::compiler::target::word
- Thread_saved_shadow_call_stack_offset = 740;
+ Thread_saved_shadow_call_stack_offset = 748;
static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
- 748;
+ 756;
static constexpr dart::compiler::target::word
Thread_slow_type_test_stub_offset = 240;
static constexpr dart::compiler::target::word
@@ -407,9 +408,9 @@
static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
36;
static constexpr dart::compiler::target::word Thread_heap_base_offset = 40;
-static constexpr dart::compiler::target::word Thread_callback_code_offset = 752;
+static constexpr dart::compiler::target::word Thread_callback_code_offset = 760;
static constexpr dart::compiler::target::word
- Thread_callback_stack_return_offset = 756;
+ Thread_callback_stack_return_offset = 764;
static constexpr dart::compiler::target::word TimelineStream_enabled_offset = 8;
static constexpr dart::compiler::target::word TwoByteString_data_offset = 12;
static constexpr dart::compiler::target::word Type_arguments_offset = 16;
@@ -469,7 +470,7 @@
4, 12, 8, 16};
static constexpr dart::compiler::target::word
Thread_write_barrier_wrappers_thread_offset[] = {
- 692, 696, 700, 704, 708, -1, 712, -1, 716, 720, -1, -1, -1, -1, -1, -1};
+ 700, 704, 708, 712, 716, -1, 720, -1, 724, 728, -1, -1, -1, -1, -1, -1};
static constexpr dart::compiler::target::word AbstractType_InstanceSize = 12;
static constexpr dart::compiler::target::word ApiError_InstanceSize = 8;
static constexpr dart::compiler::target::word Array_header_size = 12;
@@ -737,16 +738,16 @@
IsolateGroup_cached_class_table_table_offset = 32;
static constexpr dart::compiler::target::word Isolate_single_step_offset = 72;
static constexpr dart::compiler::target::word Isolate_user_tag_offset = 32;
-static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 32;
+static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 24;
static constexpr dart::compiler::target::word
- LinkedHashBase_deleted_keys_offset = 48;
+ LinkedHashBase_deleted_keys_offset = 40;
static constexpr dart::compiler::target::word LinkedHashBase_hash_mask_offset =
- 24;
-static constexpr dart::compiler::target::word LinkedHashBase_index_offset = 16;
+ 16;
+static constexpr dart::compiler::target::word LinkedHashBase_index_offset = 48;
static constexpr dart::compiler::target::word
LinkedHashBase_type_arguments_offset = 8;
static constexpr dart::compiler::target::word LinkedHashBase_used_data_offset =
- 40;
+ 32;
static constexpr dart::compiler::target::word LocalHandle_ptr_offset = 0;
static constexpr dart::compiler::target::word
MarkingStackBlock_pointers_offset = 16;
@@ -762,11 +763,12 @@
24;
static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
- 256;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 136;
+ 368;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 248;
static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
- 312;
-static constexpr dart::compiler::target::word ObjectStore_type_type_offset = 96;
+ 424;
+static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
+ 208;
static constexpr dart::compiler::target::word OneByteString_data_offset = 16;
static constexpr dart::compiler::target::word PointerBase_data_field_offset = 8;
static constexpr dart::compiler::target::word Pointer_type_arguments_offset =
@@ -788,9 +790,9 @@
static constexpr dart::compiler::target::word
Thread_AllocateArray_entry_point_offset = 728;
static constexpr dart::compiler::target::word Thread_active_exception_offset =
- 1464;
+ 1480;
static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
- 1472;
+ 1488;
static constexpr dart::compiler::target::word
Thread_array_write_barrier_code_offset = 232;
static constexpr dart::compiler::target::word
@@ -816,7 +818,7 @@
static constexpr dart::compiler::target::word
Thread_allocate_object_slow_stub_offset = 384;
static constexpr dart::compiler::target::word Thread_api_top_scope_offset =
- 1544;
+ 1560;
static constexpr dart::compiler::target::word
Thread_auto_scope_native_wrapper_entry_point_offset = 656;
static constexpr dart::compiler::target::word Thread_bool_false_offset = 216;
@@ -827,7 +829,7 @@
Thread_call_to_runtime_entry_point_offset = 528;
static constexpr dart::compiler::target::word
Thread_call_to_runtime_stub_offset = 264;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1560;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1576;
static constexpr dart::compiler::target::word
Thread_dispatch_table_array_offset = 96;
static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
@@ -845,7 +847,7 @@
static constexpr dart::compiler::target::word
Thread_enter_safepoint_stub_offset = 488;
static constexpr dart::compiler::target::word Thread_execution_state_offset =
- 1504;
+ 1520;
static constexpr dart::compiler::target::word
Thread_exit_safepoint_stub_offset = 496;
static constexpr dart::compiler::target::word
@@ -865,14 +867,14 @@
static constexpr dart::compiler::target::word
Thread_float_zerow_address_offset = 720;
static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
- 1480;
+ 1496;
static constexpr dart::compiler::target::word
Thread_invoke_dart_code_stub_offset = 256;
static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
- 1536;
+ 1552;
static constexpr dart::compiler::target::word Thread_isolate_offset = 88;
static constexpr dart::compiler::target::word Thread_isolate_group_offset =
- 1568;
+ 1584;
static constexpr dart::compiler::target::word Thread_field_table_values_offset =
136;
static constexpr dart::compiler::target::word
@@ -914,11 +916,11 @@
static constexpr dart::compiler::target::word Thread_object_null_offset = 200;
static constexpr dart::compiler::target::word
Thread_predefined_symbols_address_offset = 664;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1488;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1504;
static constexpr dart::compiler::target::word
- Thread_saved_shadow_call_stack_offset = 1496;
+ Thread_saved_shadow_call_stack_offset = 1512;
static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
- 1512;
+ 1528;
static constexpr dart::compiler::target::word
Thread_slow_type_test_stub_offset = 472;
static constexpr dart::compiler::target::word
@@ -953,9 +955,9 @@
72;
static constexpr dart::compiler::target::word Thread_heap_base_offset = 80;
static constexpr dart::compiler::target::word Thread_callback_code_offset =
- 1520;
+ 1536;
static constexpr dart::compiler::target::word
- Thread_callback_stack_return_offset = 1528;
+ Thread_callback_stack_return_offset = 1544;
static constexpr dart::compiler::target::word TimelineStream_enabled_offset =
16;
static constexpr dart::compiler::target::word TwoByteString_data_offset = 16;
@@ -1016,8 +1018,8 @@
8, 24, 16, 32};
static constexpr dart::compiler::target::word
Thread_write_barrier_wrappers_thread_offset[] = {
- 1376, 1384, 1392, 1400, -1, -1, 1408, 1416,
- 1424, 1432, 1440, -1, 1448, 1456, -1, -1};
+ 1392, 1400, 1408, 1416, -1, -1, 1424, 1432,
+ 1440, 1448, 1456, -1, 1464, 1472, -1, -1};
static constexpr dart::compiler::target::word AbstractType_InstanceSize = 24;
static constexpr dart::compiler::target::word ApiError_InstanceSize = 16;
static constexpr dart::compiler::target::word Array_header_size = 24;
@@ -1284,16 +1286,16 @@
IsolateGroup_cached_class_table_table_offset = 16;
static constexpr dart::compiler::target::word Isolate_single_step_offset = 36;
static constexpr dart::compiler::target::word Isolate_user_tag_offset = 16;
-static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 16;
+static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 12;
static constexpr dart::compiler::target::word
- LinkedHashBase_deleted_keys_offset = 24;
+ LinkedHashBase_deleted_keys_offset = 20;
static constexpr dart::compiler::target::word LinkedHashBase_hash_mask_offset =
- 12;
-static constexpr dart::compiler::target::word LinkedHashBase_index_offset = 8;
+ 8;
+static constexpr dart::compiler::target::word LinkedHashBase_index_offset = 24;
static constexpr dart::compiler::target::word
LinkedHashBase_type_arguments_offset = 4;
static constexpr dart::compiler::target::word LinkedHashBase_used_data_offset =
- 20;
+ 16;
static constexpr dart::compiler::target::word LocalHandle_ptr_offset = 0;
static constexpr dart::compiler::target::word
MarkingStackBlock_pointers_offset = 8;
@@ -1309,11 +1311,12 @@
12;
static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
- 128;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 68;
+ 184;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 124;
static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
- 156;
-static constexpr dart::compiler::target::word ObjectStore_type_type_offset = 48;
+ 212;
+static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
+ 104;
static constexpr dart::compiler::target::word OneByteString_data_offset = 12;
static constexpr dart::compiler::target::word PointerBase_data_field_offset = 4;
static constexpr dart::compiler::target::word Pointer_type_arguments_offset = 8;
@@ -1334,9 +1337,9 @@
static constexpr dart::compiler::target::word
Thread_AllocateArray_entry_point_offset = 368;
static constexpr dart::compiler::target::word Thread_active_exception_offset =
- 692;
+ 700;
static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
- 696;
+ 704;
static constexpr dart::compiler::target::word
Thread_array_write_barrier_code_offset = 120;
static constexpr dart::compiler::target::word
@@ -1361,7 +1364,7 @@
Thread_allocate_object_slow_entry_point_offset = 288;
static constexpr dart::compiler::target::word
Thread_allocate_object_slow_stub_offset = 196;
-static constexpr dart::compiler::target::word Thread_api_top_scope_offset = 732;
+static constexpr dart::compiler::target::word Thread_api_top_scope_offset = 740;
static constexpr dart::compiler::target::word
Thread_auto_scope_native_wrapper_entry_point_offset = 332;
static constexpr dart::compiler::target::word Thread_bool_false_offset = 112;
@@ -1372,7 +1375,7 @@
Thread_call_to_runtime_entry_point_offset = 268;
static constexpr dart::compiler::target::word
Thread_call_to_runtime_stub_offset = 136;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 740;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 748;
static constexpr dart::compiler::target::word
Thread_dispatch_table_array_offset = 48;
static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
@@ -1390,7 +1393,7 @@
static constexpr dart::compiler::target::word
Thread_enter_safepoint_stub_offset = 248;
static constexpr dart::compiler::target::word Thread_execution_state_offset =
- 712;
+ 720;
static constexpr dart::compiler::target::word
Thread_exit_safepoint_stub_offset = 252;
static constexpr dart::compiler::target::word
@@ -1410,13 +1413,13 @@
static constexpr dart::compiler::target::word
Thread_float_zerow_address_offset = 364;
static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
- 700;
+ 708;
static constexpr dart::compiler::target::word
Thread_invoke_dart_code_stub_offset = 132;
static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
- 728;
+ 736;
static constexpr dart::compiler::target::word Thread_isolate_offset = 44;
-static constexpr dart::compiler::target::word Thread_isolate_group_offset = 744;
+static constexpr dart::compiler::target::word Thread_isolate_group_offset = 752;
static constexpr dart::compiler::target::word Thread_field_table_values_offset =
68;
static constexpr dart::compiler::target::word
@@ -1458,11 +1461,11 @@
static constexpr dart::compiler::target::word Thread_object_null_offset = 104;
static constexpr dart::compiler::target::word
Thread_predefined_symbols_address_offset = 336;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 704;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 712;
static constexpr dart::compiler::target::word
- Thread_saved_shadow_call_stack_offset = 708;
+ Thread_saved_shadow_call_stack_offset = 716;
static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
- 716;
+ 724;
static constexpr dart::compiler::target::word
Thread_slow_type_test_stub_offset = 240;
static constexpr dart::compiler::target::word
@@ -1496,9 +1499,9 @@
static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
36;
static constexpr dart::compiler::target::word Thread_heap_base_offset = 40;
-static constexpr dart::compiler::target::word Thread_callback_code_offset = 720;
+static constexpr dart::compiler::target::word Thread_callback_code_offset = 728;
static constexpr dart::compiler::target::word
- Thread_callback_stack_return_offset = 724;
+ Thread_callback_stack_return_offset = 732;
static constexpr dart::compiler::target::word TimelineStream_enabled_offset = 8;
static constexpr dart::compiler::target::word TwoByteString_data_offset = 12;
static constexpr dart::compiler::target::word Type_arguments_offset = 16;
@@ -1823,16 +1826,16 @@
IsolateGroup_cached_class_table_table_offset = 32;
static constexpr dart::compiler::target::word Isolate_single_step_offset = 72;
static constexpr dart::compiler::target::word Isolate_user_tag_offset = 32;
-static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 32;
+static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 24;
static constexpr dart::compiler::target::word
- LinkedHashBase_deleted_keys_offset = 48;
+ LinkedHashBase_deleted_keys_offset = 40;
static constexpr dart::compiler::target::word LinkedHashBase_hash_mask_offset =
- 24;
-static constexpr dart::compiler::target::word LinkedHashBase_index_offset = 16;
+ 16;
+static constexpr dart::compiler::target::word LinkedHashBase_index_offset = 48;
static constexpr dart::compiler::target::word
LinkedHashBase_type_arguments_offset = 8;
static constexpr dart::compiler::target::word LinkedHashBase_used_data_offset =
- 40;
+ 32;
static constexpr dart::compiler::target::word LocalHandle_ptr_offset = 0;
static constexpr dart::compiler::target::word
MarkingStackBlock_pointers_offset = 16;
@@ -1848,11 +1851,12 @@
24;
static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
- 256;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 136;
+ 368;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 248;
static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
- 312;
-static constexpr dart::compiler::target::word ObjectStore_type_type_offset = 96;
+ 424;
+static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
+ 208;
static constexpr dart::compiler::target::word OneByteString_data_offset = 16;
static constexpr dart::compiler::target::word PointerBase_data_field_offset = 8;
static constexpr dart::compiler::target::word Pointer_type_arguments_offset =
@@ -1874,9 +1878,9 @@
static constexpr dart::compiler::target::word
Thread_AllocateArray_entry_point_offset = 728;
static constexpr dart::compiler::target::word Thread_active_exception_offset =
- 1528;
+ 1544;
static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
- 1536;
+ 1552;
static constexpr dart::compiler::target::word
Thread_array_write_barrier_code_offset = 232;
static constexpr dart::compiler::target::word
@@ -1902,7 +1906,7 @@
static constexpr dart::compiler::target::word
Thread_allocate_object_slow_stub_offset = 384;
static constexpr dart::compiler::target::word Thread_api_top_scope_offset =
- 1608;
+ 1624;
static constexpr dart::compiler::target::word
Thread_auto_scope_native_wrapper_entry_point_offset = 656;
static constexpr dart::compiler::target::word Thread_bool_false_offset = 216;
@@ -1913,7 +1917,7 @@
Thread_call_to_runtime_entry_point_offset = 528;
static constexpr dart::compiler::target::word
Thread_call_to_runtime_stub_offset = 264;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1624;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1640;
static constexpr dart::compiler::target::word
Thread_dispatch_table_array_offset = 96;
static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
@@ -1931,7 +1935,7 @@
static constexpr dart::compiler::target::word
Thread_enter_safepoint_stub_offset = 488;
static constexpr dart::compiler::target::word Thread_execution_state_offset =
- 1568;
+ 1584;
static constexpr dart::compiler::target::word
Thread_exit_safepoint_stub_offset = 496;
static constexpr dart::compiler::target::word
@@ -1951,14 +1955,14 @@
static constexpr dart::compiler::target::word
Thread_float_zerow_address_offset = 720;
static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
- 1544;
+ 1560;
static constexpr dart::compiler::target::word
Thread_invoke_dart_code_stub_offset = 256;
static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
- 1600;
+ 1616;
static constexpr dart::compiler::target::word Thread_isolate_offset = 88;
static constexpr dart::compiler::target::word Thread_isolate_group_offset =
- 1632;
+ 1648;
static constexpr dart::compiler::target::word Thread_field_table_values_offset =
136;
static constexpr dart::compiler::target::word
@@ -2000,11 +2004,11 @@
static constexpr dart::compiler::target::word Thread_object_null_offset = 200;
static constexpr dart::compiler::target::word
Thread_predefined_symbols_address_offset = 664;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1552;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1568;
static constexpr dart::compiler::target::word
- Thread_saved_shadow_call_stack_offset = 1560;
+ Thread_saved_shadow_call_stack_offset = 1576;
static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
- 1576;
+ 1592;
static constexpr dart::compiler::target::word
Thread_slow_type_test_stub_offset = 472;
static constexpr dart::compiler::target::word
@@ -2039,9 +2043,9 @@
72;
static constexpr dart::compiler::target::word Thread_heap_base_offset = 80;
static constexpr dart::compiler::target::word Thread_callback_code_offset =
- 1584;
+ 1600;
static constexpr dart::compiler::target::word
- Thread_callback_stack_return_offset = 1592;
+ Thread_callback_stack_return_offset = 1608;
static constexpr dart::compiler::target::word TimelineStream_enabled_offset =
16;
static constexpr dart::compiler::target::word TwoByteString_data_offset = 16;
@@ -2102,9 +2106,9 @@
8, 24, 16, 32};
static constexpr dart::compiler::target::word
Thread_write_barrier_wrappers_thread_offset[] = {
- 1376, 1384, 1392, 1400, 1408, 1416, 1424, 1432, 1440, 1448, 1456,
- 1464, 1472, 1480, 1488, -1, -1, -1, -1, 1496, 1504, -1,
- -1, 1512, 1520, 1528, -1, -1, -1, -1, -1, -1};
+ 1392, 1400, 1408, 1416, 1424, 1432, 1440, 1448, 1456, 1464, 1472,
+ 1480, 1488, 1496, 1504, -1, -1, -1, -1, 1512, 1520, -1,
+ -1, 1528, 1536, 1544, -1, -1, -1, -1, -1, -1};
static constexpr dart::compiler::target::word AbstractType_InstanceSize = 24;
static constexpr dart::compiler::target::word ApiError_InstanceSize = 16;
static constexpr dart::compiler::target::word Array_header_size = 24;
@@ -2371,16 +2375,16 @@
IsolateGroup_cached_class_table_table_offset = 32;
static constexpr dart::compiler::target::word Isolate_single_step_offset = 72;
static constexpr dart::compiler::target::word Isolate_user_tag_offset = 32;
-static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 20;
+static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 16;
static constexpr dart::compiler::target::word
- LinkedHashBase_deleted_keys_offset = 28;
+ LinkedHashBase_deleted_keys_offset = 24;
static constexpr dart::compiler::target::word LinkedHashBase_hash_mask_offset =
- 16;
-static constexpr dart::compiler::target::word LinkedHashBase_index_offset = 12;
+ 12;
+static constexpr dart::compiler::target::word LinkedHashBase_index_offset = 28;
static constexpr dart::compiler::target::word
LinkedHashBase_type_arguments_offset = 8;
static constexpr dart::compiler::target::word LinkedHashBase_used_data_offset =
- 24;
+ 20;
static constexpr dart::compiler::target::word LocalHandle_ptr_offset = 0;
static constexpr dart::compiler::target::word
MarkingStackBlock_pointers_offset = 16;
@@ -2396,11 +2400,12 @@
24;
static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
- 256;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 136;
+ 368;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 248;
static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
- 312;
-static constexpr dart::compiler::target::word ObjectStore_type_type_offset = 96;
+ 424;
+static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
+ 208;
static constexpr dart::compiler::target::word OneByteString_data_offset = 16;
static constexpr dart::compiler::target::word PointerBase_data_field_offset = 8;
static constexpr dart::compiler::target::word Pointer_type_arguments_offset =
@@ -2422,9 +2427,9 @@
static constexpr dart::compiler::target::word
Thread_AllocateArray_entry_point_offset = 728;
static constexpr dart::compiler::target::word Thread_active_exception_offset =
- 1464;
+ 1480;
static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
- 1472;
+ 1488;
static constexpr dart::compiler::target::word
Thread_array_write_barrier_code_offset = 232;
static constexpr dart::compiler::target::word
@@ -2450,7 +2455,7 @@
static constexpr dart::compiler::target::word
Thread_allocate_object_slow_stub_offset = 384;
static constexpr dart::compiler::target::word Thread_api_top_scope_offset =
- 1544;
+ 1560;
static constexpr dart::compiler::target::word
Thread_auto_scope_native_wrapper_entry_point_offset = 656;
static constexpr dart::compiler::target::word Thread_bool_false_offset = 216;
@@ -2461,7 +2466,7 @@
Thread_call_to_runtime_entry_point_offset = 528;
static constexpr dart::compiler::target::word
Thread_call_to_runtime_stub_offset = 264;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1560;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1576;
static constexpr dart::compiler::target::word
Thread_dispatch_table_array_offset = 96;
static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
@@ -2479,7 +2484,7 @@
static constexpr dart::compiler::target::word
Thread_enter_safepoint_stub_offset = 488;
static constexpr dart::compiler::target::word Thread_execution_state_offset =
- 1504;
+ 1520;
static constexpr dart::compiler::target::word
Thread_exit_safepoint_stub_offset = 496;
static constexpr dart::compiler::target::word
@@ -2499,14 +2504,14 @@
static constexpr dart::compiler::target::word
Thread_float_zerow_address_offset = 720;
static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
- 1480;
+ 1496;
static constexpr dart::compiler::target::word
Thread_invoke_dart_code_stub_offset = 256;
static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
- 1536;
+ 1552;
static constexpr dart::compiler::target::word Thread_isolate_offset = 88;
static constexpr dart::compiler::target::word Thread_isolate_group_offset =
- 1568;
+ 1584;
static constexpr dart::compiler::target::word Thread_field_table_values_offset =
136;
static constexpr dart::compiler::target::word
@@ -2548,11 +2553,11 @@
static constexpr dart::compiler::target::word Thread_object_null_offset = 200;
static constexpr dart::compiler::target::word
Thread_predefined_symbols_address_offset = 664;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1488;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1504;
static constexpr dart::compiler::target::word
- Thread_saved_shadow_call_stack_offset = 1496;
+ Thread_saved_shadow_call_stack_offset = 1512;
static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
- 1512;
+ 1528;
static constexpr dart::compiler::target::word
Thread_slow_type_test_stub_offset = 472;
static constexpr dart::compiler::target::word
@@ -2587,33 +2592,33 @@
72;
static constexpr dart::compiler::target::word Thread_heap_base_offset = 80;
static constexpr dart::compiler::target::word Thread_callback_code_offset =
- 1520;
+ 1536;
static constexpr dart::compiler::target::word
- Thread_callback_stack_return_offset = 1528;
+ Thread_callback_stack_return_offset = 1544;
static constexpr dart::compiler::target::word TimelineStream_enabled_offset =
16;
static constexpr dart::compiler::target::word TwoByteString_data_offset = 16;
-static constexpr dart::compiler::target::word Type_arguments_offset = 24;
-static constexpr dart::compiler::target::word Type_hash_offset = 28;
-static constexpr dart::compiler::target::word Type_type_class_id_offset = 20;
-static constexpr dart::compiler::target::word Type_type_state_offset = 32;
-static constexpr dart::compiler::target::word Type_nullability_offset = 33;
-static constexpr dart::compiler::target::word FunctionType_hash_offset = 36;
+static constexpr dart::compiler::target::word Type_arguments_offset = 28;
+static constexpr dart::compiler::target::word Type_hash_offset = 32;
+static constexpr dart::compiler::target::word Type_type_class_id_offset = 24;
+static constexpr dart::compiler::target::word Type_type_state_offset = 36;
+static constexpr dart::compiler::target::word Type_nullability_offset = 37;
+static constexpr dart::compiler::target::word FunctionType_hash_offset = 40;
static constexpr dart::compiler::target::word
- FunctionType_packed_parameter_counts_offset = 40;
+ FunctionType_packed_parameter_counts_offset = 44;
static constexpr dart::compiler::target::word
- FunctionType_packed_type_parameter_counts_offset = 44;
+ FunctionType_packed_type_parameter_counts_offset = 48;
static constexpr dart::compiler::target::word
- FunctionType_parameter_types_offset = 28;
+ FunctionType_parameter_types_offset = 32;
static constexpr dart::compiler::target::word
- FunctionType_named_parameter_names_offset = 32;
+ FunctionType_named_parameter_names_offset = 36;
static constexpr dart::compiler::target::word
- FunctionType_type_parameters_offset = 20;
+ FunctionType_type_parameters_offset = 24;
static constexpr dart::compiler::target::word
- TypeParameter_parameterized_class_id_offset = 28;
-static constexpr dart::compiler::target::word TypeParameter_index_offset = 31;
+ TypeParameter_parameterized_class_id_offset = 32;
+static constexpr dart::compiler::target::word TypeParameter_index_offset = 35;
static constexpr dart::compiler::target::word TypeParameter_nullability_offset =
- 33;
+ 37;
static constexpr dart::compiler::target::word
TypeArguments_instantiations_offset = 8;
static constexpr dart::compiler::target::word TypeArguments_length_offset = 12;
@@ -2625,13 +2630,13 @@
static constexpr dart::compiler::target::word TypeParameters_bounds_offset = 16;
static constexpr dart::compiler::target::word TypeParameters_defaults_offset =
20;
-static constexpr dart::compiler::target::word TypeParameter_bound_offset = 24;
-static constexpr dart::compiler::target::word TypeParameter_flags_offset = 32;
-static constexpr dart::compiler::target::word TypeRef_type_offset = 20;
-static constexpr dart::compiler::target::word TypedDataBase_length_offset = 16;
-static constexpr dart::compiler::target::word TypedDataView_data_offset = 20;
+static constexpr dart::compiler::target::word TypeParameter_bound_offset = 28;
+static constexpr dart::compiler::target::word TypeParameter_flags_offset = 36;
+static constexpr dart::compiler::target::word TypeRef_type_offset = 24;
+static constexpr dart::compiler::target::word TypedDataBase_length_offset = 20;
+static constexpr dart::compiler::target::word TypedDataView_data_offset = 24;
static constexpr dart::compiler::target::word
- TypedDataView_offset_in_bytes_offset = 24;
+ TypedDataView_offset_in_bytes_offset = 28;
static constexpr dart::compiler::target::word TypedData_data_offset = 24;
static constexpr dart::compiler::target::word
UnhandledException_exception_offset = 8;
@@ -2650,8 +2655,8 @@
8, 24, 16, 32};
static constexpr dart::compiler::target::word
Thread_write_barrier_wrappers_thread_offset[] = {
- 1376, 1384, 1392, 1400, -1, -1, 1408, 1416,
- 1424, 1432, 1440, -1, 1448, 1456, -1, -1};
+ 1392, 1400, 1408, 1416, -1, -1, 1424, 1432,
+ 1440, 1448, 1456, -1, 1464, 1472, -1, -1};
static constexpr dart::compiler::target::word AbstractType_InstanceSize = 24;
static constexpr dart::compiler::target::word ApiError_InstanceSize = 16;
static constexpr dart::compiler::target::word Array_header_size = 16;
@@ -2678,7 +2683,7 @@
static constexpr dart::compiler::target::word Float32x4_InstanceSize = 24;
static constexpr dart::compiler::target::word Float64x2_InstanceSize = 24;
static constexpr dart::compiler::target::word Function_InstanceSize = 96;
-static constexpr dart::compiler::target::word FunctionType_InstanceSize = 48;
+static constexpr dart::compiler::target::word FunctionType_InstanceSize = 56;
static constexpr dart::compiler::target::word FutureOr_InstanceSize = 16;
static constexpr dart::compiler::target::word GrowableObjectArray_InstanceSize =
24;
@@ -2726,7 +2731,7 @@
static constexpr dart::compiler::target::word Type_InstanceSize = 40;
static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 40;
static constexpr dart::compiler::target::word TypeParameters_InstanceSize = 24;
-static constexpr dart::compiler::target::word TypeRef_InstanceSize = 24;
+static constexpr dart::compiler::target::word TypeRef_InstanceSize = 32;
static constexpr dart::compiler::target::word TypedData_HeaderSize = 24;
static constexpr dart::compiler::target::word TypedDataBase_InstanceSize = 24;
static constexpr dart::compiler::target::word TypedDataView_InstanceSize = 32;
@@ -2918,16 +2923,16 @@
IsolateGroup_cached_class_table_table_offset = 32;
static constexpr dart::compiler::target::word Isolate_single_step_offset = 72;
static constexpr dart::compiler::target::word Isolate_user_tag_offset = 32;
-static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 20;
+static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 16;
static constexpr dart::compiler::target::word
- LinkedHashBase_deleted_keys_offset = 28;
+ LinkedHashBase_deleted_keys_offset = 24;
static constexpr dart::compiler::target::word LinkedHashBase_hash_mask_offset =
- 16;
-static constexpr dart::compiler::target::word LinkedHashBase_index_offset = 12;
+ 12;
+static constexpr dart::compiler::target::word LinkedHashBase_index_offset = 28;
static constexpr dart::compiler::target::word
LinkedHashBase_type_arguments_offset = 8;
static constexpr dart::compiler::target::word LinkedHashBase_used_data_offset =
- 24;
+ 20;
static constexpr dart::compiler::target::word LocalHandle_ptr_offset = 0;
static constexpr dart::compiler::target::word
MarkingStackBlock_pointers_offset = 16;
@@ -2943,11 +2948,12 @@
24;
static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
- 256;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 136;
+ 368;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 248;
static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
- 312;
-static constexpr dart::compiler::target::word ObjectStore_type_type_offset = 96;
+ 424;
+static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
+ 208;
static constexpr dart::compiler::target::word OneByteString_data_offset = 16;
static constexpr dart::compiler::target::word PointerBase_data_field_offset = 8;
static constexpr dart::compiler::target::word Pointer_type_arguments_offset =
@@ -2969,9 +2975,9 @@
static constexpr dart::compiler::target::word
Thread_AllocateArray_entry_point_offset = 728;
static constexpr dart::compiler::target::word Thread_active_exception_offset =
- 1528;
+ 1544;
static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
- 1536;
+ 1552;
static constexpr dart::compiler::target::word
Thread_array_write_barrier_code_offset = 232;
static constexpr dart::compiler::target::word
@@ -2997,7 +3003,7 @@
static constexpr dart::compiler::target::word
Thread_allocate_object_slow_stub_offset = 384;
static constexpr dart::compiler::target::word Thread_api_top_scope_offset =
- 1608;
+ 1624;
static constexpr dart::compiler::target::word
Thread_auto_scope_native_wrapper_entry_point_offset = 656;
static constexpr dart::compiler::target::word Thread_bool_false_offset = 216;
@@ -3008,7 +3014,7 @@
Thread_call_to_runtime_entry_point_offset = 528;
static constexpr dart::compiler::target::word
Thread_call_to_runtime_stub_offset = 264;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1624;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1640;
static constexpr dart::compiler::target::word
Thread_dispatch_table_array_offset = 96;
static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
@@ -3026,7 +3032,7 @@
static constexpr dart::compiler::target::word
Thread_enter_safepoint_stub_offset = 488;
static constexpr dart::compiler::target::word Thread_execution_state_offset =
- 1568;
+ 1584;
static constexpr dart::compiler::target::word
Thread_exit_safepoint_stub_offset = 496;
static constexpr dart::compiler::target::word
@@ -3046,14 +3052,14 @@
static constexpr dart::compiler::target::word
Thread_float_zerow_address_offset = 720;
static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
- 1544;
+ 1560;
static constexpr dart::compiler::target::word
Thread_invoke_dart_code_stub_offset = 256;
static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
- 1600;
+ 1616;
static constexpr dart::compiler::target::word Thread_isolate_offset = 88;
static constexpr dart::compiler::target::word Thread_isolate_group_offset =
- 1632;
+ 1648;
static constexpr dart::compiler::target::word Thread_field_table_values_offset =
136;
static constexpr dart::compiler::target::word
@@ -3095,11 +3101,11 @@
static constexpr dart::compiler::target::word Thread_object_null_offset = 200;
static constexpr dart::compiler::target::word
Thread_predefined_symbols_address_offset = 664;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1552;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1568;
static constexpr dart::compiler::target::word
- Thread_saved_shadow_call_stack_offset = 1560;
+ Thread_saved_shadow_call_stack_offset = 1576;
static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
- 1576;
+ 1592;
static constexpr dart::compiler::target::word
Thread_slow_type_test_stub_offset = 472;
static constexpr dart::compiler::target::word
@@ -3134,33 +3140,33 @@
72;
static constexpr dart::compiler::target::word Thread_heap_base_offset = 80;
static constexpr dart::compiler::target::word Thread_callback_code_offset =
- 1584;
+ 1600;
static constexpr dart::compiler::target::word
- Thread_callback_stack_return_offset = 1592;
+ Thread_callback_stack_return_offset = 1608;
static constexpr dart::compiler::target::word TimelineStream_enabled_offset =
16;
static constexpr dart::compiler::target::word TwoByteString_data_offset = 16;
-static constexpr dart::compiler::target::word Type_arguments_offset = 24;
-static constexpr dart::compiler::target::word Type_hash_offset = 28;
-static constexpr dart::compiler::target::word Type_type_class_id_offset = 20;
-static constexpr dart::compiler::target::word Type_type_state_offset = 32;
-static constexpr dart::compiler::target::word Type_nullability_offset = 33;
-static constexpr dart::compiler::target::word FunctionType_hash_offset = 36;
+static constexpr dart::compiler::target::word Type_arguments_offset = 28;
+static constexpr dart::compiler::target::word Type_hash_offset = 32;
+static constexpr dart::compiler::target::word Type_type_class_id_offset = 24;
+static constexpr dart::compiler::target::word Type_type_state_offset = 36;
+static constexpr dart::compiler::target::word Type_nullability_offset = 37;
+static constexpr dart::compiler::target::word FunctionType_hash_offset = 40;
static constexpr dart::compiler::target::word
- FunctionType_packed_parameter_counts_offset = 40;
+ FunctionType_packed_parameter_counts_offset = 44;
static constexpr dart::compiler::target::word
- FunctionType_packed_type_parameter_counts_offset = 44;
+ FunctionType_packed_type_parameter_counts_offset = 48;
static constexpr dart::compiler::target::word
- FunctionType_parameter_types_offset = 28;
+ FunctionType_parameter_types_offset = 32;
static constexpr dart::compiler::target::word
- FunctionType_named_parameter_names_offset = 32;
+ FunctionType_named_parameter_names_offset = 36;
static constexpr dart::compiler::target::word
- FunctionType_type_parameters_offset = 20;
+ FunctionType_type_parameters_offset = 24;
static constexpr dart::compiler::target::word
- TypeParameter_parameterized_class_id_offset = 28;
-static constexpr dart::compiler::target::word TypeParameter_index_offset = 31;
+ TypeParameter_parameterized_class_id_offset = 32;
+static constexpr dart::compiler::target::word TypeParameter_index_offset = 35;
static constexpr dart::compiler::target::word TypeParameter_nullability_offset =
- 33;
+ 37;
static constexpr dart::compiler::target::word
TypeArguments_instantiations_offset = 8;
static constexpr dart::compiler::target::word TypeArguments_length_offset = 12;
@@ -3172,13 +3178,13 @@
static constexpr dart::compiler::target::word TypeParameters_bounds_offset = 16;
static constexpr dart::compiler::target::word TypeParameters_defaults_offset =
20;
-static constexpr dart::compiler::target::word TypeParameter_bound_offset = 24;
-static constexpr dart::compiler::target::word TypeParameter_flags_offset = 32;
-static constexpr dart::compiler::target::word TypeRef_type_offset = 20;
-static constexpr dart::compiler::target::word TypedDataBase_length_offset = 16;
-static constexpr dart::compiler::target::word TypedDataView_data_offset = 20;
+static constexpr dart::compiler::target::word TypeParameter_bound_offset = 28;
+static constexpr dart::compiler::target::word TypeParameter_flags_offset = 36;
+static constexpr dart::compiler::target::word TypeRef_type_offset = 24;
+static constexpr dart::compiler::target::word TypedDataBase_length_offset = 20;
+static constexpr dart::compiler::target::word TypedDataView_data_offset = 24;
static constexpr dart::compiler::target::word
- TypedDataView_offset_in_bytes_offset = 24;
+ TypedDataView_offset_in_bytes_offset = 28;
static constexpr dart::compiler::target::word TypedData_data_offset = 24;
static constexpr dart::compiler::target::word
UnhandledException_exception_offset = 8;
@@ -3197,9 +3203,9 @@
8, 24, 16, 32};
static constexpr dart::compiler::target::word
Thread_write_barrier_wrappers_thread_offset[] = {
- 1376, 1384, 1392, 1400, 1408, 1416, 1424, 1432, 1440, 1448, 1456,
- 1464, 1472, 1480, 1488, -1, -1, -1, -1, 1496, 1504, -1,
- -1, 1512, 1520, 1528, -1, -1, -1, -1, -1, -1};
+ 1392, 1400, 1408, 1416, 1424, 1432, 1440, 1448, 1456, 1464, 1472,
+ 1480, 1488, 1496, 1504, -1, -1, -1, -1, 1512, 1520, -1,
+ -1, 1528, 1536, 1544, -1, -1, -1, -1, -1, -1};
static constexpr dart::compiler::target::word AbstractType_InstanceSize = 24;
static constexpr dart::compiler::target::word ApiError_InstanceSize = 16;
static constexpr dart::compiler::target::word Array_header_size = 16;
@@ -3226,7 +3232,7 @@
static constexpr dart::compiler::target::word Float32x4_InstanceSize = 24;
static constexpr dart::compiler::target::word Float64x2_InstanceSize = 24;
static constexpr dart::compiler::target::word Function_InstanceSize = 96;
-static constexpr dart::compiler::target::word FunctionType_InstanceSize = 48;
+static constexpr dart::compiler::target::word FunctionType_InstanceSize = 56;
static constexpr dart::compiler::target::word FutureOr_InstanceSize = 16;
static constexpr dart::compiler::target::word GrowableObjectArray_InstanceSize =
24;
@@ -3274,7 +3280,7 @@
static constexpr dart::compiler::target::word Type_InstanceSize = 40;
static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 40;
static constexpr dart::compiler::target::word TypeParameters_InstanceSize = 24;
-static constexpr dart::compiler::target::word TypeRef_InstanceSize = 24;
+static constexpr dart::compiler::target::word TypeRef_InstanceSize = 32;
static constexpr dart::compiler::target::word TypedData_HeaderSize = 24;
static constexpr dart::compiler::target::word TypedDataBase_InstanceSize = 24;
static constexpr dart::compiler::target::word TypedDataView_InstanceSize = 32;
@@ -3462,16 +3468,16 @@
static constexpr dart::compiler::target::word
IsolateGroup_cached_class_table_table_offset = 16;
static constexpr dart::compiler::target::word Isolate_user_tag_offset = 16;
-static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 16;
+static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 12;
static constexpr dart::compiler::target::word
- LinkedHashBase_deleted_keys_offset = 24;
+ LinkedHashBase_deleted_keys_offset = 20;
static constexpr dart::compiler::target::word LinkedHashBase_hash_mask_offset =
- 12;
-static constexpr dart::compiler::target::word LinkedHashBase_index_offset = 8;
+ 8;
+static constexpr dart::compiler::target::word LinkedHashBase_index_offset = 24;
static constexpr dart::compiler::target::word
LinkedHashBase_type_arguments_offset = 4;
static constexpr dart::compiler::target::word LinkedHashBase_used_data_offset =
- 20;
+ 16;
static constexpr dart::compiler::target::word LocalHandle_ptr_offset = 0;
static constexpr dart::compiler::target::word
MarkingStackBlock_pointers_offset = 8;
@@ -3487,11 +3493,12 @@
12;
static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
- 128;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 68;
+ 184;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 124;
static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
- 156;
-static constexpr dart::compiler::target::word ObjectStore_type_type_offset = 48;
+ 212;
+static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
+ 104;
static constexpr dart::compiler::target::word OneByteString_data_offset = 12;
static constexpr dart::compiler::target::word PointerBase_data_field_offset = 4;
static constexpr dart::compiler::target::word Pointer_type_arguments_offset = 8;
@@ -3512,9 +3519,9 @@
static constexpr dart::compiler::target::word
Thread_AllocateArray_entry_point_offset = 368;
static constexpr dart::compiler::target::word Thread_active_exception_offset =
- 724;
+ 732;
static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
- 728;
+ 736;
static constexpr dart::compiler::target::word
Thread_array_write_barrier_code_offset = 120;
static constexpr dart::compiler::target::word
@@ -3539,7 +3546,7 @@
Thread_allocate_object_slow_entry_point_offset = 288;
static constexpr dart::compiler::target::word
Thread_allocate_object_slow_stub_offset = 196;
-static constexpr dart::compiler::target::word Thread_api_top_scope_offset = 764;
+static constexpr dart::compiler::target::word Thread_api_top_scope_offset = 772;
static constexpr dart::compiler::target::word
Thread_auto_scope_native_wrapper_entry_point_offset = 332;
static constexpr dart::compiler::target::word Thread_bool_false_offset = 112;
@@ -3550,7 +3557,7 @@
Thread_call_to_runtime_entry_point_offset = 268;
static constexpr dart::compiler::target::word
Thread_call_to_runtime_stub_offset = 136;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 772;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 780;
static constexpr dart::compiler::target::word
Thread_dispatch_table_array_offset = 48;
static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
@@ -3568,7 +3575,7 @@
static constexpr dart::compiler::target::word
Thread_enter_safepoint_stub_offset = 248;
static constexpr dart::compiler::target::word Thread_execution_state_offset =
- 744;
+ 752;
static constexpr dart::compiler::target::word
Thread_exit_safepoint_stub_offset = 252;
static constexpr dart::compiler::target::word
@@ -3588,13 +3595,13 @@
static constexpr dart::compiler::target::word
Thread_float_zerow_address_offset = 364;
static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
- 732;
+ 740;
static constexpr dart::compiler::target::word
Thread_invoke_dart_code_stub_offset = 132;
static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
- 760;
+ 768;
static constexpr dart::compiler::target::word Thread_isolate_offset = 44;
-static constexpr dart::compiler::target::word Thread_isolate_group_offset = 776;
+static constexpr dart::compiler::target::word Thread_isolate_group_offset = 784;
static constexpr dart::compiler::target::word Thread_field_table_values_offset =
68;
static constexpr dart::compiler::target::word
@@ -3636,11 +3643,11 @@
static constexpr dart::compiler::target::word Thread_object_null_offset = 104;
static constexpr dart::compiler::target::word
Thread_predefined_symbols_address_offset = 336;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 736;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 744;
static constexpr dart::compiler::target::word
- Thread_saved_shadow_call_stack_offset = 740;
+ Thread_saved_shadow_call_stack_offset = 748;
static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
- 748;
+ 756;
static constexpr dart::compiler::target::word
Thread_slow_type_test_stub_offset = 240;
static constexpr dart::compiler::target::word
@@ -3674,9 +3681,9 @@
static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
36;
static constexpr dart::compiler::target::word Thread_heap_base_offset = 40;
-static constexpr dart::compiler::target::word Thread_callback_code_offset = 752;
+static constexpr dart::compiler::target::word Thread_callback_code_offset = 760;
static constexpr dart::compiler::target::word
- Thread_callback_stack_return_offset = 756;
+ Thread_callback_stack_return_offset = 764;
static constexpr dart::compiler::target::word TimelineStream_enabled_offset = 8;
static constexpr dart::compiler::target::word TwoByteString_data_offset = 12;
static constexpr dart::compiler::target::word Type_arguments_offset = 16;
@@ -3736,7 +3743,7 @@
4, 12, 8, 16};
static constexpr dart::compiler::target::word
Thread_write_barrier_wrappers_thread_offset[] = {
- 692, 696, 700, 704, 708, -1, 712, -1, 716, 720, -1, -1, -1, -1, -1, -1};
+ 700, 704, 708, 712, 716, -1, 720, -1, 724, 728, -1, -1, -1, -1, -1, -1};
static constexpr dart::compiler::target::word AbstractType_InstanceSize = 12;
static constexpr dart::compiler::target::word ApiError_InstanceSize = 8;
static constexpr dart::compiler::target::word Array_header_size = 12;
@@ -3998,16 +4005,16 @@
static constexpr dart::compiler::target::word
IsolateGroup_cached_class_table_table_offset = 32;
static constexpr dart::compiler::target::word Isolate_user_tag_offset = 32;
-static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 32;
+static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 24;
static constexpr dart::compiler::target::word
- LinkedHashBase_deleted_keys_offset = 48;
+ LinkedHashBase_deleted_keys_offset = 40;
static constexpr dart::compiler::target::word LinkedHashBase_hash_mask_offset =
- 24;
-static constexpr dart::compiler::target::word LinkedHashBase_index_offset = 16;
+ 16;
+static constexpr dart::compiler::target::word LinkedHashBase_index_offset = 48;
static constexpr dart::compiler::target::word
LinkedHashBase_type_arguments_offset = 8;
static constexpr dart::compiler::target::word LinkedHashBase_used_data_offset =
- 40;
+ 32;
static constexpr dart::compiler::target::word LocalHandle_ptr_offset = 0;
static constexpr dart::compiler::target::word
MarkingStackBlock_pointers_offset = 16;
@@ -4023,11 +4030,12 @@
24;
static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
- 256;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 136;
+ 368;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 248;
static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
- 312;
-static constexpr dart::compiler::target::word ObjectStore_type_type_offset = 96;
+ 424;
+static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
+ 208;
static constexpr dart::compiler::target::word OneByteString_data_offset = 16;
static constexpr dart::compiler::target::word PointerBase_data_field_offset = 8;
static constexpr dart::compiler::target::word Pointer_type_arguments_offset =
@@ -4049,9 +4057,9 @@
static constexpr dart::compiler::target::word
Thread_AllocateArray_entry_point_offset = 728;
static constexpr dart::compiler::target::word Thread_active_exception_offset =
- 1464;
+ 1480;
static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
- 1472;
+ 1488;
static constexpr dart::compiler::target::word
Thread_array_write_barrier_code_offset = 232;
static constexpr dart::compiler::target::word
@@ -4077,7 +4085,7 @@
static constexpr dart::compiler::target::word
Thread_allocate_object_slow_stub_offset = 384;
static constexpr dart::compiler::target::word Thread_api_top_scope_offset =
- 1544;
+ 1560;
static constexpr dart::compiler::target::word
Thread_auto_scope_native_wrapper_entry_point_offset = 656;
static constexpr dart::compiler::target::word Thread_bool_false_offset = 216;
@@ -4088,7 +4096,7 @@
Thread_call_to_runtime_entry_point_offset = 528;
static constexpr dart::compiler::target::word
Thread_call_to_runtime_stub_offset = 264;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1560;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1576;
static constexpr dart::compiler::target::word
Thread_dispatch_table_array_offset = 96;
static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
@@ -4106,7 +4114,7 @@
static constexpr dart::compiler::target::word
Thread_enter_safepoint_stub_offset = 488;
static constexpr dart::compiler::target::word Thread_execution_state_offset =
- 1504;
+ 1520;
static constexpr dart::compiler::target::word
Thread_exit_safepoint_stub_offset = 496;
static constexpr dart::compiler::target::word
@@ -4126,14 +4134,14 @@
static constexpr dart::compiler::target::word
Thread_float_zerow_address_offset = 720;
static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
- 1480;
+ 1496;
static constexpr dart::compiler::target::word
Thread_invoke_dart_code_stub_offset = 256;
static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
- 1536;
+ 1552;
static constexpr dart::compiler::target::word Thread_isolate_offset = 88;
static constexpr dart::compiler::target::word Thread_isolate_group_offset =
- 1568;
+ 1584;
static constexpr dart::compiler::target::word Thread_field_table_values_offset =
136;
static constexpr dart::compiler::target::word
@@ -4175,11 +4183,11 @@
static constexpr dart::compiler::target::word Thread_object_null_offset = 200;
static constexpr dart::compiler::target::word
Thread_predefined_symbols_address_offset = 664;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1488;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1504;
static constexpr dart::compiler::target::word
- Thread_saved_shadow_call_stack_offset = 1496;
+ Thread_saved_shadow_call_stack_offset = 1512;
static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
- 1512;
+ 1528;
static constexpr dart::compiler::target::word
Thread_slow_type_test_stub_offset = 472;
static constexpr dart::compiler::target::word
@@ -4214,9 +4222,9 @@
72;
static constexpr dart::compiler::target::word Thread_heap_base_offset = 80;
static constexpr dart::compiler::target::word Thread_callback_code_offset =
- 1520;
+ 1536;
static constexpr dart::compiler::target::word
- Thread_callback_stack_return_offset = 1528;
+ Thread_callback_stack_return_offset = 1544;
static constexpr dart::compiler::target::word TimelineStream_enabled_offset =
16;
static constexpr dart::compiler::target::word TwoByteString_data_offset = 16;
@@ -4277,8 +4285,8 @@
8, 24, 16, 32};
static constexpr dart::compiler::target::word
Thread_write_barrier_wrappers_thread_offset[] = {
- 1376, 1384, 1392, 1400, -1, -1, 1408, 1416,
- 1424, 1432, 1440, -1, 1448, 1456, -1, -1};
+ 1392, 1400, 1408, 1416, -1, -1, 1424, 1432,
+ 1440, 1448, 1456, -1, 1464, 1472, -1, -1};
static constexpr dart::compiler::target::word AbstractType_InstanceSize = 24;
static constexpr dart::compiler::target::word ApiError_InstanceSize = 16;
static constexpr dart::compiler::target::word Array_header_size = 24;
@@ -4539,16 +4547,16 @@
static constexpr dart::compiler::target::word
IsolateGroup_cached_class_table_table_offset = 16;
static constexpr dart::compiler::target::word Isolate_user_tag_offset = 16;
-static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 16;
+static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 12;
static constexpr dart::compiler::target::word
- LinkedHashBase_deleted_keys_offset = 24;
+ LinkedHashBase_deleted_keys_offset = 20;
static constexpr dart::compiler::target::word LinkedHashBase_hash_mask_offset =
- 12;
-static constexpr dart::compiler::target::word LinkedHashBase_index_offset = 8;
+ 8;
+static constexpr dart::compiler::target::word LinkedHashBase_index_offset = 24;
static constexpr dart::compiler::target::word
LinkedHashBase_type_arguments_offset = 4;
static constexpr dart::compiler::target::word LinkedHashBase_used_data_offset =
- 20;
+ 16;
static constexpr dart::compiler::target::word LocalHandle_ptr_offset = 0;
static constexpr dart::compiler::target::word
MarkingStackBlock_pointers_offset = 8;
@@ -4564,11 +4572,12 @@
12;
static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
- 128;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 68;
+ 184;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 124;
static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
- 156;
-static constexpr dart::compiler::target::word ObjectStore_type_type_offset = 48;
+ 212;
+static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
+ 104;
static constexpr dart::compiler::target::word OneByteString_data_offset = 12;
static constexpr dart::compiler::target::word PointerBase_data_field_offset = 4;
static constexpr dart::compiler::target::word Pointer_type_arguments_offset = 8;
@@ -4589,9 +4598,9 @@
static constexpr dart::compiler::target::word
Thread_AllocateArray_entry_point_offset = 368;
static constexpr dart::compiler::target::word Thread_active_exception_offset =
- 692;
+ 700;
static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
- 696;
+ 704;
static constexpr dart::compiler::target::word
Thread_array_write_barrier_code_offset = 120;
static constexpr dart::compiler::target::word
@@ -4616,7 +4625,7 @@
Thread_allocate_object_slow_entry_point_offset = 288;
static constexpr dart::compiler::target::word
Thread_allocate_object_slow_stub_offset = 196;
-static constexpr dart::compiler::target::word Thread_api_top_scope_offset = 732;
+static constexpr dart::compiler::target::word Thread_api_top_scope_offset = 740;
static constexpr dart::compiler::target::word
Thread_auto_scope_native_wrapper_entry_point_offset = 332;
static constexpr dart::compiler::target::word Thread_bool_false_offset = 112;
@@ -4627,7 +4636,7 @@
Thread_call_to_runtime_entry_point_offset = 268;
static constexpr dart::compiler::target::word
Thread_call_to_runtime_stub_offset = 136;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 740;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 748;
static constexpr dart::compiler::target::word
Thread_dispatch_table_array_offset = 48;
static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
@@ -4645,7 +4654,7 @@
static constexpr dart::compiler::target::word
Thread_enter_safepoint_stub_offset = 248;
static constexpr dart::compiler::target::word Thread_execution_state_offset =
- 712;
+ 720;
static constexpr dart::compiler::target::word
Thread_exit_safepoint_stub_offset = 252;
static constexpr dart::compiler::target::word
@@ -4665,13 +4674,13 @@
static constexpr dart::compiler::target::word
Thread_float_zerow_address_offset = 364;
static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
- 700;
+ 708;
static constexpr dart::compiler::target::word
Thread_invoke_dart_code_stub_offset = 132;
static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
- 728;
+ 736;
static constexpr dart::compiler::target::word Thread_isolate_offset = 44;
-static constexpr dart::compiler::target::word Thread_isolate_group_offset = 744;
+static constexpr dart::compiler::target::word Thread_isolate_group_offset = 752;
static constexpr dart::compiler::target::word Thread_field_table_values_offset =
68;
static constexpr dart::compiler::target::word
@@ -4713,11 +4722,11 @@
static constexpr dart::compiler::target::word Thread_object_null_offset = 104;
static constexpr dart::compiler::target::word
Thread_predefined_symbols_address_offset = 336;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 704;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 712;
static constexpr dart::compiler::target::word
- Thread_saved_shadow_call_stack_offset = 708;
+ Thread_saved_shadow_call_stack_offset = 716;
static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
- 716;
+ 724;
static constexpr dart::compiler::target::word
Thread_slow_type_test_stub_offset = 240;
static constexpr dart::compiler::target::word
@@ -4751,9 +4760,9 @@
static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
36;
static constexpr dart::compiler::target::word Thread_heap_base_offset = 40;
-static constexpr dart::compiler::target::word Thread_callback_code_offset = 720;
+static constexpr dart::compiler::target::word Thread_callback_code_offset = 728;
static constexpr dart::compiler::target::word
- Thread_callback_stack_return_offset = 724;
+ Thread_callback_stack_return_offset = 732;
static constexpr dart::compiler::target::word TimelineStream_enabled_offset = 8;
static constexpr dart::compiler::target::word TwoByteString_data_offset = 12;
static constexpr dart::compiler::target::word Type_arguments_offset = 16;
@@ -5072,16 +5081,16 @@
static constexpr dart::compiler::target::word
IsolateGroup_cached_class_table_table_offset = 32;
static constexpr dart::compiler::target::word Isolate_user_tag_offset = 32;
-static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 32;
+static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 24;
static constexpr dart::compiler::target::word
- LinkedHashBase_deleted_keys_offset = 48;
+ LinkedHashBase_deleted_keys_offset = 40;
static constexpr dart::compiler::target::word LinkedHashBase_hash_mask_offset =
- 24;
-static constexpr dart::compiler::target::word LinkedHashBase_index_offset = 16;
+ 16;
+static constexpr dart::compiler::target::word LinkedHashBase_index_offset = 48;
static constexpr dart::compiler::target::word
LinkedHashBase_type_arguments_offset = 8;
static constexpr dart::compiler::target::word LinkedHashBase_used_data_offset =
- 40;
+ 32;
static constexpr dart::compiler::target::word LocalHandle_ptr_offset = 0;
static constexpr dart::compiler::target::word
MarkingStackBlock_pointers_offset = 16;
@@ -5097,11 +5106,12 @@
24;
static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
- 256;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 136;
+ 368;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 248;
static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
- 312;
-static constexpr dart::compiler::target::word ObjectStore_type_type_offset = 96;
+ 424;
+static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
+ 208;
static constexpr dart::compiler::target::word OneByteString_data_offset = 16;
static constexpr dart::compiler::target::word PointerBase_data_field_offset = 8;
static constexpr dart::compiler::target::word Pointer_type_arguments_offset =
@@ -5123,9 +5133,9 @@
static constexpr dart::compiler::target::word
Thread_AllocateArray_entry_point_offset = 728;
static constexpr dart::compiler::target::word Thread_active_exception_offset =
- 1528;
+ 1544;
static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
- 1536;
+ 1552;
static constexpr dart::compiler::target::word
Thread_array_write_barrier_code_offset = 232;
static constexpr dart::compiler::target::word
@@ -5151,7 +5161,7 @@
static constexpr dart::compiler::target::word
Thread_allocate_object_slow_stub_offset = 384;
static constexpr dart::compiler::target::word Thread_api_top_scope_offset =
- 1608;
+ 1624;
static constexpr dart::compiler::target::word
Thread_auto_scope_native_wrapper_entry_point_offset = 656;
static constexpr dart::compiler::target::word Thread_bool_false_offset = 216;
@@ -5162,7 +5172,7 @@
Thread_call_to_runtime_entry_point_offset = 528;
static constexpr dart::compiler::target::word
Thread_call_to_runtime_stub_offset = 264;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1624;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1640;
static constexpr dart::compiler::target::word
Thread_dispatch_table_array_offset = 96;
static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
@@ -5180,7 +5190,7 @@
static constexpr dart::compiler::target::word
Thread_enter_safepoint_stub_offset = 488;
static constexpr dart::compiler::target::word Thread_execution_state_offset =
- 1568;
+ 1584;
static constexpr dart::compiler::target::word
Thread_exit_safepoint_stub_offset = 496;
static constexpr dart::compiler::target::word
@@ -5200,14 +5210,14 @@
static constexpr dart::compiler::target::word
Thread_float_zerow_address_offset = 720;
static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
- 1544;
+ 1560;
static constexpr dart::compiler::target::word
Thread_invoke_dart_code_stub_offset = 256;
static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
- 1600;
+ 1616;
static constexpr dart::compiler::target::word Thread_isolate_offset = 88;
static constexpr dart::compiler::target::word Thread_isolate_group_offset =
- 1632;
+ 1648;
static constexpr dart::compiler::target::word Thread_field_table_values_offset =
136;
static constexpr dart::compiler::target::word
@@ -5249,11 +5259,11 @@
static constexpr dart::compiler::target::word Thread_object_null_offset = 200;
static constexpr dart::compiler::target::word
Thread_predefined_symbols_address_offset = 664;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1552;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1568;
static constexpr dart::compiler::target::word
- Thread_saved_shadow_call_stack_offset = 1560;
+ Thread_saved_shadow_call_stack_offset = 1576;
static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
- 1576;
+ 1592;
static constexpr dart::compiler::target::word
Thread_slow_type_test_stub_offset = 472;
static constexpr dart::compiler::target::word
@@ -5288,9 +5298,9 @@
72;
static constexpr dart::compiler::target::word Thread_heap_base_offset = 80;
static constexpr dart::compiler::target::word Thread_callback_code_offset =
- 1584;
+ 1600;
static constexpr dart::compiler::target::word
- Thread_callback_stack_return_offset = 1592;
+ Thread_callback_stack_return_offset = 1608;
static constexpr dart::compiler::target::word TimelineStream_enabled_offset =
16;
static constexpr dart::compiler::target::word TwoByteString_data_offset = 16;
@@ -5351,9 +5361,9 @@
8, 24, 16, 32};
static constexpr dart::compiler::target::word
Thread_write_barrier_wrappers_thread_offset[] = {
- 1376, 1384, 1392, 1400, 1408, 1416, 1424, 1432, 1440, 1448, 1456,
- 1464, 1472, 1480, 1488, -1, -1, -1, -1, 1496, 1504, -1,
- -1, 1512, 1520, 1528, -1, -1, -1, -1, -1, -1};
+ 1392, 1400, 1408, 1416, 1424, 1432, 1440, 1448, 1456, 1464, 1472,
+ 1480, 1488, 1496, 1504, -1, -1, -1, -1, 1512, 1520, -1,
+ -1, 1528, 1536, 1544, -1, -1, -1, -1, -1, -1};
static constexpr dart::compiler::target::word AbstractType_InstanceSize = 24;
static constexpr dart::compiler::target::word ApiError_InstanceSize = 16;
static constexpr dart::compiler::target::word Array_header_size = 24;
@@ -5614,16 +5624,16 @@
static constexpr dart::compiler::target::word
IsolateGroup_cached_class_table_table_offset = 32;
static constexpr dart::compiler::target::word Isolate_user_tag_offset = 32;
-static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 20;
+static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 16;
static constexpr dart::compiler::target::word
- LinkedHashBase_deleted_keys_offset = 28;
+ LinkedHashBase_deleted_keys_offset = 24;
static constexpr dart::compiler::target::word LinkedHashBase_hash_mask_offset =
- 16;
-static constexpr dart::compiler::target::word LinkedHashBase_index_offset = 12;
+ 12;
+static constexpr dart::compiler::target::word LinkedHashBase_index_offset = 28;
static constexpr dart::compiler::target::word
LinkedHashBase_type_arguments_offset = 8;
static constexpr dart::compiler::target::word LinkedHashBase_used_data_offset =
- 24;
+ 20;
static constexpr dart::compiler::target::word LocalHandle_ptr_offset = 0;
static constexpr dart::compiler::target::word
MarkingStackBlock_pointers_offset = 16;
@@ -5639,11 +5649,12 @@
24;
static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
- 256;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 136;
+ 368;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 248;
static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
- 312;
-static constexpr dart::compiler::target::word ObjectStore_type_type_offset = 96;
+ 424;
+static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
+ 208;
static constexpr dart::compiler::target::word OneByteString_data_offset = 16;
static constexpr dart::compiler::target::word PointerBase_data_field_offset = 8;
static constexpr dart::compiler::target::word Pointer_type_arguments_offset =
@@ -5665,9 +5676,9 @@
static constexpr dart::compiler::target::word
Thread_AllocateArray_entry_point_offset = 728;
static constexpr dart::compiler::target::word Thread_active_exception_offset =
- 1464;
+ 1480;
static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
- 1472;
+ 1488;
static constexpr dart::compiler::target::word
Thread_array_write_barrier_code_offset = 232;
static constexpr dart::compiler::target::word
@@ -5693,7 +5704,7 @@
static constexpr dart::compiler::target::word
Thread_allocate_object_slow_stub_offset = 384;
static constexpr dart::compiler::target::word Thread_api_top_scope_offset =
- 1544;
+ 1560;
static constexpr dart::compiler::target::word
Thread_auto_scope_native_wrapper_entry_point_offset = 656;
static constexpr dart::compiler::target::word Thread_bool_false_offset = 216;
@@ -5704,7 +5715,7 @@
Thread_call_to_runtime_entry_point_offset = 528;
static constexpr dart::compiler::target::word
Thread_call_to_runtime_stub_offset = 264;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1560;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1576;
static constexpr dart::compiler::target::word
Thread_dispatch_table_array_offset = 96;
static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
@@ -5722,7 +5733,7 @@
static constexpr dart::compiler::target::word
Thread_enter_safepoint_stub_offset = 488;
static constexpr dart::compiler::target::word Thread_execution_state_offset =
- 1504;
+ 1520;
static constexpr dart::compiler::target::word
Thread_exit_safepoint_stub_offset = 496;
static constexpr dart::compiler::target::word
@@ -5742,14 +5753,14 @@
static constexpr dart::compiler::target::word
Thread_float_zerow_address_offset = 720;
static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
- 1480;
+ 1496;
static constexpr dart::compiler::target::word
Thread_invoke_dart_code_stub_offset = 256;
static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
- 1536;
+ 1552;
static constexpr dart::compiler::target::word Thread_isolate_offset = 88;
static constexpr dart::compiler::target::word Thread_isolate_group_offset =
- 1568;
+ 1584;
static constexpr dart::compiler::target::word Thread_field_table_values_offset =
136;
static constexpr dart::compiler::target::word
@@ -5791,11 +5802,11 @@
static constexpr dart::compiler::target::word Thread_object_null_offset = 200;
static constexpr dart::compiler::target::word
Thread_predefined_symbols_address_offset = 664;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1488;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1504;
static constexpr dart::compiler::target::word
- Thread_saved_shadow_call_stack_offset = 1496;
+ Thread_saved_shadow_call_stack_offset = 1512;
static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
- 1512;
+ 1528;
static constexpr dart::compiler::target::word
Thread_slow_type_test_stub_offset = 472;
static constexpr dart::compiler::target::word
@@ -5830,33 +5841,33 @@
72;
static constexpr dart::compiler::target::word Thread_heap_base_offset = 80;
static constexpr dart::compiler::target::word Thread_callback_code_offset =
- 1520;
+ 1536;
static constexpr dart::compiler::target::word
- Thread_callback_stack_return_offset = 1528;
+ Thread_callback_stack_return_offset = 1544;
static constexpr dart::compiler::target::word TimelineStream_enabled_offset =
16;
static constexpr dart::compiler::target::word TwoByteString_data_offset = 16;
-static constexpr dart::compiler::target::word Type_arguments_offset = 24;
-static constexpr dart::compiler::target::word Type_hash_offset = 28;
-static constexpr dart::compiler::target::word Type_type_class_id_offset = 20;
-static constexpr dart::compiler::target::word Type_type_state_offset = 32;
-static constexpr dart::compiler::target::word Type_nullability_offset = 33;
-static constexpr dart::compiler::target::word FunctionType_hash_offset = 36;
+static constexpr dart::compiler::target::word Type_arguments_offset = 28;
+static constexpr dart::compiler::target::word Type_hash_offset = 32;
+static constexpr dart::compiler::target::word Type_type_class_id_offset = 24;
+static constexpr dart::compiler::target::word Type_type_state_offset = 36;
+static constexpr dart::compiler::target::word Type_nullability_offset = 37;
+static constexpr dart::compiler::target::word FunctionType_hash_offset = 40;
static constexpr dart::compiler::target::word
- FunctionType_packed_parameter_counts_offset = 40;
+ FunctionType_packed_parameter_counts_offset = 44;
static constexpr dart::compiler::target::word
- FunctionType_packed_type_parameter_counts_offset = 44;
+ FunctionType_packed_type_parameter_counts_offset = 48;
static constexpr dart::compiler::target::word
- FunctionType_parameter_types_offset = 28;
+ FunctionType_parameter_types_offset = 32;
static constexpr dart::compiler::target::word
- FunctionType_named_parameter_names_offset = 32;
+ FunctionType_named_parameter_names_offset = 36;
static constexpr dart::compiler::target::word
- FunctionType_type_parameters_offset = 20;
+ FunctionType_type_parameters_offset = 24;
static constexpr dart::compiler::target::word
- TypeParameter_parameterized_class_id_offset = 28;
-static constexpr dart::compiler::target::word TypeParameter_index_offset = 31;
+ TypeParameter_parameterized_class_id_offset = 32;
+static constexpr dart::compiler::target::word TypeParameter_index_offset = 35;
static constexpr dart::compiler::target::word TypeParameter_nullability_offset =
- 33;
+ 37;
static constexpr dart::compiler::target::word
TypeArguments_instantiations_offset = 8;
static constexpr dart::compiler::target::word TypeArguments_length_offset = 12;
@@ -5868,13 +5879,13 @@
static constexpr dart::compiler::target::word TypeParameters_bounds_offset = 16;
static constexpr dart::compiler::target::word TypeParameters_defaults_offset =
20;
-static constexpr dart::compiler::target::word TypeParameter_bound_offset = 24;
-static constexpr dart::compiler::target::word TypeParameter_flags_offset = 32;
-static constexpr dart::compiler::target::word TypeRef_type_offset = 20;
-static constexpr dart::compiler::target::word TypedDataBase_length_offset = 16;
-static constexpr dart::compiler::target::word TypedDataView_data_offset = 20;
+static constexpr dart::compiler::target::word TypeParameter_bound_offset = 28;
+static constexpr dart::compiler::target::word TypeParameter_flags_offset = 36;
+static constexpr dart::compiler::target::word TypeRef_type_offset = 24;
+static constexpr dart::compiler::target::word TypedDataBase_length_offset = 20;
+static constexpr dart::compiler::target::word TypedDataView_data_offset = 24;
static constexpr dart::compiler::target::word
- TypedDataView_offset_in_bytes_offset = 24;
+ TypedDataView_offset_in_bytes_offset = 28;
static constexpr dart::compiler::target::word TypedData_data_offset = 24;
static constexpr dart::compiler::target::word
UnhandledException_exception_offset = 8;
@@ -5893,8 +5904,8 @@
8, 24, 16, 32};
static constexpr dart::compiler::target::word
Thread_write_barrier_wrappers_thread_offset[] = {
- 1376, 1384, 1392, 1400, -1, -1, 1408, 1416,
- 1424, 1432, 1440, -1, 1448, 1456, -1, -1};
+ 1392, 1400, 1408, 1416, -1, -1, 1424, 1432,
+ 1440, 1448, 1456, -1, 1464, 1472, -1, -1};
static constexpr dart::compiler::target::word AbstractType_InstanceSize = 24;
static constexpr dart::compiler::target::word ApiError_InstanceSize = 16;
static constexpr dart::compiler::target::word Array_header_size = 16;
@@ -5921,7 +5932,7 @@
static constexpr dart::compiler::target::word Float32x4_InstanceSize = 24;
static constexpr dart::compiler::target::word Float64x2_InstanceSize = 24;
static constexpr dart::compiler::target::word Function_InstanceSize = 96;
-static constexpr dart::compiler::target::word FunctionType_InstanceSize = 48;
+static constexpr dart::compiler::target::word FunctionType_InstanceSize = 56;
static constexpr dart::compiler::target::word FutureOr_InstanceSize = 16;
static constexpr dart::compiler::target::word GrowableObjectArray_InstanceSize =
24;
@@ -5969,7 +5980,7 @@
static constexpr dart::compiler::target::word Type_InstanceSize = 40;
static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 40;
static constexpr dart::compiler::target::word TypeParameters_InstanceSize = 24;
-static constexpr dart::compiler::target::word TypeRef_InstanceSize = 24;
+static constexpr dart::compiler::target::word TypeRef_InstanceSize = 32;
static constexpr dart::compiler::target::word TypedData_HeaderSize = 24;
static constexpr dart::compiler::target::word TypedDataBase_InstanceSize = 24;
static constexpr dart::compiler::target::word TypedDataView_InstanceSize = 32;
@@ -6155,16 +6166,16 @@
static constexpr dart::compiler::target::word
IsolateGroup_cached_class_table_table_offset = 32;
static constexpr dart::compiler::target::word Isolate_user_tag_offset = 32;
-static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 20;
+static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 16;
static constexpr dart::compiler::target::word
- LinkedHashBase_deleted_keys_offset = 28;
+ LinkedHashBase_deleted_keys_offset = 24;
static constexpr dart::compiler::target::word LinkedHashBase_hash_mask_offset =
- 16;
-static constexpr dart::compiler::target::word LinkedHashBase_index_offset = 12;
+ 12;
+static constexpr dart::compiler::target::word LinkedHashBase_index_offset = 28;
static constexpr dart::compiler::target::word
LinkedHashBase_type_arguments_offset = 8;
static constexpr dart::compiler::target::word LinkedHashBase_used_data_offset =
- 24;
+ 20;
static constexpr dart::compiler::target::word LocalHandle_ptr_offset = 0;
static constexpr dart::compiler::target::word
MarkingStackBlock_pointers_offset = 16;
@@ -6180,11 +6191,12 @@
24;
static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
- 256;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 136;
+ 368;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 248;
static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
- 312;
-static constexpr dart::compiler::target::word ObjectStore_type_type_offset = 96;
+ 424;
+static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
+ 208;
static constexpr dart::compiler::target::word OneByteString_data_offset = 16;
static constexpr dart::compiler::target::word PointerBase_data_field_offset = 8;
static constexpr dart::compiler::target::word Pointer_type_arguments_offset =
@@ -6206,9 +6218,9 @@
static constexpr dart::compiler::target::word
Thread_AllocateArray_entry_point_offset = 728;
static constexpr dart::compiler::target::word Thread_active_exception_offset =
- 1528;
+ 1544;
static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
- 1536;
+ 1552;
static constexpr dart::compiler::target::word
Thread_array_write_barrier_code_offset = 232;
static constexpr dart::compiler::target::word
@@ -6234,7 +6246,7 @@
static constexpr dart::compiler::target::word
Thread_allocate_object_slow_stub_offset = 384;
static constexpr dart::compiler::target::word Thread_api_top_scope_offset =
- 1608;
+ 1624;
static constexpr dart::compiler::target::word
Thread_auto_scope_native_wrapper_entry_point_offset = 656;
static constexpr dart::compiler::target::word Thread_bool_false_offset = 216;
@@ -6245,7 +6257,7 @@
Thread_call_to_runtime_entry_point_offset = 528;
static constexpr dart::compiler::target::word
Thread_call_to_runtime_stub_offset = 264;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1624;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1640;
static constexpr dart::compiler::target::word
Thread_dispatch_table_array_offset = 96;
static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
@@ -6263,7 +6275,7 @@
static constexpr dart::compiler::target::word
Thread_enter_safepoint_stub_offset = 488;
static constexpr dart::compiler::target::word Thread_execution_state_offset =
- 1568;
+ 1584;
static constexpr dart::compiler::target::word
Thread_exit_safepoint_stub_offset = 496;
static constexpr dart::compiler::target::word
@@ -6283,14 +6295,14 @@
static constexpr dart::compiler::target::word
Thread_float_zerow_address_offset = 720;
static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
- 1544;
+ 1560;
static constexpr dart::compiler::target::word
Thread_invoke_dart_code_stub_offset = 256;
static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
- 1600;
+ 1616;
static constexpr dart::compiler::target::word Thread_isolate_offset = 88;
static constexpr dart::compiler::target::word Thread_isolate_group_offset =
- 1632;
+ 1648;
static constexpr dart::compiler::target::word Thread_field_table_values_offset =
136;
static constexpr dart::compiler::target::word
@@ -6332,11 +6344,11 @@
static constexpr dart::compiler::target::word Thread_object_null_offset = 200;
static constexpr dart::compiler::target::word
Thread_predefined_symbols_address_offset = 664;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1552;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1568;
static constexpr dart::compiler::target::word
- Thread_saved_shadow_call_stack_offset = 1560;
+ Thread_saved_shadow_call_stack_offset = 1576;
static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
- 1576;
+ 1592;
static constexpr dart::compiler::target::word
Thread_slow_type_test_stub_offset = 472;
static constexpr dart::compiler::target::word
@@ -6371,33 +6383,33 @@
72;
static constexpr dart::compiler::target::word Thread_heap_base_offset = 80;
static constexpr dart::compiler::target::word Thread_callback_code_offset =
- 1584;
+ 1600;
static constexpr dart::compiler::target::word
- Thread_callback_stack_return_offset = 1592;
+ Thread_callback_stack_return_offset = 1608;
static constexpr dart::compiler::target::word TimelineStream_enabled_offset =
16;
static constexpr dart::compiler::target::word TwoByteString_data_offset = 16;
-static constexpr dart::compiler::target::word Type_arguments_offset = 24;
-static constexpr dart::compiler::target::word Type_hash_offset = 28;
-static constexpr dart::compiler::target::word Type_type_class_id_offset = 20;
-static constexpr dart::compiler::target::word Type_type_state_offset = 32;
-static constexpr dart::compiler::target::word Type_nullability_offset = 33;
-static constexpr dart::compiler::target::word FunctionType_hash_offset = 36;
+static constexpr dart::compiler::target::word Type_arguments_offset = 28;
+static constexpr dart::compiler::target::word Type_hash_offset = 32;
+static constexpr dart::compiler::target::word Type_type_class_id_offset = 24;
+static constexpr dart::compiler::target::word Type_type_state_offset = 36;
+static constexpr dart::compiler::target::word Type_nullability_offset = 37;
+static constexpr dart::compiler::target::word FunctionType_hash_offset = 40;
static constexpr dart::compiler::target::word
- FunctionType_packed_parameter_counts_offset = 40;
+ FunctionType_packed_parameter_counts_offset = 44;
static constexpr dart::compiler::target::word
- FunctionType_packed_type_parameter_counts_offset = 44;
+ FunctionType_packed_type_parameter_counts_offset = 48;
static constexpr dart::compiler::target::word
- FunctionType_parameter_types_offset = 28;
+ FunctionType_parameter_types_offset = 32;
static constexpr dart::compiler::target::word
- FunctionType_named_parameter_names_offset = 32;
+ FunctionType_named_parameter_names_offset = 36;
static constexpr dart::compiler::target::word
- FunctionType_type_parameters_offset = 20;
+ FunctionType_type_parameters_offset = 24;
static constexpr dart::compiler::target::word
- TypeParameter_parameterized_class_id_offset = 28;
-static constexpr dart::compiler::target::word TypeParameter_index_offset = 31;
+ TypeParameter_parameterized_class_id_offset = 32;
+static constexpr dart::compiler::target::word TypeParameter_index_offset = 35;
static constexpr dart::compiler::target::word TypeParameter_nullability_offset =
- 33;
+ 37;
static constexpr dart::compiler::target::word
TypeArguments_instantiations_offset = 8;
static constexpr dart::compiler::target::word TypeArguments_length_offset = 12;
@@ -6409,13 +6421,13 @@
static constexpr dart::compiler::target::word TypeParameters_bounds_offset = 16;
static constexpr dart::compiler::target::word TypeParameters_defaults_offset =
20;
-static constexpr dart::compiler::target::word TypeParameter_bound_offset = 24;
-static constexpr dart::compiler::target::word TypeParameter_flags_offset = 32;
-static constexpr dart::compiler::target::word TypeRef_type_offset = 20;
-static constexpr dart::compiler::target::word TypedDataBase_length_offset = 16;
-static constexpr dart::compiler::target::word TypedDataView_data_offset = 20;
+static constexpr dart::compiler::target::word TypeParameter_bound_offset = 28;
+static constexpr dart::compiler::target::word TypeParameter_flags_offset = 36;
+static constexpr dart::compiler::target::word TypeRef_type_offset = 24;
+static constexpr dart::compiler::target::word TypedDataBase_length_offset = 20;
+static constexpr dart::compiler::target::word TypedDataView_data_offset = 24;
static constexpr dart::compiler::target::word
- TypedDataView_offset_in_bytes_offset = 24;
+ TypedDataView_offset_in_bytes_offset = 28;
static constexpr dart::compiler::target::word TypedData_data_offset = 24;
static constexpr dart::compiler::target::word
UnhandledException_exception_offset = 8;
@@ -6434,9 +6446,9 @@
8, 24, 16, 32};
static constexpr dart::compiler::target::word
Thread_write_barrier_wrappers_thread_offset[] = {
- 1376, 1384, 1392, 1400, 1408, 1416, 1424, 1432, 1440, 1448, 1456,
- 1464, 1472, 1480, 1488, -1, -1, -1, -1, 1496, 1504, -1,
- -1, 1512, 1520, 1528, -1, -1, -1, -1, -1, -1};
+ 1392, 1400, 1408, 1416, 1424, 1432, 1440, 1448, 1456, 1464, 1472,
+ 1480, 1488, 1496, 1504, -1, -1, -1, -1, 1512, 1520, -1,
+ -1, 1528, 1536, 1544, -1, -1, -1, -1, -1, -1};
static constexpr dart::compiler::target::word AbstractType_InstanceSize = 24;
static constexpr dart::compiler::target::word ApiError_InstanceSize = 16;
static constexpr dart::compiler::target::word Array_header_size = 16;
@@ -6463,7 +6475,7 @@
static constexpr dart::compiler::target::word Float32x4_InstanceSize = 24;
static constexpr dart::compiler::target::word Float64x2_InstanceSize = 24;
static constexpr dart::compiler::target::word Function_InstanceSize = 96;
-static constexpr dart::compiler::target::word FunctionType_InstanceSize = 48;
+static constexpr dart::compiler::target::word FunctionType_InstanceSize = 56;
static constexpr dart::compiler::target::word FutureOr_InstanceSize = 16;
static constexpr dart::compiler::target::word GrowableObjectArray_InstanceSize =
24;
@@ -6511,7 +6523,7 @@
static constexpr dart::compiler::target::word Type_InstanceSize = 40;
static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 40;
static constexpr dart::compiler::target::word TypeParameters_InstanceSize = 24;
-static constexpr dart::compiler::target::word TypeRef_InstanceSize = 24;
+static constexpr dart::compiler::target::word TypeRef_InstanceSize = 32;
static constexpr dart::compiler::target::word TypedData_HeaderSize = 24;
static constexpr dart::compiler::target::word TypedDataBase_InstanceSize = 24;
static constexpr dart::compiler::target::word TypedDataView_InstanceSize = 32;
@@ -6723,17 +6735,17 @@
36;
static constexpr dart::compiler::target::word AOT_Isolate_user_tag_offset = 16;
static constexpr dart::compiler::target::word AOT_LinkedHashBase_data_offset =
- 16;
+ 12;
static constexpr dart::compiler::target::word
- AOT_LinkedHashBase_deleted_keys_offset = 24;
+ AOT_LinkedHashBase_deleted_keys_offset = 20;
static constexpr dart::compiler::target::word
- AOT_LinkedHashBase_hash_mask_offset = 12;
+ AOT_LinkedHashBase_hash_mask_offset = 8;
static constexpr dart::compiler::target::word AOT_LinkedHashBase_index_offset =
- 8;
+ 24;
static constexpr dart::compiler::target::word
AOT_LinkedHashBase_type_arguments_offset = 4;
static constexpr dart::compiler::target::word
- AOT_LinkedHashBase_used_data_offset = 20;
+ AOT_LinkedHashBase_used_data_offset = 16;
static constexpr dart::compiler::target::word AOT_LocalHandle_ptr_offset = 0;
static constexpr dart::compiler::target::word
AOT_MarkingStackBlock_pointers_offset = 8;
@@ -6753,13 +6765,13 @@
static constexpr dart::compiler::target::word
AOT_NativeArguments_thread_offset = 0;
static constexpr dart::compiler::target::word
- AOT_ObjectStore_double_type_offset = 128;
+ AOT_ObjectStore_double_type_offset = 184;
static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
- 68;
+ 124;
static constexpr dart::compiler::target::word
- AOT_ObjectStore_string_type_offset = 156;
+ AOT_ObjectStore_string_type_offset = 212;
static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
- 48;
+ 104;
static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
12;
static constexpr dart::compiler::target::word
@@ -6785,9 +6797,9 @@
static constexpr dart::compiler::target::word
AOT_Thread_AllocateArray_entry_point_offset = 368;
static constexpr dart::compiler::target::word
- AOT_Thread_active_exception_offset = 724;
+ AOT_Thread_active_exception_offset = 732;
static constexpr dart::compiler::target::word
- AOT_Thread_active_stacktrace_offset = 728;
+ AOT_Thread_active_stacktrace_offset = 736;
static constexpr dart::compiler::target::word
AOT_Thread_array_write_barrier_code_offset = 120;
static constexpr dart::compiler::target::word
@@ -6813,7 +6825,7 @@
static constexpr dart::compiler::target::word
AOT_Thread_allocate_object_slow_stub_offset = 196;
static constexpr dart::compiler::target::word AOT_Thread_api_top_scope_offset =
- 764;
+ 772;
static constexpr dart::compiler::target::word
AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 332;
static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
@@ -6826,7 +6838,7 @@
static constexpr dart::compiler::target::word
AOT_Thread_call_to_runtime_stub_offset = 136;
static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
- 772;
+ 780;
static constexpr dart::compiler::target::word
AOT_Thread_dispatch_table_array_offset = 48;
static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
@@ -6845,7 +6857,7 @@
static constexpr dart::compiler::target::word
AOT_Thread_enter_safepoint_stub_offset = 248;
static constexpr dart::compiler::target::word
- AOT_Thread_execution_state_offset = 744;
+ AOT_Thread_execution_state_offset = 752;
static constexpr dart::compiler::target::word
AOT_Thread_exit_safepoint_stub_offset = 252;
static constexpr dart::compiler::target::word
@@ -6865,14 +6877,14 @@
static constexpr dart::compiler::target::word
AOT_Thread_float_zerow_address_offset = 364;
static constexpr dart::compiler::target::word
- AOT_Thread_global_object_pool_offset = 732;
+ AOT_Thread_global_object_pool_offset = 740;
static constexpr dart::compiler::target::word
AOT_Thread_invoke_dart_code_stub_offset = 132;
static constexpr dart::compiler::target::word
- AOT_Thread_exit_through_ffi_offset = 760;
+ AOT_Thread_exit_through_ffi_offset = 768;
static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 44;
static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset =
- 776;
+ 784;
static constexpr dart::compiler::target::word
AOT_Thread_field_table_values_offset = 68;
static constexpr dart::compiler::target::word
@@ -6916,11 +6928,11 @@
104;
static constexpr dart::compiler::target::word
AOT_Thread_predefined_symbols_address_offset = 336;
-static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset = 736;
+static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset = 744;
static constexpr dart::compiler::target::word
- AOT_Thread_saved_shadow_call_stack_offset = 740;
+ AOT_Thread_saved_shadow_call_stack_offset = 748;
static constexpr dart::compiler::target::word
- AOT_Thread_safepoint_state_offset = 748;
+ AOT_Thread_safepoint_state_offset = 756;
static constexpr dart::compiler::target::word
AOT_Thread_slow_type_test_stub_offset = 240;
static constexpr dart::compiler::target::word
@@ -6957,9 +6969,9 @@
AOT_Thread_write_barrier_mask_offset = 36;
static constexpr dart::compiler::target::word AOT_Thread_heap_base_offset = 40;
static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
- 752;
+ 760;
static constexpr dart::compiler::target::word
- AOT_Thread_callback_stack_return_offset = 756;
+ AOT_Thread_callback_stack_return_offset = 764;
static constexpr dart::compiler::target::word
AOT_TimelineStream_enabled_offset = 8;
static constexpr dart::compiler::target::word AOT_TwoByteString_data_offset =
@@ -7032,7 +7044,7 @@
4, 12, 8, 16};
static constexpr dart::compiler::target::word
AOT_Thread_write_barrier_wrappers_thread_offset[] = {
- 692, 696, 700, 704, 708, -1, 712, -1, 716, 720, -1, -1, -1, -1, -1, -1};
+ 700, 704, 708, 712, 716, -1, 720, -1, 724, 728, -1, -1, -1, -1, -1, -1};
static constexpr dart::compiler::target::word AOT_AbstractType_InstanceSize =
12;
static constexpr dart::compiler::target::word AOT_ApiError_InstanceSize = 8;
@@ -7330,17 +7342,17 @@
72;
static constexpr dart::compiler::target::word AOT_Isolate_user_tag_offset = 32;
static constexpr dart::compiler::target::word AOT_LinkedHashBase_data_offset =
- 32;
+ 24;
static constexpr dart::compiler::target::word
- AOT_LinkedHashBase_deleted_keys_offset = 48;
+ AOT_LinkedHashBase_deleted_keys_offset = 40;
static constexpr dart::compiler::target::word
- AOT_LinkedHashBase_hash_mask_offset = 24;
+ AOT_LinkedHashBase_hash_mask_offset = 16;
static constexpr dart::compiler::target::word AOT_LinkedHashBase_index_offset =
- 16;
+ 48;
static constexpr dart::compiler::target::word
AOT_LinkedHashBase_type_arguments_offset = 8;
static constexpr dart::compiler::target::word
- AOT_LinkedHashBase_used_data_offset = 40;
+ AOT_LinkedHashBase_used_data_offset = 32;
static constexpr dart::compiler::target::word AOT_LocalHandle_ptr_offset = 0;
static constexpr dart::compiler::target::word
AOT_MarkingStackBlock_pointers_offset = 16;
@@ -7360,13 +7372,13 @@
static constexpr dart::compiler::target::word
AOT_NativeArguments_thread_offset = 0;
static constexpr dart::compiler::target::word
- AOT_ObjectStore_double_type_offset = 256;
+ AOT_ObjectStore_double_type_offset = 368;
static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
- 136;
+ 248;
static constexpr dart::compiler::target::word
- AOT_ObjectStore_string_type_offset = 312;
+ AOT_ObjectStore_string_type_offset = 424;
static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
- 96;
+ 208;
static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
16;
static constexpr dart::compiler::target::word
@@ -7392,9 +7404,9 @@
static constexpr dart::compiler::target::word
AOT_Thread_AllocateArray_entry_point_offset = 728;
static constexpr dart::compiler::target::word
- AOT_Thread_active_exception_offset = 1464;
+ AOT_Thread_active_exception_offset = 1480;
static constexpr dart::compiler::target::word
- AOT_Thread_active_stacktrace_offset = 1472;
+ AOT_Thread_active_stacktrace_offset = 1488;
static constexpr dart::compiler::target::word
AOT_Thread_array_write_barrier_code_offset = 232;
static constexpr dart::compiler::target::word
@@ -7420,7 +7432,7 @@
static constexpr dart::compiler::target::word
AOT_Thread_allocate_object_slow_stub_offset = 384;
static constexpr dart::compiler::target::word AOT_Thread_api_top_scope_offset =
- 1544;
+ 1560;
static constexpr dart::compiler::target::word
AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 656;
static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
@@ -7433,7 +7445,7 @@
static constexpr dart::compiler::target::word
AOT_Thread_call_to_runtime_stub_offset = 264;
static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
- 1560;
+ 1576;
static constexpr dart::compiler::target::word
AOT_Thread_dispatch_table_array_offset = 96;
static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
@@ -7452,7 +7464,7 @@
static constexpr dart::compiler::target::word
AOT_Thread_enter_safepoint_stub_offset = 488;
static constexpr dart::compiler::target::word
- AOT_Thread_execution_state_offset = 1504;
+ AOT_Thread_execution_state_offset = 1520;
static constexpr dart::compiler::target::word
AOT_Thread_exit_safepoint_stub_offset = 496;
static constexpr dart::compiler::target::word
@@ -7472,14 +7484,14 @@
static constexpr dart::compiler::target::word
AOT_Thread_float_zerow_address_offset = 720;
static constexpr dart::compiler::target::word
- AOT_Thread_global_object_pool_offset = 1480;
+ AOT_Thread_global_object_pool_offset = 1496;
static constexpr dart::compiler::target::word
AOT_Thread_invoke_dart_code_stub_offset = 256;
static constexpr dart::compiler::target::word
- AOT_Thread_exit_through_ffi_offset = 1536;
+ AOT_Thread_exit_through_ffi_offset = 1552;
static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 88;
static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset =
- 1568;
+ 1584;
static constexpr dart::compiler::target::word
AOT_Thread_field_table_values_offset = 136;
static constexpr dart::compiler::target::word
@@ -7524,11 +7536,11 @@
static constexpr dart::compiler::target::word
AOT_Thread_predefined_symbols_address_offset = 664;
static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset =
- 1488;
+ 1504;
static constexpr dart::compiler::target::word
- AOT_Thread_saved_shadow_call_stack_offset = 1496;
+ AOT_Thread_saved_shadow_call_stack_offset = 1512;
static constexpr dart::compiler::target::word
- AOT_Thread_safepoint_state_offset = 1512;
+ AOT_Thread_safepoint_state_offset = 1528;
static constexpr dart::compiler::target::word
AOT_Thread_slow_type_test_stub_offset = 472;
static constexpr dart::compiler::target::word
@@ -7565,9 +7577,9 @@
AOT_Thread_write_barrier_mask_offset = 72;
static constexpr dart::compiler::target::word AOT_Thread_heap_base_offset = 80;
static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
- 1520;
+ 1536;
static constexpr dart::compiler::target::word
- AOT_Thread_callback_stack_return_offset = 1528;
+ AOT_Thread_callback_stack_return_offset = 1544;
static constexpr dart::compiler::target::word
AOT_TimelineStream_enabled_offset = 16;
static constexpr dart::compiler::target::word AOT_TwoByteString_data_offset =
@@ -7641,8 +7653,8 @@
8, 24, 16, 32};
static constexpr dart::compiler::target::word
AOT_Thread_write_barrier_wrappers_thread_offset[] = {
- 1376, 1384, 1392, 1400, -1, -1, 1408, 1416,
- 1424, 1432, 1440, -1, 1448, 1456, -1, -1};
+ 1392, 1400, 1408, 1416, -1, -1, 1424, 1432,
+ 1440, 1448, 1456, -1, 1464, 1472, -1, -1};
static constexpr dart::compiler::target::word AOT_AbstractType_InstanceSize =
24;
static constexpr dart::compiler::target::word AOT_ApiError_InstanceSize = 16;
@@ -7943,17 +7955,17 @@
72;
static constexpr dart::compiler::target::word AOT_Isolate_user_tag_offset = 32;
static constexpr dart::compiler::target::word AOT_LinkedHashBase_data_offset =
- 32;
+ 24;
static constexpr dart::compiler::target::word
- AOT_LinkedHashBase_deleted_keys_offset = 48;
+ AOT_LinkedHashBase_deleted_keys_offset = 40;
static constexpr dart::compiler::target::word
- AOT_LinkedHashBase_hash_mask_offset = 24;
+ AOT_LinkedHashBase_hash_mask_offset = 16;
static constexpr dart::compiler::target::word AOT_LinkedHashBase_index_offset =
- 16;
+ 48;
static constexpr dart::compiler::target::word
AOT_LinkedHashBase_type_arguments_offset = 8;
static constexpr dart::compiler::target::word
- AOT_LinkedHashBase_used_data_offset = 40;
+ AOT_LinkedHashBase_used_data_offset = 32;
static constexpr dart::compiler::target::word AOT_LocalHandle_ptr_offset = 0;
static constexpr dart::compiler::target::word
AOT_MarkingStackBlock_pointers_offset = 16;
@@ -7973,13 +7985,13 @@
static constexpr dart::compiler::target::word
AOT_NativeArguments_thread_offset = 0;
static constexpr dart::compiler::target::word
- AOT_ObjectStore_double_type_offset = 256;
+ AOT_ObjectStore_double_type_offset = 368;
static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
- 136;
+ 248;
static constexpr dart::compiler::target::word
- AOT_ObjectStore_string_type_offset = 312;
+ AOT_ObjectStore_string_type_offset = 424;
static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
- 96;
+ 208;
static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
16;
static constexpr dart::compiler::target::word
@@ -8005,9 +8017,9 @@
static constexpr dart::compiler::target::word
AOT_Thread_AllocateArray_entry_point_offset = 728;
static constexpr dart::compiler::target::word
- AOT_Thread_active_exception_offset = 1528;
+ AOT_Thread_active_exception_offset = 1544;
static constexpr dart::compiler::target::word
- AOT_Thread_active_stacktrace_offset = 1536;
+ AOT_Thread_active_stacktrace_offset = 1552;
static constexpr dart::compiler::target::word
AOT_Thread_array_write_barrier_code_offset = 232;
static constexpr dart::compiler::target::word
@@ -8033,7 +8045,7 @@
static constexpr dart::compiler::target::word
AOT_Thread_allocate_object_slow_stub_offset = 384;
static constexpr dart::compiler::target::word AOT_Thread_api_top_scope_offset =
- 1608;
+ 1624;
static constexpr dart::compiler::target::word
AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 656;
static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
@@ -8046,7 +8058,7 @@
static constexpr dart::compiler::target::word
AOT_Thread_call_to_runtime_stub_offset = 264;
static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
- 1624;
+ 1640;
static constexpr dart::compiler::target::word
AOT_Thread_dispatch_table_array_offset = 96;
static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
@@ -8065,7 +8077,7 @@
static constexpr dart::compiler::target::word
AOT_Thread_enter_safepoint_stub_offset = 488;
static constexpr dart::compiler::target::word
- AOT_Thread_execution_state_offset = 1568;
+ AOT_Thread_execution_state_offset = 1584;
static constexpr dart::compiler::target::word
AOT_Thread_exit_safepoint_stub_offset = 496;
static constexpr dart::compiler::target::word
@@ -8085,14 +8097,14 @@
static constexpr dart::compiler::target::word
AOT_Thread_float_zerow_address_offset = 720;
static constexpr dart::compiler::target::word
- AOT_Thread_global_object_pool_offset = 1544;
+ AOT_Thread_global_object_pool_offset = 1560;
static constexpr dart::compiler::target::word
AOT_Thread_invoke_dart_code_stub_offset = 256;
static constexpr dart::compiler::target::word
- AOT_Thread_exit_through_ffi_offset = 1600;
+ AOT_Thread_exit_through_ffi_offset = 1616;
static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 88;
static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset =
- 1632;
+ 1648;
static constexpr dart::compiler::target::word
AOT_Thread_field_table_values_offset = 136;
static constexpr dart::compiler::target::word
@@ -8137,11 +8149,11 @@
static constexpr dart::compiler::target::word
AOT_Thread_predefined_symbols_address_offset = 664;
static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset =
- 1552;
+ 1568;
static constexpr dart::compiler::target::word
- AOT_Thread_saved_shadow_call_stack_offset = 1560;
+ AOT_Thread_saved_shadow_call_stack_offset = 1576;
static constexpr dart::compiler::target::word
- AOT_Thread_safepoint_state_offset = 1576;
+ AOT_Thread_safepoint_state_offset = 1592;
static constexpr dart::compiler::target::word
AOT_Thread_slow_type_test_stub_offset = 472;
static constexpr dart::compiler::target::word
@@ -8178,9 +8190,9 @@
AOT_Thread_write_barrier_mask_offset = 72;
static constexpr dart::compiler::target::word AOT_Thread_heap_base_offset = 80;
static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
- 1584;
+ 1600;
static constexpr dart::compiler::target::word
- AOT_Thread_callback_stack_return_offset = 1592;
+ AOT_Thread_callback_stack_return_offset = 1608;
static constexpr dart::compiler::target::word
AOT_TimelineStream_enabled_offset = 16;
static constexpr dart::compiler::target::word AOT_TwoByteString_data_offset =
@@ -8254,9 +8266,9 @@
8, 24, 16, 32};
static constexpr dart::compiler::target::word
AOT_Thread_write_barrier_wrappers_thread_offset[] = {
- 1376, 1384, 1392, 1400, 1408, 1416, 1424, 1432, 1440, 1448, 1456,
- 1464, 1472, 1480, 1488, -1, -1, -1, -1, 1496, 1504, -1,
- -1, 1512, 1520, 1528, -1, -1, -1, -1, -1, -1};
+ 1392, 1400, 1408, 1416, 1424, 1432, 1440, 1448, 1456, 1464, 1472,
+ 1480, 1488, 1496, 1504, -1, -1, -1, -1, 1512, 1520, -1,
+ -1, 1528, 1536, 1544, -1, -1, -1, -1, -1, -1};
static constexpr dart::compiler::target::word AOT_AbstractType_InstanceSize =
24;
static constexpr dart::compiler::target::word AOT_ApiError_InstanceSize = 16;
@@ -8553,17 +8565,17 @@
72;
static constexpr dart::compiler::target::word AOT_Isolate_user_tag_offset = 32;
static constexpr dart::compiler::target::word AOT_LinkedHashBase_data_offset =
- 20;
+ 16;
static constexpr dart::compiler::target::word
- AOT_LinkedHashBase_deleted_keys_offset = 28;
+ AOT_LinkedHashBase_deleted_keys_offset = 24;
static constexpr dart::compiler::target::word
- AOT_LinkedHashBase_hash_mask_offset = 16;
+ AOT_LinkedHashBase_hash_mask_offset = 12;
static constexpr dart::compiler::target::word AOT_LinkedHashBase_index_offset =
- 12;
+ 28;
static constexpr dart::compiler::target::word
AOT_LinkedHashBase_type_arguments_offset = 8;
static constexpr dart::compiler::target::word
- AOT_LinkedHashBase_used_data_offset = 24;
+ AOT_LinkedHashBase_used_data_offset = 20;
static constexpr dart::compiler::target::word AOT_LocalHandle_ptr_offset = 0;
static constexpr dart::compiler::target::word
AOT_MarkingStackBlock_pointers_offset = 16;
@@ -8583,13 +8595,13 @@
static constexpr dart::compiler::target::word
AOT_NativeArguments_thread_offset = 0;
static constexpr dart::compiler::target::word
- AOT_ObjectStore_double_type_offset = 256;
+ AOT_ObjectStore_double_type_offset = 368;
static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
- 136;
+ 248;
static constexpr dart::compiler::target::word
- AOT_ObjectStore_string_type_offset = 312;
+ AOT_ObjectStore_string_type_offset = 424;
static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
- 96;
+ 208;
static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
16;
static constexpr dart::compiler::target::word
@@ -8615,9 +8627,9 @@
static constexpr dart::compiler::target::word
AOT_Thread_AllocateArray_entry_point_offset = 728;
static constexpr dart::compiler::target::word
- AOT_Thread_active_exception_offset = 1464;
+ AOT_Thread_active_exception_offset = 1480;
static constexpr dart::compiler::target::word
- AOT_Thread_active_stacktrace_offset = 1472;
+ AOT_Thread_active_stacktrace_offset = 1488;
static constexpr dart::compiler::target::word
AOT_Thread_array_write_barrier_code_offset = 232;
static constexpr dart::compiler::target::word
@@ -8643,7 +8655,7 @@
static constexpr dart::compiler::target::word
AOT_Thread_allocate_object_slow_stub_offset = 384;
static constexpr dart::compiler::target::word AOT_Thread_api_top_scope_offset =
- 1544;
+ 1560;
static constexpr dart::compiler::target::word
AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 656;
static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
@@ -8656,7 +8668,7 @@
static constexpr dart::compiler::target::word
AOT_Thread_call_to_runtime_stub_offset = 264;
static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
- 1560;
+ 1576;
static constexpr dart::compiler::target::word
AOT_Thread_dispatch_table_array_offset = 96;
static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
@@ -8675,7 +8687,7 @@
static constexpr dart::compiler::target::word
AOT_Thread_enter_safepoint_stub_offset = 488;
static constexpr dart::compiler::target::word
- AOT_Thread_execution_state_offset = 1504;
+ AOT_Thread_execution_state_offset = 1520;
static constexpr dart::compiler::target::word
AOT_Thread_exit_safepoint_stub_offset = 496;
static constexpr dart::compiler::target::word
@@ -8695,14 +8707,14 @@
static constexpr dart::compiler::target::word
AOT_Thread_float_zerow_address_offset = 720;
static constexpr dart::compiler::target::word
- AOT_Thread_global_object_pool_offset = 1480;
+ AOT_Thread_global_object_pool_offset = 1496;
static constexpr dart::compiler::target::word
AOT_Thread_invoke_dart_code_stub_offset = 256;
static constexpr dart::compiler::target::word
- AOT_Thread_exit_through_ffi_offset = 1536;
+ AOT_Thread_exit_through_ffi_offset = 1552;
static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 88;
static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset =
- 1568;
+ 1584;
static constexpr dart::compiler::target::word
AOT_Thread_field_table_values_offset = 136;
static constexpr dart::compiler::target::word
@@ -8747,11 +8759,11 @@
static constexpr dart::compiler::target::word
AOT_Thread_predefined_symbols_address_offset = 664;
static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset =
- 1488;
+ 1504;
static constexpr dart::compiler::target::word
- AOT_Thread_saved_shadow_call_stack_offset = 1496;
+ AOT_Thread_saved_shadow_call_stack_offset = 1512;
static constexpr dart::compiler::target::word
- AOT_Thread_safepoint_state_offset = 1512;
+ AOT_Thread_safepoint_state_offset = 1528;
static constexpr dart::compiler::target::word
AOT_Thread_slow_type_test_stub_offset = 472;
static constexpr dart::compiler::target::word
@@ -8788,36 +8800,36 @@
AOT_Thread_write_barrier_mask_offset = 72;
static constexpr dart::compiler::target::word AOT_Thread_heap_base_offset = 80;
static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
- 1520;
+ 1536;
static constexpr dart::compiler::target::word
- AOT_Thread_callback_stack_return_offset = 1528;
+ AOT_Thread_callback_stack_return_offset = 1544;
static constexpr dart::compiler::target::word
AOT_TimelineStream_enabled_offset = 16;
static constexpr dart::compiler::target::word AOT_TwoByteString_data_offset =
16;
-static constexpr dart::compiler::target::word AOT_Type_arguments_offset = 24;
-static constexpr dart::compiler::target::word AOT_Type_hash_offset = 28;
+static constexpr dart::compiler::target::word AOT_Type_arguments_offset = 28;
+static constexpr dart::compiler::target::word AOT_Type_hash_offset = 32;
static constexpr dart::compiler::target::word AOT_Type_type_class_id_offset =
- 20;
-static constexpr dart::compiler::target::word AOT_Type_type_state_offset = 32;
-static constexpr dart::compiler::target::word AOT_Type_nullability_offset = 33;
-static constexpr dart::compiler::target::word AOT_FunctionType_hash_offset = 36;
+ 24;
+static constexpr dart::compiler::target::word AOT_Type_type_state_offset = 36;
+static constexpr dart::compiler::target::word AOT_Type_nullability_offset = 37;
+static constexpr dart::compiler::target::word AOT_FunctionType_hash_offset = 40;
static constexpr dart::compiler::target::word
- AOT_FunctionType_packed_parameter_counts_offset = 40;
+ AOT_FunctionType_packed_parameter_counts_offset = 44;
static constexpr dart::compiler::target::word
- AOT_FunctionType_packed_type_parameter_counts_offset = 44;
+ AOT_FunctionType_packed_type_parameter_counts_offset = 48;
static constexpr dart::compiler::target::word
- AOT_FunctionType_parameter_types_offset = 28;
+ AOT_FunctionType_parameter_types_offset = 32;
static constexpr dart::compiler::target::word
- AOT_FunctionType_named_parameter_names_offset = 32;
+ AOT_FunctionType_named_parameter_names_offset = 36;
static constexpr dart::compiler::target::word
- AOT_FunctionType_type_parameters_offset = 20;
+ AOT_FunctionType_type_parameters_offset = 24;
static constexpr dart::compiler::target::word
- AOT_TypeParameter_parameterized_class_id_offset = 28;
+ AOT_TypeParameter_parameterized_class_id_offset = 32;
static constexpr dart::compiler::target::word AOT_TypeParameter_index_offset =
- 31;
+ 35;
static constexpr dart::compiler::target::word
- AOT_TypeParameter_nullability_offset = 33;
+ AOT_TypeParameter_nullability_offset = 37;
static constexpr dart::compiler::target::word
AOT_TypeArguments_instantiations_offset = 8;
static constexpr dart::compiler::target::word AOT_TypeArguments_length_offset =
@@ -8835,16 +8847,16 @@
static constexpr dart::compiler::target::word
AOT_TypeParameters_defaults_offset = 20;
static constexpr dart::compiler::target::word AOT_TypeParameter_bound_offset =
- 24;
+ 28;
static constexpr dart::compiler::target::word AOT_TypeParameter_flags_offset =
- 32;
-static constexpr dart::compiler::target::word AOT_TypeRef_type_offset = 20;
+ 36;
+static constexpr dart::compiler::target::word AOT_TypeRef_type_offset = 24;
static constexpr dart::compiler::target::word AOT_TypedDataBase_length_offset =
- 16;
-static constexpr dart::compiler::target::word AOT_TypedDataView_data_offset =
20;
+static constexpr dart::compiler::target::word AOT_TypedDataView_data_offset =
+ 24;
static constexpr dart::compiler::target::word
- AOT_TypedDataView_offset_in_bytes_offset = 24;
+ AOT_TypedDataView_offset_in_bytes_offset = 28;
static constexpr dart::compiler::target::word AOT_TypedData_data_offset = 24;
static constexpr dart::compiler::target::word
AOT_UnhandledException_exception_offset = 8;
@@ -8864,8 +8876,8 @@
8, 24, 16, 32};
static constexpr dart::compiler::target::word
AOT_Thread_write_barrier_wrappers_thread_offset[] = {
- 1376, 1384, 1392, 1400, -1, -1, 1408, 1416,
- 1424, 1432, 1440, -1, 1448, 1456, -1, -1};
+ 1392, 1400, 1408, 1416, -1, -1, 1424, 1432,
+ 1440, 1448, 1456, -1, 1464, 1472, -1, -1};
static constexpr dart::compiler::target::word AOT_AbstractType_InstanceSize =
24;
static constexpr dart::compiler::target::word AOT_ApiError_InstanceSize = 16;
@@ -8895,7 +8907,7 @@
static constexpr dart::compiler::target::word AOT_Float64x2_InstanceSize = 24;
static constexpr dart::compiler::target::word AOT_Function_InstanceSize = 56;
static constexpr dart::compiler::target::word AOT_FunctionType_InstanceSize =
- 48;
+ 56;
static constexpr dart::compiler::target::word AOT_FutureOr_InstanceSize = 16;
static constexpr dart::compiler::target::word
AOT_GrowableObjectArray_InstanceSize = 24;
@@ -8950,7 +8962,7 @@
40;
static constexpr dart::compiler::target::word AOT_TypeParameters_InstanceSize =
24;
-static constexpr dart::compiler::target::word AOT_TypeRef_InstanceSize = 24;
+static constexpr dart::compiler::target::word AOT_TypeRef_InstanceSize = 32;
static constexpr dart::compiler::target::word AOT_TypedData_HeaderSize = 24;
static constexpr dart::compiler::target::word AOT_TypedDataBase_InstanceSize =
24;
@@ -9162,17 +9174,17 @@
72;
static constexpr dart::compiler::target::word AOT_Isolate_user_tag_offset = 32;
static constexpr dart::compiler::target::word AOT_LinkedHashBase_data_offset =
- 20;
+ 16;
static constexpr dart::compiler::target::word
- AOT_LinkedHashBase_deleted_keys_offset = 28;
+ AOT_LinkedHashBase_deleted_keys_offset = 24;
static constexpr dart::compiler::target::word
- AOT_LinkedHashBase_hash_mask_offset = 16;
+ AOT_LinkedHashBase_hash_mask_offset = 12;
static constexpr dart::compiler::target::word AOT_LinkedHashBase_index_offset =
- 12;
+ 28;
static constexpr dart::compiler::target::word
AOT_LinkedHashBase_type_arguments_offset = 8;
static constexpr dart::compiler::target::word
- AOT_LinkedHashBase_used_data_offset = 24;
+ AOT_LinkedHashBase_used_data_offset = 20;
static constexpr dart::compiler::target::word AOT_LocalHandle_ptr_offset = 0;
static constexpr dart::compiler::target::word
AOT_MarkingStackBlock_pointers_offset = 16;
@@ -9192,13 +9204,13 @@
static constexpr dart::compiler::target::word
AOT_NativeArguments_thread_offset = 0;
static constexpr dart::compiler::target::word
- AOT_ObjectStore_double_type_offset = 256;
+ AOT_ObjectStore_double_type_offset = 368;
static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
- 136;
+ 248;
static constexpr dart::compiler::target::word
- AOT_ObjectStore_string_type_offset = 312;
+ AOT_ObjectStore_string_type_offset = 424;
static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
- 96;
+ 208;
static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
16;
static constexpr dart::compiler::target::word
@@ -9224,9 +9236,9 @@
static constexpr dart::compiler::target::word
AOT_Thread_AllocateArray_entry_point_offset = 728;
static constexpr dart::compiler::target::word
- AOT_Thread_active_exception_offset = 1528;
+ AOT_Thread_active_exception_offset = 1544;
static constexpr dart::compiler::target::word
- AOT_Thread_active_stacktrace_offset = 1536;
+ AOT_Thread_active_stacktrace_offset = 1552;
static constexpr dart::compiler::target::word
AOT_Thread_array_write_barrier_code_offset = 232;
static constexpr dart::compiler::target::word
@@ -9252,7 +9264,7 @@
static constexpr dart::compiler::target::word
AOT_Thread_allocate_object_slow_stub_offset = 384;
static constexpr dart::compiler::target::word AOT_Thread_api_top_scope_offset =
- 1608;
+ 1624;
static constexpr dart::compiler::target::word
AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 656;
static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
@@ -9265,7 +9277,7 @@
static constexpr dart::compiler::target::word
AOT_Thread_call_to_runtime_stub_offset = 264;
static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
- 1624;
+ 1640;
static constexpr dart::compiler::target::word
AOT_Thread_dispatch_table_array_offset = 96;
static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
@@ -9284,7 +9296,7 @@
static constexpr dart::compiler::target::word
AOT_Thread_enter_safepoint_stub_offset = 488;
static constexpr dart::compiler::target::word
- AOT_Thread_execution_state_offset = 1568;
+ AOT_Thread_execution_state_offset = 1584;
static constexpr dart::compiler::target::word
AOT_Thread_exit_safepoint_stub_offset = 496;
static constexpr dart::compiler::target::word
@@ -9304,14 +9316,14 @@
static constexpr dart::compiler::target::word
AOT_Thread_float_zerow_address_offset = 720;
static constexpr dart::compiler::target::word
- AOT_Thread_global_object_pool_offset = 1544;
+ AOT_Thread_global_object_pool_offset = 1560;
static constexpr dart::compiler::target::word
AOT_Thread_invoke_dart_code_stub_offset = 256;
static constexpr dart::compiler::target::word
- AOT_Thread_exit_through_ffi_offset = 1600;
+ AOT_Thread_exit_through_ffi_offset = 1616;
static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 88;
static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset =
- 1632;
+ 1648;
static constexpr dart::compiler::target::word
AOT_Thread_field_table_values_offset = 136;
static constexpr dart::compiler::target::word
@@ -9356,11 +9368,11 @@
static constexpr dart::compiler::target::word
AOT_Thread_predefined_symbols_address_offset = 664;
static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset =
- 1552;
+ 1568;
static constexpr dart::compiler::target::word
- AOT_Thread_saved_shadow_call_stack_offset = 1560;
+ AOT_Thread_saved_shadow_call_stack_offset = 1576;
static constexpr dart::compiler::target::word
- AOT_Thread_safepoint_state_offset = 1576;
+ AOT_Thread_safepoint_state_offset = 1592;
static constexpr dart::compiler::target::word
AOT_Thread_slow_type_test_stub_offset = 472;
static constexpr dart::compiler::target::word
@@ -9397,36 +9409,36 @@
AOT_Thread_write_barrier_mask_offset = 72;
static constexpr dart::compiler::target::word AOT_Thread_heap_base_offset = 80;
static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
- 1584;
+ 1600;
static constexpr dart::compiler::target::word
- AOT_Thread_callback_stack_return_offset = 1592;
+ AOT_Thread_callback_stack_return_offset = 1608;
static constexpr dart::compiler::target::word
AOT_TimelineStream_enabled_offset = 16;
static constexpr dart::compiler::target::word AOT_TwoByteString_data_offset =
16;
-static constexpr dart::compiler::target::word AOT_Type_arguments_offset = 24;
-static constexpr dart::compiler::target::word AOT_Type_hash_offset = 28;
+static constexpr dart::compiler::target::word AOT_Type_arguments_offset = 28;
+static constexpr dart::compiler::target::word AOT_Type_hash_offset = 32;
static constexpr dart::compiler::target::word AOT_Type_type_class_id_offset =
- 20;
-static constexpr dart::compiler::target::word AOT_Type_type_state_offset = 32;
-static constexpr dart::compiler::target::word AOT_Type_nullability_offset = 33;
-static constexpr dart::compiler::target::word AOT_FunctionType_hash_offset = 36;
+ 24;
+static constexpr dart::compiler::target::word AOT_Type_type_state_offset = 36;
+static constexpr dart::compiler::target::word AOT_Type_nullability_offset = 37;
+static constexpr dart::compiler::target::word AOT_FunctionType_hash_offset = 40;
static constexpr dart::compiler::target::word
- AOT_FunctionType_packed_parameter_counts_offset = 40;
+ AOT_FunctionType_packed_parameter_counts_offset = 44;
static constexpr dart::compiler::target::word
- AOT_FunctionType_packed_type_parameter_counts_offset = 44;
+ AOT_FunctionType_packed_type_parameter_counts_offset = 48;
static constexpr dart::compiler::target::word
- AOT_FunctionType_parameter_types_offset = 28;
+ AOT_FunctionType_parameter_types_offset = 32;
static constexpr dart::compiler::target::word
- AOT_FunctionType_named_parameter_names_offset = 32;
+ AOT_FunctionType_named_parameter_names_offset = 36;
static constexpr dart::compiler::target::word
- AOT_FunctionType_type_parameters_offset = 20;
+ AOT_FunctionType_type_parameters_offset = 24;
static constexpr dart::compiler::target::word
- AOT_TypeParameter_parameterized_class_id_offset = 28;
+ AOT_TypeParameter_parameterized_class_id_offset = 32;
static constexpr dart::compiler::target::word AOT_TypeParameter_index_offset =
- 31;
+ 35;
static constexpr dart::compiler::target::word
- AOT_TypeParameter_nullability_offset = 33;
+ AOT_TypeParameter_nullability_offset = 37;
static constexpr dart::compiler::target::word
AOT_TypeArguments_instantiations_offset = 8;
static constexpr dart::compiler::target::word AOT_TypeArguments_length_offset =
@@ -9444,16 +9456,16 @@
static constexpr dart::compiler::target::word
AOT_TypeParameters_defaults_offset = 20;
static constexpr dart::compiler::target::word AOT_TypeParameter_bound_offset =
- 24;
+ 28;
static constexpr dart::compiler::target::word AOT_TypeParameter_flags_offset =
- 32;
-static constexpr dart::compiler::target::word AOT_TypeRef_type_offset = 20;
+ 36;
+static constexpr dart::compiler::target::word AOT_TypeRef_type_offset = 24;
static constexpr dart::compiler::target::word AOT_TypedDataBase_length_offset =
- 16;
-static constexpr dart::compiler::target::word AOT_TypedDataView_data_offset =
20;
+static constexpr dart::compiler::target::word AOT_TypedDataView_data_offset =
+ 24;
static constexpr dart::compiler::target::word
- AOT_TypedDataView_offset_in_bytes_offset = 24;
+ AOT_TypedDataView_offset_in_bytes_offset = 28;
static constexpr dart::compiler::target::word AOT_TypedData_data_offset = 24;
static constexpr dart::compiler::target::word
AOT_UnhandledException_exception_offset = 8;
@@ -9473,9 +9485,9 @@
8, 24, 16, 32};
static constexpr dart::compiler::target::word
AOT_Thread_write_barrier_wrappers_thread_offset[] = {
- 1376, 1384, 1392, 1400, 1408, 1416, 1424, 1432, 1440, 1448, 1456,
- 1464, 1472, 1480, 1488, -1, -1, -1, -1, 1496, 1504, -1,
- -1, 1512, 1520, 1528, -1, -1, -1, -1, -1, -1};
+ 1392, 1400, 1408, 1416, 1424, 1432, 1440, 1448, 1456, 1464, 1472,
+ 1480, 1488, 1496, 1504, -1, -1, -1, -1, 1512, 1520, -1,
+ -1, 1528, 1536, 1544, -1, -1, -1, -1, -1, -1};
static constexpr dart::compiler::target::word AOT_AbstractType_InstanceSize =
24;
static constexpr dart::compiler::target::word AOT_ApiError_InstanceSize = 16;
@@ -9505,7 +9517,7 @@
static constexpr dart::compiler::target::word AOT_Float64x2_InstanceSize = 24;
static constexpr dart::compiler::target::word AOT_Function_InstanceSize = 56;
static constexpr dart::compiler::target::word AOT_FunctionType_InstanceSize =
- 48;
+ 56;
static constexpr dart::compiler::target::word AOT_FutureOr_InstanceSize = 16;
static constexpr dart::compiler::target::word
AOT_GrowableObjectArray_InstanceSize = 24;
@@ -9560,7 +9572,7 @@
40;
static constexpr dart::compiler::target::word AOT_TypeParameters_InstanceSize =
24;
-static constexpr dart::compiler::target::word AOT_TypeRef_InstanceSize = 24;
+static constexpr dart::compiler::target::word AOT_TypeRef_InstanceSize = 32;
static constexpr dart::compiler::target::word AOT_TypedData_HeaderSize = 24;
static constexpr dart::compiler::target::word AOT_TypedDataBase_InstanceSize =
24;
@@ -9767,17 +9779,17 @@
AOT_IsolateGroup_cached_class_table_table_offset = 16;
static constexpr dart::compiler::target::word AOT_Isolate_user_tag_offset = 16;
static constexpr dart::compiler::target::word AOT_LinkedHashBase_data_offset =
- 16;
+ 12;
static constexpr dart::compiler::target::word
- AOT_LinkedHashBase_deleted_keys_offset = 24;
+ AOT_LinkedHashBase_deleted_keys_offset = 20;
static constexpr dart::compiler::target::word
- AOT_LinkedHashBase_hash_mask_offset = 12;
+ AOT_LinkedHashBase_hash_mask_offset = 8;
static constexpr dart::compiler::target::word AOT_LinkedHashBase_index_offset =
- 8;
+ 24;
static constexpr dart::compiler::target::word
AOT_LinkedHashBase_type_arguments_offset = 4;
static constexpr dart::compiler::target::word
- AOT_LinkedHashBase_used_data_offset = 20;
+ AOT_LinkedHashBase_used_data_offset = 16;
static constexpr dart::compiler::target::word AOT_LocalHandle_ptr_offset = 0;
static constexpr dart::compiler::target::word
AOT_MarkingStackBlock_pointers_offset = 8;
@@ -9797,13 +9809,13 @@
static constexpr dart::compiler::target::word
AOT_NativeArguments_thread_offset = 0;
static constexpr dart::compiler::target::word
- AOT_ObjectStore_double_type_offset = 128;
+ AOT_ObjectStore_double_type_offset = 184;
static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
- 68;
+ 124;
static constexpr dart::compiler::target::word
- AOT_ObjectStore_string_type_offset = 156;
+ AOT_ObjectStore_string_type_offset = 212;
static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
- 48;
+ 104;
static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
12;
static constexpr dart::compiler::target::word
@@ -9829,9 +9841,9 @@
static constexpr dart::compiler::target::word
AOT_Thread_AllocateArray_entry_point_offset = 368;
static constexpr dart::compiler::target::word
- AOT_Thread_active_exception_offset = 724;
+ AOT_Thread_active_exception_offset = 732;
static constexpr dart::compiler::target::word
- AOT_Thread_active_stacktrace_offset = 728;
+ AOT_Thread_active_stacktrace_offset = 736;
static constexpr dart::compiler::target::word
AOT_Thread_array_write_barrier_code_offset = 120;
static constexpr dart::compiler::target::word
@@ -9857,7 +9869,7 @@
static constexpr dart::compiler::target::word
AOT_Thread_allocate_object_slow_stub_offset = 196;
static constexpr dart::compiler::target::word AOT_Thread_api_top_scope_offset =
- 764;
+ 772;
static constexpr dart::compiler::target::word
AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 332;
static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
@@ -9870,7 +9882,7 @@
static constexpr dart::compiler::target::word
AOT_Thread_call_to_runtime_stub_offset = 136;
static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
- 772;
+ 780;
static constexpr dart::compiler::target::word
AOT_Thread_dispatch_table_array_offset = 48;
static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
@@ -9889,7 +9901,7 @@
static constexpr dart::compiler::target::word
AOT_Thread_enter_safepoint_stub_offset = 248;
static constexpr dart::compiler::target::word
- AOT_Thread_execution_state_offset = 744;
+ AOT_Thread_execution_state_offset = 752;
static constexpr dart::compiler::target::word
AOT_Thread_exit_safepoint_stub_offset = 252;
static constexpr dart::compiler::target::word
@@ -9909,14 +9921,14 @@
static constexpr dart::compiler::target::word
AOT_Thread_float_zerow_address_offset = 364;
static constexpr dart::compiler::target::word
- AOT_Thread_global_object_pool_offset = 732;
+ AOT_Thread_global_object_pool_offset = 740;
static constexpr dart::compiler::target::word
AOT_Thread_invoke_dart_code_stub_offset = 132;
static constexpr dart::compiler::target::word
- AOT_Thread_exit_through_ffi_offset = 760;
+ AOT_Thread_exit_through_ffi_offset = 768;
static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 44;
static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset =
- 776;
+ 784;
static constexpr dart::compiler::target::word
AOT_Thread_field_table_values_offset = 68;
static constexpr dart::compiler::target::word
@@ -9960,11 +9972,11 @@
104;
static constexpr dart::compiler::target::word
AOT_Thread_predefined_symbols_address_offset = 336;
-static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset = 736;
+static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset = 744;
static constexpr dart::compiler::target::word
- AOT_Thread_saved_shadow_call_stack_offset = 740;
+ AOT_Thread_saved_shadow_call_stack_offset = 748;
static constexpr dart::compiler::target::word
- AOT_Thread_safepoint_state_offset = 748;
+ AOT_Thread_safepoint_state_offset = 756;
static constexpr dart::compiler::target::word
AOT_Thread_slow_type_test_stub_offset = 240;
static constexpr dart::compiler::target::word
@@ -10001,9 +10013,9 @@
AOT_Thread_write_barrier_mask_offset = 36;
static constexpr dart::compiler::target::word AOT_Thread_heap_base_offset = 40;
static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
- 752;
+ 760;
static constexpr dart::compiler::target::word
- AOT_Thread_callback_stack_return_offset = 756;
+ AOT_Thread_callback_stack_return_offset = 764;
static constexpr dart::compiler::target::word
AOT_TimelineStream_enabled_offset = 8;
static constexpr dart::compiler::target::word AOT_TwoByteString_data_offset =
@@ -10076,7 +10088,7 @@
4, 12, 8, 16};
static constexpr dart::compiler::target::word
AOT_Thread_write_barrier_wrappers_thread_offset[] = {
- 692, 696, 700, 704, 708, -1, 712, -1, 716, 720, -1, -1, -1, -1, -1, -1};
+ 700, 704, 708, 712, 716, -1, 720, -1, 724, 728, -1, -1, -1, -1, -1, -1};
static constexpr dart::compiler::target::word AOT_AbstractType_InstanceSize =
12;
static constexpr dart::compiler::target::word AOT_ApiError_InstanceSize = 8;
@@ -10367,17 +10379,17 @@
AOT_IsolateGroup_cached_class_table_table_offset = 32;
static constexpr dart::compiler::target::word AOT_Isolate_user_tag_offset = 32;
static constexpr dart::compiler::target::word AOT_LinkedHashBase_data_offset =
- 32;
+ 24;
static constexpr dart::compiler::target::word
- AOT_LinkedHashBase_deleted_keys_offset = 48;
+ AOT_LinkedHashBase_deleted_keys_offset = 40;
static constexpr dart::compiler::target::word
- AOT_LinkedHashBase_hash_mask_offset = 24;
+ AOT_LinkedHashBase_hash_mask_offset = 16;
static constexpr dart::compiler::target::word AOT_LinkedHashBase_index_offset =
- 16;
+ 48;
static constexpr dart::compiler::target::word
AOT_LinkedHashBase_type_arguments_offset = 8;
static constexpr dart::compiler::target::word
- AOT_LinkedHashBase_used_data_offset = 40;
+ AOT_LinkedHashBase_used_data_offset = 32;
static constexpr dart::compiler::target::word AOT_LocalHandle_ptr_offset = 0;
static constexpr dart::compiler::target::word
AOT_MarkingStackBlock_pointers_offset = 16;
@@ -10397,13 +10409,13 @@
static constexpr dart::compiler::target::word
AOT_NativeArguments_thread_offset = 0;
static constexpr dart::compiler::target::word
- AOT_ObjectStore_double_type_offset = 256;
+ AOT_ObjectStore_double_type_offset = 368;
static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
- 136;
+ 248;
static constexpr dart::compiler::target::word
- AOT_ObjectStore_string_type_offset = 312;
+ AOT_ObjectStore_string_type_offset = 424;
static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
- 96;
+ 208;
static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
16;
static constexpr dart::compiler::target::word
@@ -10429,9 +10441,9 @@
static constexpr dart::compiler::target::word
AOT_Thread_AllocateArray_entry_point_offset = 728;
static constexpr dart::compiler::target::word
- AOT_Thread_active_exception_offset = 1464;
+ AOT_Thread_active_exception_offset = 1480;
static constexpr dart::compiler::target::word
- AOT_Thread_active_stacktrace_offset = 1472;
+ AOT_Thread_active_stacktrace_offset = 1488;
static constexpr dart::compiler::target::word
AOT_Thread_array_write_barrier_code_offset = 232;
static constexpr dart::compiler::target::word
@@ -10457,7 +10469,7 @@
static constexpr dart::compiler::target::word
AOT_Thread_allocate_object_slow_stub_offset = 384;
static constexpr dart::compiler::target::word AOT_Thread_api_top_scope_offset =
- 1544;
+ 1560;
static constexpr dart::compiler::target::word
AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 656;
static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
@@ -10470,7 +10482,7 @@
static constexpr dart::compiler::target::word
AOT_Thread_call_to_runtime_stub_offset = 264;
static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
- 1560;
+ 1576;
static constexpr dart::compiler::target::word
AOT_Thread_dispatch_table_array_offset = 96;
static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
@@ -10489,7 +10501,7 @@
static constexpr dart::compiler::target::word
AOT_Thread_enter_safepoint_stub_offset = 488;
static constexpr dart::compiler::target::word
- AOT_Thread_execution_state_offset = 1504;
+ AOT_Thread_execution_state_offset = 1520;
static constexpr dart::compiler::target::word
AOT_Thread_exit_safepoint_stub_offset = 496;
static constexpr dart::compiler::target::word
@@ -10509,14 +10521,14 @@
static constexpr dart::compiler::target::word
AOT_Thread_float_zerow_address_offset = 720;
static constexpr dart::compiler::target::word
- AOT_Thread_global_object_pool_offset = 1480;
+ AOT_Thread_global_object_pool_offset = 1496;
static constexpr dart::compiler::target::word
AOT_Thread_invoke_dart_code_stub_offset = 256;
static constexpr dart::compiler::target::word
- AOT_Thread_exit_through_ffi_offset = 1536;
+ AOT_Thread_exit_through_ffi_offset = 1552;
static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 88;
static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset =
- 1568;
+ 1584;
static constexpr dart::compiler::target::word
AOT_Thread_field_table_values_offset = 136;
static constexpr dart::compiler::target::word
@@ -10561,11 +10573,11 @@
static constexpr dart::compiler::target::word
AOT_Thread_predefined_symbols_address_offset = 664;
static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset =
- 1488;
+ 1504;
static constexpr dart::compiler::target::word
- AOT_Thread_saved_shadow_call_stack_offset = 1496;
+ AOT_Thread_saved_shadow_call_stack_offset = 1512;
static constexpr dart::compiler::target::word
- AOT_Thread_safepoint_state_offset = 1512;
+ AOT_Thread_safepoint_state_offset = 1528;
static constexpr dart::compiler::target::word
AOT_Thread_slow_type_test_stub_offset = 472;
static constexpr dart::compiler::target::word
@@ -10602,9 +10614,9 @@
AOT_Thread_write_barrier_mask_offset = 72;
static constexpr dart::compiler::target::word AOT_Thread_heap_base_offset = 80;
static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
- 1520;
+ 1536;
static constexpr dart::compiler::target::word
- AOT_Thread_callback_stack_return_offset = 1528;
+ AOT_Thread_callback_stack_return_offset = 1544;
static constexpr dart::compiler::target::word
AOT_TimelineStream_enabled_offset = 16;
static constexpr dart::compiler::target::word AOT_TwoByteString_data_offset =
@@ -10678,8 +10690,8 @@
8, 24, 16, 32};
static constexpr dart::compiler::target::word
AOT_Thread_write_barrier_wrappers_thread_offset[] = {
- 1376, 1384, 1392, 1400, -1, -1, 1408, 1416,
- 1424, 1432, 1440, -1, 1448, 1456, -1, -1};
+ 1392, 1400, 1408, 1416, -1, -1, 1424, 1432,
+ 1440, 1448, 1456, -1, 1464, 1472, -1, -1};
static constexpr dart::compiler::target::word AOT_AbstractType_InstanceSize =
24;
static constexpr dart::compiler::target::word AOT_ApiError_InstanceSize = 16;
@@ -10973,17 +10985,17 @@
AOT_IsolateGroup_cached_class_table_table_offset = 32;
static constexpr dart::compiler::target::word AOT_Isolate_user_tag_offset = 32;
static constexpr dart::compiler::target::word AOT_LinkedHashBase_data_offset =
- 32;
+ 24;
static constexpr dart::compiler::target::word
- AOT_LinkedHashBase_deleted_keys_offset = 48;
+ AOT_LinkedHashBase_deleted_keys_offset = 40;
static constexpr dart::compiler::target::word
- AOT_LinkedHashBase_hash_mask_offset = 24;
+ AOT_LinkedHashBase_hash_mask_offset = 16;
static constexpr dart::compiler::target::word AOT_LinkedHashBase_index_offset =
- 16;
+ 48;
static constexpr dart::compiler::target::word
AOT_LinkedHashBase_type_arguments_offset = 8;
static constexpr dart::compiler::target::word
- AOT_LinkedHashBase_used_data_offset = 40;
+ AOT_LinkedHashBase_used_data_offset = 32;
static constexpr dart::compiler::target::word AOT_LocalHandle_ptr_offset = 0;
static constexpr dart::compiler::target::word
AOT_MarkingStackBlock_pointers_offset = 16;
@@ -11003,13 +11015,13 @@
static constexpr dart::compiler::target::word
AOT_NativeArguments_thread_offset = 0;
static constexpr dart::compiler::target::word
- AOT_ObjectStore_double_type_offset = 256;
+ AOT_ObjectStore_double_type_offset = 368;
static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
- 136;
+ 248;
static constexpr dart::compiler::target::word
- AOT_ObjectStore_string_type_offset = 312;
+ AOT_ObjectStore_string_type_offset = 424;
static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
- 96;
+ 208;
static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
16;
static constexpr dart::compiler::target::word
@@ -11035,9 +11047,9 @@
static constexpr dart::compiler::target::word
AOT_Thread_AllocateArray_entry_point_offset = 728;
static constexpr dart::compiler::target::word
- AOT_Thread_active_exception_offset = 1528;
+ AOT_Thread_active_exception_offset = 1544;
static constexpr dart::compiler::target::word
- AOT_Thread_active_stacktrace_offset = 1536;
+ AOT_Thread_active_stacktrace_offset = 1552;
static constexpr dart::compiler::target::word
AOT_Thread_array_write_barrier_code_offset = 232;
static constexpr dart::compiler::target::word
@@ -11063,7 +11075,7 @@
static constexpr dart::compiler::target::word
AOT_Thread_allocate_object_slow_stub_offset = 384;
static constexpr dart::compiler::target::word AOT_Thread_api_top_scope_offset =
- 1608;
+ 1624;
static constexpr dart::compiler::target::word
AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 656;
static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
@@ -11076,7 +11088,7 @@
static constexpr dart::compiler::target::word
AOT_Thread_call_to_runtime_stub_offset = 264;
static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
- 1624;
+ 1640;
static constexpr dart::compiler::target::word
AOT_Thread_dispatch_table_array_offset = 96;
static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
@@ -11095,7 +11107,7 @@
static constexpr dart::compiler::target::word
AOT_Thread_enter_safepoint_stub_offset = 488;
static constexpr dart::compiler::target::word
- AOT_Thread_execution_state_offset = 1568;
+ AOT_Thread_execution_state_offset = 1584;
static constexpr dart::compiler::target::word
AOT_Thread_exit_safepoint_stub_offset = 496;
static constexpr dart::compiler::target::word
@@ -11115,14 +11127,14 @@
static constexpr dart::compiler::target::word
AOT_Thread_float_zerow_address_offset = 720;
static constexpr dart::compiler::target::word
- AOT_Thread_global_object_pool_offset = 1544;
+ AOT_Thread_global_object_pool_offset = 1560;
static constexpr dart::compiler::target::word
AOT_Thread_invoke_dart_code_stub_offset = 256;
static constexpr dart::compiler::target::word
- AOT_Thread_exit_through_ffi_offset = 1600;
+ AOT_Thread_exit_through_ffi_offset = 1616;
static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 88;
static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset =
- 1632;
+ 1648;
static constexpr dart::compiler::target::word
AOT_Thread_field_table_values_offset = 136;
static constexpr dart::compiler::target::word
@@ -11167,11 +11179,11 @@
static constexpr dart::compiler::target::word
AOT_Thread_predefined_symbols_address_offset = 664;
static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset =
- 1552;
+ 1568;
static constexpr dart::compiler::target::word
- AOT_Thread_saved_shadow_call_stack_offset = 1560;
+ AOT_Thread_saved_shadow_call_stack_offset = 1576;
static constexpr dart::compiler::target::word
- AOT_Thread_safepoint_state_offset = 1576;
+ AOT_Thread_safepoint_state_offset = 1592;
static constexpr dart::compiler::target::word
AOT_Thread_slow_type_test_stub_offset = 472;
static constexpr dart::compiler::target::word
@@ -11208,9 +11220,9 @@
AOT_Thread_write_barrier_mask_offset = 72;
static constexpr dart::compiler::target::word AOT_Thread_heap_base_offset = 80;
static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
- 1584;
+ 1600;
static constexpr dart::compiler::target::word
- AOT_Thread_callback_stack_return_offset = 1592;
+ AOT_Thread_callback_stack_return_offset = 1608;
static constexpr dart::compiler::target::word
AOT_TimelineStream_enabled_offset = 16;
static constexpr dart::compiler::target::word AOT_TwoByteString_data_offset =
@@ -11284,9 +11296,9 @@
8, 24, 16, 32};
static constexpr dart::compiler::target::word
AOT_Thread_write_barrier_wrappers_thread_offset[] = {
- 1376, 1384, 1392, 1400, 1408, 1416, 1424, 1432, 1440, 1448, 1456,
- 1464, 1472, 1480, 1488, -1, -1, -1, -1, 1496, 1504, -1,
- -1, 1512, 1520, 1528, -1, -1, -1, -1, -1, -1};
+ 1392, 1400, 1408, 1416, 1424, 1432, 1440, 1448, 1456, 1464, 1472,
+ 1480, 1488, 1496, 1504, -1, -1, -1, -1, 1512, 1520, -1,
+ -1, 1528, 1536, 1544, -1, -1, -1, -1, -1, -1};
static constexpr dart::compiler::target::word AOT_AbstractType_InstanceSize =
24;
static constexpr dart::compiler::target::word AOT_ApiError_InstanceSize = 16;
@@ -11576,17 +11588,17 @@
AOT_IsolateGroup_cached_class_table_table_offset = 32;
static constexpr dart::compiler::target::word AOT_Isolate_user_tag_offset = 32;
static constexpr dart::compiler::target::word AOT_LinkedHashBase_data_offset =
- 20;
+ 16;
static constexpr dart::compiler::target::word
- AOT_LinkedHashBase_deleted_keys_offset = 28;
+ AOT_LinkedHashBase_deleted_keys_offset = 24;
static constexpr dart::compiler::target::word
- AOT_LinkedHashBase_hash_mask_offset = 16;
+ AOT_LinkedHashBase_hash_mask_offset = 12;
static constexpr dart::compiler::target::word AOT_LinkedHashBase_index_offset =
- 12;
+ 28;
static constexpr dart::compiler::target::word
AOT_LinkedHashBase_type_arguments_offset = 8;
static constexpr dart::compiler::target::word
- AOT_LinkedHashBase_used_data_offset = 24;
+ AOT_LinkedHashBase_used_data_offset = 20;
static constexpr dart::compiler::target::word AOT_LocalHandle_ptr_offset = 0;
static constexpr dart::compiler::target::word
AOT_MarkingStackBlock_pointers_offset = 16;
@@ -11606,13 +11618,13 @@
static constexpr dart::compiler::target::word
AOT_NativeArguments_thread_offset = 0;
static constexpr dart::compiler::target::word
- AOT_ObjectStore_double_type_offset = 256;
+ AOT_ObjectStore_double_type_offset = 368;
static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
- 136;
+ 248;
static constexpr dart::compiler::target::word
- AOT_ObjectStore_string_type_offset = 312;
+ AOT_ObjectStore_string_type_offset = 424;
static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
- 96;
+ 208;
static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
16;
static constexpr dart::compiler::target::word
@@ -11638,9 +11650,9 @@
static constexpr dart::compiler::target::word
AOT_Thread_AllocateArray_entry_point_offset = 728;
static constexpr dart::compiler::target::word
- AOT_Thread_active_exception_offset = 1464;
+ AOT_Thread_active_exception_offset = 1480;
static constexpr dart::compiler::target::word
- AOT_Thread_active_stacktrace_offset = 1472;
+ AOT_Thread_active_stacktrace_offset = 1488;
static constexpr dart::compiler::target::word
AOT_Thread_array_write_barrier_code_offset = 232;
static constexpr dart::compiler::target::word
@@ -11666,7 +11678,7 @@
static constexpr dart::compiler::target::word
AOT_Thread_allocate_object_slow_stub_offset = 384;
static constexpr dart::compiler::target::word AOT_Thread_api_top_scope_offset =
- 1544;
+ 1560;
static constexpr dart::compiler::target::word
AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 656;
static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
@@ -11679,7 +11691,7 @@
static constexpr dart::compiler::target::word
AOT_Thread_call_to_runtime_stub_offset = 264;
static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
- 1560;
+ 1576;
static constexpr dart::compiler::target::word
AOT_Thread_dispatch_table_array_offset = 96;
static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
@@ -11698,7 +11710,7 @@
static constexpr dart::compiler::target::word
AOT_Thread_enter_safepoint_stub_offset = 488;
static constexpr dart::compiler::target::word
- AOT_Thread_execution_state_offset = 1504;
+ AOT_Thread_execution_state_offset = 1520;
static constexpr dart::compiler::target::word
AOT_Thread_exit_safepoint_stub_offset = 496;
static constexpr dart::compiler::target::word
@@ -11718,14 +11730,14 @@
static constexpr dart::compiler::target::word
AOT_Thread_float_zerow_address_offset = 720;
static constexpr dart::compiler::target::word
- AOT_Thread_global_object_pool_offset = 1480;
+ AOT_Thread_global_object_pool_offset = 1496;
static constexpr dart::compiler::target::word
AOT_Thread_invoke_dart_code_stub_offset = 256;
static constexpr dart::compiler::target::word
- AOT_Thread_exit_through_ffi_offset = 1536;
+ AOT_Thread_exit_through_ffi_offset = 1552;
static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 88;
static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset =
- 1568;
+ 1584;
static constexpr dart::compiler::target::word
AOT_Thread_field_table_values_offset = 136;
static constexpr dart::compiler::target::word
@@ -11770,11 +11782,11 @@
static constexpr dart::compiler::target::word
AOT_Thread_predefined_symbols_address_offset = 664;
static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset =
- 1488;
+ 1504;
static constexpr dart::compiler::target::word
- AOT_Thread_saved_shadow_call_stack_offset = 1496;
+ AOT_Thread_saved_shadow_call_stack_offset = 1512;
static constexpr dart::compiler::target::word
- AOT_Thread_safepoint_state_offset = 1512;
+ AOT_Thread_safepoint_state_offset = 1528;
static constexpr dart::compiler::target::word
AOT_Thread_slow_type_test_stub_offset = 472;
static constexpr dart::compiler::target::word
@@ -11811,36 +11823,36 @@
AOT_Thread_write_barrier_mask_offset = 72;
static constexpr dart::compiler::target::word AOT_Thread_heap_base_offset = 80;
static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
- 1520;
+ 1536;
static constexpr dart::compiler::target::word
- AOT_Thread_callback_stack_return_offset = 1528;
+ AOT_Thread_callback_stack_return_offset = 1544;
static constexpr dart::compiler::target::word
AOT_TimelineStream_enabled_offset = 16;
static constexpr dart::compiler::target::word AOT_TwoByteString_data_offset =
16;
-static constexpr dart::compiler::target::word AOT_Type_arguments_offset = 24;
-static constexpr dart::compiler::target::word AOT_Type_hash_offset = 28;
+static constexpr dart::compiler::target::word AOT_Type_arguments_offset = 28;
+static constexpr dart::compiler::target::word AOT_Type_hash_offset = 32;
static constexpr dart::compiler::target::word AOT_Type_type_class_id_offset =
- 20;
-static constexpr dart::compiler::target::word AOT_Type_type_state_offset = 32;
-static constexpr dart::compiler::target::word AOT_Type_nullability_offset = 33;
-static constexpr dart::compiler::target::word AOT_FunctionType_hash_offset = 36;
+ 24;
+static constexpr dart::compiler::target::word AOT_Type_type_state_offset = 36;
+static constexpr dart::compiler::target::word AOT_Type_nullability_offset = 37;
+static constexpr dart::compiler::target::word AOT_FunctionType_hash_offset = 40;
static constexpr dart::compiler::target::word
- AOT_FunctionType_packed_parameter_counts_offset = 40;
+ AOT_FunctionType_packed_parameter_counts_offset = 44;
static constexpr dart::compiler::target::word
- AOT_FunctionType_packed_type_parameter_counts_offset = 44;
+ AOT_FunctionType_packed_type_parameter_counts_offset = 48;
static constexpr dart::compiler::target::word
- AOT_FunctionType_parameter_types_offset = 28;
+ AOT_FunctionType_parameter_types_offset = 32;
static constexpr dart::compiler::target::word
- AOT_FunctionType_named_parameter_names_offset = 32;
+ AOT_FunctionType_named_parameter_names_offset = 36;
static constexpr dart::compiler::target::word
- AOT_FunctionType_type_parameters_offset = 20;
+ AOT_FunctionType_type_parameters_offset = 24;
static constexpr dart::compiler::target::word
- AOT_TypeParameter_parameterized_class_id_offset = 28;
+ AOT_TypeParameter_parameterized_class_id_offset = 32;
static constexpr dart::compiler::target::word AOT_TypeParameter_index_offset =
- 31;
+ 35;
static constexpr dart::compiler::target::word
- AOT_TypeParameter_nullability_offset = 33;
+ AOT_TypeParameter_nullability_offset = 37;
static constexpr dart::compiler::target::word
AOT_TypeArguments_instantiations_offset = 8;
static constexpr dart::compiler::target::word AOT_TypeArguments_length_offset =
@@ -11858,16 +11870,16 @@
static constexpr dart::compiler::target::word
AOT_TypeParameters_defaults_offset = 20;
static constexpr dart::compiler::target::word AOT_TypeParameter_bound_offset =
- 24;
+ 28;
static constexpr dart::compiler::target::word AOT_TypeParameter_flags_offset =
- 32;
-static constexpr dart::compiler::target::word AOT_TypeRef_type_offset = 20;
+ 36;
+static constexpr dart::compiler::target::word AOT_TypeRef_type_offset = 24;
static constexpr dart::compiler::target::word AOT_TypedDataBase_length_offset =
- 16;
-static constexpr dart::compiler::target::word AOT_TypedDataView_data_offset =
20;
+static constexpr dart::compiler::target::word AOT_TypedDataView_data_offset =
+ 24;
static constexpr dart::compiler::target::word
- AOT_TypedDataView_offset_in_bytes_offset = 24;
+ AOT_TypedDataView_offset_in_bytes_offset = 28;
static constexpr dart::compiler::target::word AOT_TypedData_data_offset = 24;
static constexpr dart::compiler::target::word
AOT_UnhandledException_exception_offset = 8;
@@ -11887,8 +11899,8 @@
8, 24, 16, 32};
static constexpr dart::compiler::target::word
AOT_Thread_write_barrier_wrappers_thread_offset[] = {
- 1376, 1384, 1392, 1400, -1, -1, 1408, 1416,
- 1424, 1432, 1440, -1, 1448, 1456, -1, -1};
+ 1392, 1400, 1408, 1416, -1, -1, 1424, 1432,
+ 1440, 1448, 1456, -1, 1464, 1472, -1, -1};
static constexpr dart::compiler::target::word AOT_AbstractType_InstanceSize =
24;
static constexpr dart::compiler::target::word AOT_ApiError_InstanceSize = 16;
@@ -11918,7 +11930,7 @@
static constexpr dart::compiler::target::word AOT_Float64x2_InstanceSize = 24;
static constexpr dart::compiler::target::word AOT_Function_InstanceSize = 56;
static constexpr dart::compiler::target::word AOT_FunctionType_InstanceSize =
- 48;
+ 56;
static constexpr dart::compiler::target::word AOT_FutureOr_InstanceSize = 16;
static constexpr dart::compiler::target::word
AOT_GrowableObjectArray_InstanceSize = 24;
@@ -11973,7 +11985,7 @@
40;
static constexpr dart::compiler::target::word AOT_TypeParameters_InstanceSize =
24;
-static constexpr dart::compiler::target::word AOT_TypeRef_InstanceSize = 24;
+static constexpr dart::compiler::target::word AOT_TypeRef_InstanceSize = 32;
static constexpr dart::compiler::target::word AOT_TypedData_HeaderSize = 24;
static constexpr dart::compiler::target::word AOT_TypedDataBase_InstanceSize =
24;
@@ -12178,17 +12190,17 @@
AOT_IsolateGroup_cached_class_table_table_offset = 32;
static constexpr dart::compiler::target::word AOT_Isolate_user_tag_offset = 32;
static constexpr dart::compiler::target::word AOT_LinkedHashBase_data_offset =
- 20;
+ 16;
static constexpr dart::compiler::target::word
- AOT_LinkedHashBase_deleted_keys_offset = 28;
+ AOT_LinkedHashBase_deleted_keys_offset = 24;
static constexpr dart::compiler::target::word
- AOT_LinkedHashBase_hash_mask_offset = 16;
+ AOT_LinkedHashBase_hash_mask_offset = 12;
static constexpr dart::compiler::target::word AOT_LinkedHashBase_index_offset =
- 12;
+ 28;
static constexpr dart::compiler::target::word
AOT_LinkedHashBase_type_arguments_offset = 8;
static constexpr dart::compiler::target::word
- AOT_LinkedHashBase_used_data_offset = 24;
+ AOT_LinkedHashBase_used_data_offset = 20;
static constexpr dart::compiler::target::word AOT_LocalHandle_ptr_offset = 0;
static constexpr dart::compiler::target::word
AOT_MarkingStackBlock_pointers_offset = 16;
@@ -12208,13 +12220,13 @@
static constexpr dart::compiler::target::word
AOT_NativeArguments_thread_offset = 0;
static constexpr dart::compiler::target::word
- AOT_ObjectStore_double_type_offset = 256;
+ AOT_ObjectStore_double_type_offset = 368;
static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
- 136;
+ 248;
static constexpr dart::compiler::target::word
- AOT_ObjectStore_string_type_offset = 312;
+ AOT_ObjectStore_string_type_offset = 424;
static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
- 96;
+ 208;
static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
16;
static constexpr dart::compiler::target::word
@@ -12240,9 +12252,9 @@
static constexpr dart::compiler::target::word
AOT_Thread_AllocateArray_entry_point_offset = 728;
static constexpr dart::compiler::target::word
- AOT_Thread_active_exception_offset = 1528;
+ AOT_Thread_active_exception_offset = 1544;
static constexpr dart::compiler::target::word
- AOT_Thread_active_stacktrace_offset = 1536;
+ AOT_Thread_active_stacktrace_offset = 1552;
static constexpr dart::compiler::target::word
AOT_Thread_array_write_barrier_code_offset = 232;
static constexpr dart::compiler::target::word
@@ -12268,7 +12280,7 @@
static constexpr dart::compiler::target::word
AOT_Thread_allocate_object_slow_stub_offset = 384;
static constexpr dart::compiler::target::word AOT_Thread_api_top_scope_offset =
- 1608;
+ 1624;
static constexpr dart::compiler::target::word
AOT_Thread_auto_scope_native_wrapper_entry_point_offset = 656;
static constexpr dart::compiler::target::word AOT_Thread_bool_false_offset =
@@ -12281,7 +12293,7 @@
static constexpr dart::compiler::target::word
AOT_Thread_call_to_runtime_stub_offset = 264;
static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
- 1624;
+ 1640;
static constexpr dart::compiler::target::word
AOT_Thread_dispatch_table_array_offset = 96;
static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
@@ -12300,7 +12312,7 @@
static constexpr dart::compiler::target::word
AOT_Thread_enter_safepoint_stub_offset = 488;
static constexpr dart::compiler::target::word
- AOT_Thread_execution_state_offset = 1568;
+ AOT_Thread_execution_state_offset = 1584;
static constexpr dart::compiler::target::word
AOT_Thread_exit_safepoint_stub_offset = 496;
static constexpr dart::compiler::target::word
@@ -12320,14 +12332,14 @@
static constexpr dart::compiler::target::word
AOT_Thread_float_zerow_address_offset = 720;
static constexpr dart::compiler::target::word
- AOT_Thread_global_object_pool_offset = 1544;
+ AOT_Thread_global_object_pool_offset = 1560;
static constexpr dart::compiler::target::word
AOT_Thread_invoke_dart_code_stub_offset = 256;
static constexpr dart::compiler::target::word
- AOT_Thread_exit_through_ffi_offset = 1600;
+ AOT_Thread_exit_through_ffi_offset = 1616;
static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 88;
static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset =
- 1632;
+ 1648;
static constexpr dart::compiler::target::word
AOT_Thread_field_table_values_offset = 136;
static constexpr dart::compiler::target::word
@@ -12372,11 +12384,11 @@
static constexpr dart::compiler::target::word
AOT_Thread_predefined_symbols_address_offset = 664;
static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset =
- 1552;
+ 1568;
static constexpr dart::compiler::target::word
- AOT_Thread_saved_shadow_call_stack_offset = 1560;
+ AOT_Thread_saved_shadow_call_stack_offset = 1576;
static constexpr dart::compiler::target::word
- AOT_Thread_safepoint_state_offset = 1576;
+ AOT_Thread_safepoint_state_offset = 1592;
static constexpr dart::compiler::target::word
AOT_Thread_slow_type_test_stub_offset = 472;
static constexpr dart::compiler::target::word
@@ -12413,36 +12425,36 @@
AOT_Thread_write_barrier_mask_offset = 72;
static constexpr dart::compiler::target::word AOT_Thread_heap_base_offset = 80;
static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
- 1584;
+ 1600;
static constexpr dart::compiler::target::word
- AOT_Thread_callback_stack_return_offset = 1592;
+ AOT_Thread_callback_stack_return_offset = 1608;
static constexpr dart::compiler::target::word
AOT_TimelineStream_enabled_offset = 16;
static constexpr dart::compiler::target::word AOT_TwoByteString_data_offset =
16;
-static constexpr dart::compiler::target::word AOT_Type_arguments_offset = 24;
-static constexpr dart::compiler::target::word AOT_Type_hash_offset = 28;
+static constexpr dart::compiler::target::word AOT_Type_arguments_offset = 28;
+static constexpr dart::compiler::target::word AOT_Type_hash_offset = 32;
static constexpr dart::compiler::target::word AOT_Type_type_class_id_offset =
- 20;
-static constexpr dart::compiler::target::word AOT_Type_type_state_offset = 32;
-static constexpr dart::compiler::target::word AOT_Type_nullability_offset = 33;
-static constexpr dart::compiler::target::word AOT_FunctionType_hash_offset = 36;
+ 24;
+static constexpr dart::compiler::target::word AOT_Type_type_state_offset = 36;
+static constexpr dart::compiler::target::word AOT_Type_nullability_offset = 37;
+static constexpr dart::compiler::target::word AOT_FunctionType_hash_offset = 40;
static constexpr dart::compiler::target::word
- AOT_FunctionType_packed_parameter_counts_offset = 40;
+ AOT_FunctionType_packed_parameter_counts_offset = 44;
static constexpr dart::compiler::target::word
- AOT_FunctionType_packed_type_parameter_counts_offset = 44;
+ AOT_FunctionType_packed_type_parameter_counts_offset = 48;
static constexpr dart::compiler::target::word
- AOT_FunctionType_parameter_types_offset = 28;
+ AOT_FunctionType_parameter_types_offset = 32;
static constexpr dart::compiler::target::word
- AOT_FunctionType_named_parameter_names_offset = 32;
+ AOT_FunctionType_named_parameter_names_offset = 36;
static constexpr dart::compiler::target::word
- AOT_FunctionType_type_parameters_offset = 20;
+ AOT_FunctionType_type_parameters_offset = 24;
static constexpr dart::compiler::target::word
- AOT_TypeParameter_parameterized_class_id_offset = 28;
+ AOT_TypeParameter_parameterized_class_id_offset = 32;
static constexpr dart::compiler::target::word AOT_TypeParameter_index_offset =
- 31;
+ 35;
static constexpr dart::compiler::target::word
- AOT_TypeParameter_nullability_offset = 33;
+ AOT_TypeParameter_nullability_offset = 37;
static constexpr dart::compiler::target::word
AOT_TypeArguments_instantiations_offset = 8;
static constexpr dart::compiler::target::word AOT_TypeArguments_length_offset =
@@ -12460,16 +12472,16 @@
static constexpr dart::compiler::target::word
AOT_TypeParameters_defaults_offset = 20;
static constexpr dart::compiler::target::word AOT_TypeParameter_bound_offset =
- 24;
+ 28;
static constexpr dart::compiler::target::word AOT_TypeParameter_flags_offset =
- 32;
-static constexpr dart::compiler::target::word AOT_TypeRef_type_offset = 20;
+ 36;
+static constexpr dart::compiler::target::word AOT_TypeRef_type_offset = 24;
static constexpr dart::compiler::target::word AOT_TypedDataBase_length_offset =
- 16;
-static constexpr dart::compiler::target::word AOT_TypedDataView_data_offset =
20;
+static constexpr dart::compiler::target::word AOT_TypedDataView_data_offset =
+ 24;
static constexpr dart::compiler::target::word
- AOT_TypedDataView_offset_in_bytes_offset = 24;
+ AOT_TypedDataView_offset_in_bytes_offset = 28;
static constexpr dart::compiler::target::word AOT_TypedData_data_offset = 24;
static constexpr dart::compiler::target::word
AOT_UnhandledException_exception_offset = 8;
@@ -12489,9 +12501,9 @@
8, 24, 16, 32};
static constexpr dart::compiler::target::word
AOT_Thread_write_barrier_wrappers_thread_offset[] = {
- 1376, 1384, 1392, 1400, 1408, 1416, 1424, 1432, 1440, 1448, 1456,
- 1464, 1472, 1480, 1488, -1, -1, -1, -1, 1496, 1504, -1,
- -1, 1512, 1520, 1528, -1, -1, -1, -1, -1, -1};
+ 1392, 1400, 1408, 1416, 1424, 1432, 1440, 1448, 1456, 1464, 1472,
+ 1480, 1488, 1496, 1504, -1, -1, -1, -1, 1512, 1520, -1,
+ -1, 1528, 1536, 1544, -1, -1, -1, -1, -1, -1};
static constexpr dart::compiler::target::word AOT_AbstractType_InstanceSize =
24;
static constexpr dart::compiler::target::word AOT_ApiError_InstanceSize = 16;
@@ -12521,7 +12533,7 @@
static constexpr dart::compiler::target::word AOT_Float64x2_InstanceSize = 24;
static constexpr dart::compiler::target::word AOT_Function_InstanceSize = 56;
static constexpr dart::compiler::target::word AOT_FunctionType_InstanceSize =
- 48;
+ 56;
static constexpr dart::compiler::target::word AOT_FutureOr_InstanceSize = 16;
static constexpr dart::compiler::target::word
AOT_GrowableObjectArray_InstanceSize = 24;
@@ -12576,7 +12588,7 @@
40;
static constexpr dart::compiler::target::word AOT_TypeParameters_InstanceSize =
24;
-static constexpr dart::compiler::target::word AOT_TypeRef_InstanceSize = 24;
+static constexpr dart::compiler::target::word AOT_TypeRef_InstanceSize = 32;
static constexpr dart::compiler::target::word AOT_TypedData_HeaderSize = 24;
static constexpr dart::compiler::target::word AOT_TypedDataBase_InstanceSize =
24;
diff --git a/runtime/vm/compiler/stub_code_compiler.h b/runtime/vm/compiler/stub_code_compiler.h
index 7b7eb71..a425e97 100644
--- a/runtime/vm/compiler/stub_code_compiler.h
+++ b/runtime/vm/compiler/stub_code_compiler.h
@@ -54,7 +54,8 @@
static void GenerateBuildMethodExtractorStub(
Assembler* assembler,
const Code& closure_allocation_stub,
- const Code& context_allocation_stub);
+ const Code& context_allocation_stub,
+ bool generic);
#endif
static void EnsureIsNewOrRemembered(Assembler* assembler,
@@ -110,7 +111,11 @@
#if defined(TARGET_ARCH_X64)
static constexpr intptr_t kNativeCallbackTrampolineSize = 10;
+#if defined(DART_COMPRESSED_POINTERS)
+ static constexpr intptr_t kNativeCallbackSharedStubSize = 225;
+#else
static constexpr intptr_t kNativeCallbackSharedStubSize = 217;
+#endif
static constexpr intptr_t kNativeCallbackTrampolineStackDelta = 2;
#elif defined(TARGET_ARCH_IA32)
static constexpr intptr_t kNativeCallbackTrampolineSize = 10;
@@ -122,7 +127,11 @@
static constexpr intptr_t kNativeCallbackTrampolineStackDelta = 4;
#elif defined(TARGET_ARCH_ARM64)
static constexpr intptr_t kNativeCallbackTrampolineSize = 12;
+#if defined(DART_COMPRESSED_POINTERS)
+ static constexpr intptr_t kNativeCallbackSharedStubSize = 276;
+#else
static constexpr intptr_t kNativeCallbackSharedStubSize = 268;
+#endif
static constexpr intptr_t kNativeCallbackTrampolineStackDelta = 2;
#endif
diff --git a/runtime/vm/compiler/stub_code_compiler_arm.cc b/runtime/vm/compiler/stub_code_compiler_arm.cc
index 50f9b49..7a139c4 100644
--- a/runtime/vm/compiler/stub_code_compiler_arm.cc
+++ b/runtime/vm/compiler/stub_code_compiler_arm.cc
@@ -224,7 +224,8 @@
void StubCodeCompiler::GenerateBuildMethodExtractorStub(
Assembler* assembler,
const Code& closure_allocation_stub,
- const Code& context_allocation_stub) {
+ const Code& context_allocation_stub,
+ bool generic) {
const intptr_t kReceiverOffset = target::frame_layout.param_end_from_fp + 1;
__ EnterStubFrame();
@@ -291,12 +292,15 @@
FieldAddress(AllocateClosureABI::kResultReg,
target::Closure::instantiator_type_arguments_offset()),
AllocateClosureABI::kScratchReg);
- __ LoadObject(AllocateClosureABI::kScratchReg, EmptyTypeArguments());
- __ StoreIntoObjectNoBarrier(
- AllocateClosureABI::kResultReg,
- FieldAddress(AllocateClosureABI::kResultReg,
- target::Closure::delayed_type_arguments_offset()),
- AllocateClosureABI::kScratchReg);
+ // Keep delayed_type_arguments as null if non-generic (see Closure::New).
+ if (generic) {
+ __ LoadObject(AllocateClosureABI::kScratchReg, EmptyTypeArguments());
+ __ StoreIntoObjectNoBarrier(
+ AllocateClosureABI::kResultReg,
+ FieldAddress(AllocateClosureABI::kResultReg,
+ target::Closure::delayed_type_arguments_offset()),
+ AllocateClosureABI::kScratchReg);
+ }
__ LeaveStubFrame();
// No-op if the two are the same.
@@ -689,13 +693,13 @@
// calling into the runtime.
__ EnterStubFrame();
__ LoadImmediate(R1, 0);
- __ Push(R9); // Preserve cache (guarded CID as Smi).
+ __ Push(R1); // Result slot.
__ Push(R0); // Preserve receiver.
- __ Push(R1);
- __ CallRuntime(kFixCallersTargetMonomorphicRuntimeEntry, 0);
- __ Pop(CODE_REG);
+ __ Push(R9); // Old cache value (also 2nd return value).
+ __ CallRuntime(kFixCallersTargetMonomorphicRuntimeEntry, 2);
+ __ Pop(R9); // Get target cache object.
__ Pop(R0); // Restore receiver.
- __ Pop(R9); // Restore cache (guarded CID as Smi).
+ __ Pop(CODE_REG); // Get target Code object.
// Remove the stub frame.
__ LeaveStubFrame();
// Jump to the dart function.
@@ -3140,20 +3144,13 @@
// proper target for the given name and arguments descriptor. If the
// illegal class id was found, the target is a cache miss handler that can
// be invoked as a normal Dart function.
- const auto target_address = FieldAddress(IP, base + target::kWordSize);
- if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
- __ ldr(
- ARGS_DESC_REG,
- FieldAddress(R9, target::CallSiteData::arguments_descriptor_offset()));
- __ Branch(target_address);
- } else {
- __ ldr(R0, target_address);
+ __ ldr(R0, FieldAddress(IP, base + target::kWordSize));
+ if (!(FLAG_precompiled_mode && FLAG_use_bare_instructions)) {
__ ldr(CODE_REG, FieldAddress(R0, target::Function::code_offset()));
- __ ldr(
- ARGS_DESC_REG,
- FieldAddress(R9, target::CallSiteData::arguments_descriptor_offset()));
- __ Branch(FieldAddress(R0, target::Function::entry_point_offset()));
}
+ __ ldr(ARGS_DESC_REG,
+ FieldAddress(R9, target::CallSiteData::arguments_descriptor_offset()));
+ __ Branch(FieldAddress(R0, target::Function::entry_point_offset()));
// Probe failed, check if it is a miss.
__ Bind(&probe_failed);
@@ -3194,14 +3191,17 @@
__ b(&loop);
__ Bind(&found);
- const intptr_t code_offset =
- target::ICData::CodeIndexFor(1) * target::kWordSize;
- const intptr_t entry_offset =
- target::ICData::EntryPointIndexFor(1) * target::kWordSize;
- if (!(FLAG_precompiled_mode && FLAG_use_bare_instructions)) {
- __ ldr(CODE_REG, Address(R8, code_offset));
+ if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
+ const intptr_t entry_offset =
+ target::ICData::EntryPointIndexFor(1) * target::kWordSize;
+ __ LoadCompressed(R0, Address(R8, entry_offset));
+ __ Branch(FieldAddress(R0, target::Function::entry_point_offset()));
+ } else {
+ const intptr_t code_offset =
+ target::ICData::CodeIndexFor(1) * target::kWordSize;
+ __ LoadCompressed(CODE_REG, Address(R8, code_offset));
+ __ Branch(FieldAddress(CODE_REG, target::Code::entry_point_offset()));
}
- __ Branch(Address(R8, entry_offset));
__ Bind(&miss);
__ LoadIsolate(R2);
diff --git a/runtime/vm/compiler/stub_code_compiler_arm64.cc b/runtime/vm/compiler/stub_code_compiler_arm64.cc
index 1e36ee5..2c1288d 100644
--- a/runtime/vm/compiler/stub_code_compiler_arm64.cc
+++ b/runtime/vm/compiler/stub_code_compiler_arm64.cc
@@ -415,8 +415,8 @@
// Load the code object.
__ LoadFromOffset(R10, THR, compiler::target::Thread::callback_code_offset());
- __ LoadFieldFromOffset(R10, R10,
- compiler::target::GrowableObjectArray::data_offset());
+ __ LoadCompressedFieldFromOffset(
+ R10, R10, compiler::target::GrowableObjectArray::data_offset());
__ LoadCompressed(
R10,
__ ElementAddressForRegIndex(
@@ -460,7 +460,8 @@
void StubCodeCompiler::GenerateBuildMethodExtractorStub(
Assembler* assembler,
const Code& closure_allocation_stub,
- const Code& context_allocation_stub) {
+ const Code& context_allocation_stub,
+ bool generic) {
const intptr_t kReceiverOffset = target::frame_layout.param_end_from_fp + 1;
__ EnterStubFrame();
@@ -530,12 +531,15 @@
FieldAddress(AllocateClosureABI::kResultReg,
target::Closure::instantiator_type_arguments_offset()),
AllocateClosureABI::kScratchReg);
- __ LoadObject(AllocateClosureABI::kScratchReg, EmptyTypeArguments());
- __ StoreCompressedIntoObjectNoBarrier(
- AllocateClosureABI::kResultReg,
- FieldAddress(AllocateClosureABI::kResultReg,
- target::Closure::delayed_type_arguments_offset()),
- AllocateClosureABI::kScratchReg);
+ // Keep delayed_type_arguments as null if non-generic (see Closure::New).
+ if (generic) {
+ __ LoadObject(AllocateClosureABI::kScratchReg, EmptyTypeArguments());
+ __ StoreCompressedIntoObjectNoBarrier(
+ AllocateClosureABI::kResultReg,
+ FieldAddress(AllocateClosureABI::kResultReg,
+ target::Closure::delayed_type_arguments_offset()),
+ AllocateClosureABI::kScratchReg);
+ }
__ LeaveStubFrame();
// No-op if the two are the same.
@@ -804,13 +808,13 @@
// Create a stub frame as we are pushing some objects on the stack before
// calling into the runtime.
__ EnterStubFrame();
- __ Push(R5); // Preserve cache (guarded CID as Smi).
+ __ Push(ZR); // Result slot.
__ Push(R0); // Preserve receiver.
- __ Push(ZR);
- __ CallRuntime(kFixCallersTargetMonomorphicRuntimeEntry, 0);
- __ Pop(CODE_REG);
- __ Pop(R0); // Restore receiver.
- __ Pop(R5); // Restore cache (guarded CID as Smi).
+ __ Push(R5); // Old cache value (also 2nd return value).
+ __ CallRuntime(kFixCallersTargetMonomorphicRuntimeEntry, 2);
+ __ Pop(R5); // Get target cache object.
+ __ Pop(R0); // Restore receiver.
+ __ Pop(CODE_REG); // Get target Code object.
// Remove the stub frame.
__ LeaveStubFrame();
// Jump to the dart function.
@@ -3309,19 +3313,12 @@
// proper target for the given name and arguments descriptor. If the
// illegal class id was found, the target is a cache miss handler that can
// be invoked as a normal Dart function.
- const auto target_address =
- FieldAddress(TMP, base + target::kCompressedWordSize, kObjectBytes);
- if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
- __ ldr(R1, target_address);
- __ ldr(
- ARGS_DESC_REG,
- FieldAddress(R5, target::CallSiteData::arguments_descriptor_offset()));
- } else {
- __ LoadCompressed(R0, target_address);
- __ ldr(R1, FieldAddress(R0, target::Function::entry_point_offset()));
- __ ldr(
- ARGS_DESC_REG,
- FieldAddress(R5, target::CallSiteData::arguments_descriptor_offset()));
+ __ LoadCompressed(
+ R0, FieldAddress(TMP, base + target::kCompressedWordSize, kObjectBytes));
+ __ ldr(R1, FieldAddress(R0, target::Function::entry_point_offset()));
+ __ ldr(ARGS_DESC_REG,
+ FieldAddress(R5, target::CallSiteData::arguments_descriptor_offset()));
+ if (!(FLAG_precompiled_mode && FLAG_use_bare_instructions)) {
__ LoadCompressed(CODE_REG,
FieldAddress(R0, target::Function::code_offset()));
}
@@ -3374,22 +3371,20 @@
__ b(&loop);
__ Bind(&found);
- const intptr_t code_offset =
- target::ICData::CodeIndexFor(1) * target::kCompressedWordSize;
-#if defined(DART_COMPRESSED_POINTERS)
- __ LoadCompressed(CODE_REG,
- Address(R8, code_offset, Address::Offset, kObjectBytes));
- __ ldr(R1, FieldAddress(CODE_REG, target::Code::entry_point_offset()));
- __ br(R1);
-#else
- const intptr_t entry_offset =
- target::ICData::EntryPointIndexFor(1) * target::kCompressedWordSize;
- __ ldr(R1, Address(R8, entry_offset));
- if (!(FLAG_precompiled_mode && FLAG_use_bare_instructions)) {
- __ ldr(CODE_REG, Address(R8, code_offset));
+ if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
+ const intptr_t entry_offset =
+ target::ICData::EntryPointIndexFor(1) * target::kCompressedWordSize;
+ __ LoadCompressed(R1,
+ Address(R8, entry_offset, Address::Offset, kObjectBytes));
+ __ ldr(R1, FieldAddress(R1, target::Function::entry_point_offset()));
+ } else {
+ const intptr_t code_offset =
+ target::ICData::CodeIndexFor(1) * target::kCompressedWordSize;
+ __ LoadCompressed(CODE_REG,
+ Address(R8, code_offset, Address::Offset, kObjectBytes));
+ __ ldr(R1, FieldAddress(CODE_REG, target::Code::entry_point_offset()));
}
__ br(R1);
-#endif
__ Bind(&miss);
__ LoadIsolate(R2);
diff --git a/runtime/vm/compiler/stub_code_compiler_ia32.cc b/runtime/vm/compiler/stub_code_compiler_ia32.cc
index 16ef27a..ea1b6a4 100644
--- a/runtime/vm/compiler/stub_code_compiler_ia32.cc
+++ b/runtime/vm/compiler/stub_code_compiler_ia32.cc
@@ -515,13 +515,13 @@
__ Bind(&monomorphic);
// This was a switchable call.
__ EnterStubFrame();
- __ pushl(ECX); // Preserve cache (guarded CID as Smi).
- __ pushl(EBX); // Preserve receiver.
__ pushl(Immediate(0)); // Result slot.
- __ CallRuntime(kFixCallersTargetMonomorphicRuntimeEntry, 0);
- __ popl(CODE_REG); // Get Code object.
+ __ pushl(EBX); // Preserve receiver.
+ __ pushl(ECX); // Old cache value (also 2nd return value).
+ __ CallRuntime(kFixCallersTargetMonomorphicRuntimeEntry, 2);
+ __ popl(ECX); // Get target cache object.
__ popl(EBX); // Restore receiver.
- __ popl(ECX); // Restore cache (guarded CID as Smi).
+ __ popl(CODE_REG); // Get target Code object.
__ movl(EAX, FieldAddress(CODE_REG, target::Code::entry_point_offset(
CodeEntryKind::kMonomorphic)));
__ LeaveFrame();
diff --git a/runtime/vm/compiler/stub_code_compiler_x64.cc b/runtime/vm/compiler/stub_code_compiler_x64.cc
index e776269..74405e0 100644
--- a/runtime/vm/compiler/stub_code_compiler_x64.cc
+++ b/runtime/vm/compiler/stub_code_compiler_x64.cc
@@ -359,9 +359,10 @@
// Load the target from the thread.
__ movq(TMP, compiler::Address(
THR, compiler::target::Thread::callback_code_offset()));
- __ movq(TMP, compiler::FieldAddress(
- TMP, compiler::target::GrowableObjectArray::data_offset()));
- __ movq(
+ __ LoadCompressed(
+ TMP, compiler::FieldAddress(
+ TMP, compiler::target::GrowableObjectArray::data_offset()));
+ __ LoadCompressed(
TMP,
__ ElementAddressForRegIndex(
/*external=*/false,
@@ -403,7 +404,8 @@
void StubCodeCompiler::GenerateBuildMethodExtractorStub(
Assembler* assembler,
const Code& closure_allocation_stub,
- const Code& context_allocation_stub) {
+ const Code& context_allocation_stub,
+ bool generic) {
const intptr_t kReceiverOffsetInWords =
target::frame_layout.param_end_from_fp + 1;
@@ -471,12 +473,15 @@
FieldAddress(AllocateClosureABI::kResultReg,
target::Closure::instantiator_type_arguments_offset()),
AllocateClosureABI::kScratchReg);
- __ LoadObject(AllocateClosureABI::kScratchReg, EmptyTypeArguments());
- __ StoreCompressedIntoObjectNoBarrier(
- AllocateClosureABI::kResultReg,
- FieldAddress(AllocateClosureABI::kResultReg,
- target::Closure::delayed_type_arguments_offset()),
- AllocateClosureABI::kScratchReg);
+ // Keep delayed_type_arguments as null if non-generic (see Closure::New).
+ if (generic) {
+ __ LoadObject(AllocateClosureABI::kScratchReg, EmptyTypeArguments());
+ __ StoreCompressedIntoObjectNoBarrier(
+ AllocateClosureABI::kResultReg,
+ FieldAddress(AllocateClosureABI::kResultReg,
+ target::Closure::delayed_type_arguments_offset()),
+ AllocateClosureABI::kScratchReg);
+ }
__ LeaveStubFrame();
// No-op if the two are the same.
@@ -721,13 +726,13 @@
__ movq(CODE_REG,
Address(THR, target::Thread::fix_callers_target_code_offset()));
__ EnterStubFrame();
- __ pushq(RBX); // Preserve cache (guarded CID as Smi).
- __ pushq(RDX); // Preserve receiver.
__ pushq(Immediate(0)); // Result slot.
- __ CallRuntime(kFixCallersTargetMonomorphicRuntimeEntry, 0);
- __ popq(CODE_REG); // Get Code object.
+ __ pushq(RDX); // Preserve receiver.
+ __ pushq(RBX); // Old cache value (also 2nd return value).
+ __ CallRuntime(kFixCallersTargetMonomorphicRuntimeEntry, 2);
+ __ popq(RBX); // Get target cache object.
__ popq(RDX); // Restore receiver.
- __ popq(RBX); // Restore cache (guarded CID as Smi).
+ __ popq(CODE_REG); // Get target Code object.
__ movq(RAX, FieldAddress(CODE_REG, target::Code::entry_point_offset(
CodeEntryKind::kMonomorphic)));
__ LeaveStubFrame();
@@ -3251,21 +3256,16 @@
// proper target for the given name and arguments descriptor. If the
// illegal class id was found, the target is a cache miss handler that can
// be invoked as a normal Dart function.
- const auto target_address = FieldAddress(RDI, RCX, TIMES_COMPRESSED_WORD_SIZE,
- base + target::kCompressedWordSize);
- if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
- __ movq(R10, FieldAddress(
- RBX, target::CallSiteData::arguments_descriptor_offset()));
- __ jmp(target_address);
- } else {
- __ LoadCompressed(RAX, target_address);
- __ movq(R10, FieldAddress(
- RBX, target::CallSiteData::arguments_descriptor_offset()));
- __ movq(RCX, FieldAddress(RAX, target::Function::entry_point_offset()));
+ __ LoadCompressed(RAX, FieldAddress(RDI, RCX, TIMES_COMPRESSED_WORD_SIZE,
+ base + target::kCompressedWordSize));
+ __ movq(R10, FieldAddress(
+ RBX, target::CallSiteData::arguments_descriptor_offset()));
+ __ movq(RCX, FieldAddress(RAX, target::Function::entry_point_offset()));
+ if (!(FLAG_precompiled_mode && FLAG_use_bare_instructions)) {
__ LoadCompressed(CODE_REG,
FieldAddress(RAX, target::Function::code_offset()));
- __ jmp(RCX);
}
+ __ jmp(RCX);
// Probe failed, check if it is a miss.
__ Bind(&probe_failed);
@@ -3316,19 +3316,17 @@
__ jmp(&loop);
__ Bind(&found);
- const intptr_t code_offset =
- target::ICData::CodeIndexFor(1) * target::kCompressedWordSize;
-#if defined(DART_COMPRESSED_POINTERS)
- __ LoadCompressed(CODE_REG, Address(R13, code_offset));
- __ jmp(FieldAddress(CODE_REG, target::Code::entry_point_offset()));
-#else
- const intptr_t entry_offset =
- target::ICData::EntryPointIndexFor(1) * target::kCompressedWordSize;
- if (!(FLAG_precompiled_mode && FLAG_use_bare_instructions)) {
- __ movq(CODE_REG, Address(R13, code_offset));
+ if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
+ const intptr_t entry_offset =
+ target::ICData::EntryPointIndexFor(1) * target::kCompressedWordSize;
+ __ LoadCompressed(RCX, Address(R13, entry_offset));
+ __ jmp(FieldAddress(RCX, target::Function::entry_point_offset()));
+ } else {
+ const intptr_t code_offset =
+ target::ICData::CodeIndexFor(1) * target::kCompressedWordSize;
+ __ LoadCompressed(CODE_REG, Address(R13, code_offset));
+ __ jmp(FieldAddress(CODE_REG, target::Code::entry_point_offset()));
}
- __ jmp(Address(R13, entry_offset));
-#endif
__ Bind(&miss);
__ LoadIsolate(RAX);
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index 2fbb323..a3e59b2 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -301,6 +301,7 @@
vm_isolate_->isolate_object_store()->Init();
TargetCPUFeatures::Init();
Object::Init(vm_isolate_->group());
+ OffsetsTable::Init();
ArgumentsDescriptor::Init();
ICData::Init();
SubtypeTestCache::Init();
@@ -635,6 +636,7 @@
ICData::Cleanup();
SubtypeTestCache::Cleanup();
ArgumentsDescriptor::Cleanup();
+ OffsetsTable::Cleanup();
TargetCPUFeatures::Cleanup();
MarkingStack::Cleanup();
StoreBuffer::Cleanup();
@@ -869,16 +871,32 @@
if (kIsAotRuntime || was_child_cloned_into_existing_isolate) {
#if !defined(TARGET_ARCH_IA32)
- ASSERT(IG->object_store()->build_method_extractor_code() != Code::null());
+ ASSERT(IG->object_store()->build_generic_method_extractor_code() !=
+ Code::null());
+ ASSERT(IG->object_store()->build_nongeneric_method_extractor_code() !=
+ Code::null());
#endif
} else {
#if !defined(TARGET_ARCH_IA32)
if (I != Dart::vm_isolate()) {
- if (IG->object_store()->build_method_extractor_code() != nullptr) {
+ if (IG->object_store()->build_generic_method_extractor_code() !=
+ nullptr) {
SafepointWriteRwLocker ml(T, IG->program_lock());
- if (IG->object_store()->build_method_extractor_code() != nullptr) {
- IG->object_store()->set_build_method_extractor_code(
- Code::Handle(StubCode::GetBuildMethodExtractorStub(nullptr)));
+ if (IG->object_store()->build_generic_method_extractor_code() !=
+ nullptr) {
+ IG->object_store()->set_build_generic_method_extractor_code(
+ Code::Handle(
+ StubCode::GetBuildGenericMethodExtractorStub(nullptr)));
+ }
+ }
+ if (IG->object_store()->build_nongeneric_method_extractor_code() !=
+ nullptr) {
+ SafepointWriteRwLocker ml(T, IG->program_lock());
+ if (IG->object_store()->build_nongeneric_method_extractor_code() !=
+ nullptr) {
+ IG->object_store()->set_build_nongeneric_method_extractor_code(
+ Code::Handle(
+ StubCode::GetBuildNonGenericMethodExtractorStub(nullptr)));
}
}
}
diff --git a/runtime/vm/dart.h b/runtime/vm/dart.h
index fa95787..b0776be 100644
--- a/runtime/vm/dart.h
+++ b/runtime/vm/dart.h
@@ -8,6 +8,7 @@
#include "include/dart_api.h"
#include "include/dart_tools_api.h"
#include "vm/allocation.h"
+#include "vm/isolate.h"
#include "vm/snapshot.h"
namespace dart {
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 4b03928..86cd097 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -32,6 +32,7 @@
#include "vm/lockers.h"
#include "vm/message.h"
#include "vm/message_handler.h"
+#include "vm/message_snapshot.h"
#include "vm/native_entry.h"
#include "vm/native_symbol.h"
#include "vm/object.h"
@@ -1453,16 +1454,14 @@
*error = nullptr;
- if (!IsolateGroup::AreIsolateGroupsEnabled()) {
+ if (!FLAG_enable_isolate_groups) {
*error = Utils::StrDup(
- "Lightweight isolates are only implemented in AOT "
- "mode and need to be explicitly enabled by passing "
+ "Lightweight isolates need to be explicitly enabled by passing "
"--enable-isolate-groups.");
return nullptr;
}
Isolate* isolate;
-#if defined(DART_PRECOMPILED_RUNTIME)
isolate = CreateWithinExistingIsolateGroup(member->group(), name, error);
if (isolate != nullptr) {
isolate->set_origin_id(member->origin_id());
@@ -1470,10 +1469,6 @@
isolate->set_on_shutdown_callback(shutdown_callback);
isolate->set_on_cleanup_callback(cleanup_callback);
}
-#else
- *error = Utils::StrDup("Lightweight isolates are not yet ready in JIT mode.");
- isolate = nullptr;
-#endif
return Api::CastIsolate(isolate);
}
@@ -2167,17 +2162,10 @@
return false;
}
- // Smis and null can be sent without serialization.
- ObjectPtr raw_obj = Api::UnwrapHandle(handle);
- if (ApiObjectConverter::CanConvert(raw_obj)) {
- return PortMap::PostMessage(
- Message::New(port_id, raw_obj, Message::kNormalPriority));
- }
-
- const Object& object = Object::Handle(Z, raw_obj);
- MessageWriter writer(false);
- return PortMap::PostMessage(
- writer.WriteMessage(object, port_id, Message::kNormalPriority));
+ const Object& object = Object::Handle(Z, Api::UnwrapHandle(handle));
+ return PortMap::PostMessage(WriteMessage(/* can_send_any_object */ false,
+ object, port_id,
+ Message::kNormalPriority));
}
DART_EXPORT Dart_Handle Dart_NewSendPort(Dart_Port port_id) {
@@ -6169,10 +6157,6 @@
return ServiceIsolate::IsServiceIsolate(iso);
}
-DART_EXPORT int64_t Dart_TimelineGetMicros() {
- return OS::GetCurrentMonotonicMicros();
-}
-
DART_EXPORT void Dart_RegisterIsolateServiceRequestCallback(
const char* name,
Dart_ServiceRequestCallback callback,
@@ -6314,6 +6298,18 @@
#endif
}
+DART_EXPORT int64_t Dart_TimelineGetMicros() {
+ return OS::GetCurrentMonotonicMicros();
+}
+
+DART_EXPORT int64_t Dart_TimelineGetTicks() {
+ return OS::GetCurrentMonotonicTicks();
+}
+
+DART_EXPORT int64_t Dart_TimelineGetTicksFrequency() {
+ return OS::GetCurrentMonotonicFrequency();
+}
+
DART_EXPORT void Dart_GlobalTimelineSetRecordedStreams(int64_t stream_mask) {
#if defined(SUPPORT_TIMELINE)
const bool api_enabled = (stream_mask & DART_TIMELINE_STREAM_API) != 0;
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index 6f116a0..b61e6c2 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -4166,6 +4166,61 @@
EXPECT_VALID(Dart_Invoke(lib, NewString("main"), 0, NULL));
}
+void FUNCTION_NAME(SecretKeeper_KeepSecret)(Dart_NativeArguments native_args) {
+ Dart_Handle receiver = Dart_GetNativeArgument(native_args, 0);
+ int64_t secret = 0;
+ Dart_GetNativeIntegerArgument(native_args, 1, &secret);
+ EXPECT_VALID(Dart_SetNativeInstanceField(receiver, 0, secret));
+}
+
+static Dart_NativeFunction SecretKeeperNativeResolver(Dart_Handle name,
+ int argument_count,
+ bool* auto_setup_scope) {
+ return reinterpret_cast<Dart_NativeFunction>(Builtin_SecretKeeper_KeepSecret);
+}
+
+TEST_CASE(DartAPI_NativeFieldAccess) {
+ const char* kScriptChars = R"(
+ import 'dart:nativewrappers';
+ class SecretKeeper extends NativeFieldWrapperClass1 {
+ SecretKeeper(int secret) { _keepSecret(secret); }
+ void _keepSecret(int secret) native "SecretKeeper_KeepSecret";
+ }
+ main() => getNativeField(SecretKeeper(321));
+ )";
+
+ Dart_Handle result;
+ Dart_Handle lib =
+ TestCase::LoadTestScript(kScriptChars, SecretKeeperNativeResolver);
+ result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
+
+ EXPECT_VALID(result);
+ EXPECT(Dart_IsInteger(result));
+ int64_t value = 0;
+ result = Dart_IntegerToInt64(result, &value);
+ EXPECT_VALID(result);
+ EXPECT_EQ(321, value);
+}
+
+TEST_CASE(DartAPI_NativeFieldAccess_Throws) {
+ const char* kScriptChars = R"(
+ import 'dart:nativewrappers';
+ class ForgetfulSecretKeeper extends NativeFieldWrapperClass1 {
+ ForgetfulSecretKeeper(int secret) { /* Forget to init. native field. */ }
+ }
+ main() => getNativeField(ForgetfulSecretKeeper(321));
+ )";
+
+ Dart_Handle result;
+ Dart_Handle lib =
+ TestCase::LoadTestScript(kScriptChars, SecretKeeperNativeResolver);
+
+ result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
+
+ EXPECT(Dart_IsError(result));
+ EXPECT(Dart_IsUnhandledExceptionError(result));
+}
+
static Dart_WeakPersistentHandle weak1 = NULL;
static Dart_WeakPersistentHandle weak2 = NULL;
static Dart_WeakPersistentHandle weak3 = NULL;
@@ -9082,6 +9137,19 @@
EXPECT_SUBSTRING("testAsyncEvent", js.ToCString());
}
+TEST_CASE(DartAPI_TimelineClock) {
+ int64_t micros1 = Dart_TimelineGetMicros();
+ int64_t ticks1 = Dart_TimelineGetTicks();
+ int64_t frequency1 = Dart_TimelineGetTicksFrequency();
+ OS::Sleep(1);
+ int64_t micros2 = Dart_TimelineGetMicros();
+ int64_t ticks2 = Dart_TimelineGetTicks();
+ int64_t frequency2 = Dart_TimelineGetTicksFrequency();
+ EXPECT_NE(micros1, micros2);
+ EXPECT_NE(ticks1, ticks2);
+ EXPECT_EQ(frequency1, frequency2);
+}
+
static void HintFreedNative(Dart_NativeArguments args) {
int64_t size = 0;
EXPECT_VALID(Dart_GetNativeIntegerArgument(args, 0, &size));
@@ -9305,7 +9373,7 @@
TEST_CASE(Dart_SetFfiNativeResolver) {
const char* kScriptChars = R"(
import 'dart:ffi';
- @FfiNative<IntPtr Function(Double)>('EchoInt')
+ @FfiNative<IntPtr Function(Double)>('EchoInt', isLeaf:true)
external int echoInt(double x);
main() => echoInt(7.0);
)";
@@ -9327,7 +9395,7 @@
TEST_CASE(Dart_SetFfiNativeResolver_MissingResolver) {
const char* kScriptChars = R"(
import 'dart:ffi';
- @FfiNative<IntPtr Function(Double)>('EchoInt')
+ @FfiNative<IntPtr Function(Double)>('EchoInt', isLeaf:true)
external int echoInt(double x);
main() => echoInt(7.0);
)";
diff --git a/runtime/vm/dart_api_message.cc b/runtime/vm/dart_api_message.cc
deleted file mode 100644
index 73df245..0000000
--- a/runtime/vm/dart_api_message.cc
+++ /dev/null
@@ -1,1192 +0,0 @@
-// Copyright (c) 2012, 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.
-
-#include <memory>
-
-#include "vm/dart_api_message.h"
-
-#include "platform/undefined_behavior_sanitizer.h"
-#include "platform/unicode.h"
-#include "vm/object.h"
-#include "vm/snapshot_ids.h"
-#include "vm/symbols.h"
-
-namespace dart {
-
-static const int kNumInitialReferences = 4;
-
-ApiMessageReader::ApiMessageReader(Message* msg)
- : BaseReader(msg->IsRaw() ? reinterpret_cast<uint8_t*>(
- static_cast<uword>(msg->raw_obj()))
- : msg->snapshot(),
- msg->snapshot_length()),
- zone_(NULL),
- backward_references_(kNumInitialReferences),
- vm_isolate_references_(kNumInitialReferences),
- vm_symbol_references_(NULL),
- finalizable_data_(msg->finalizable_data()) {}
-
-ApiMessageReader::~ApiMessageReader() {}
-
-void ApiMessageReader::Init() {
- // We need to have an enclosing ApiNativeScope.
- ASSERT(ApiNativeScope::Current() != NULL);
- zone_ = ApiNativeScope::Current()->zone();
- ASSERT(zone_ != NULL);
-
- // Initialize marker objects used to handle Lists.
- // TODO(sjesse): Remove this when message serialization format is
- // updated.
- memset(&type_arguments_marker, 0, sizeof(type_arguments_marker));
- memset(&dynamic_type_marker, 0, sizeof(dynamic_type_marker));
- type_arguments_marker.type =
- static_cast<Dart_CObject_Type>(Dart_CObject_Internal::kTypeArguments);
- dynamic_type_marker.type =
- static_cast<Dart_CObject_Type>(Dart_CObject_Internal::kDynamicType);
-}
-
-Dart_CObject* ApiMessageReader::ReadMessage() {
- Init();
- if (PendingBytes() > 0) {
- // Read the object out of the message.
- return ReadObject();
- } else {
- const ObjectPtr raw_obj = static_cast<const ObjectPtr>(
- reinterpret_cast<uword>(CurrentBufferAddress()));
- ASSERT(ApiObjectConverter::CanConvert(raw_obj));
- Dart_CObject* cobj =
- reinterpret_cast<Dart_CObject*>(allocator(sizeof(Dart_CObject)));
- ApiObjectConverter::Convert(raw_obj, cobj);
- return cobj;
- }
-}
-
-intptr_t ApiMessageReader::LookupInternalClass(intptr_t class_header) {
- if (IsVMIsolateObject(class_header)) {
- return GetVMIsolateObjectId(class_header);
- }
- ASSERT(SerializedHeaderTag::decode(class_header) == kObjectId);
- return SerializedHeaderData::decode(class_header);
-}
-
-Dart_CObject* ApiMessageReader::AllocateDartCObject(Dart_CObject_Type type) {
- Dart_CObject* value =
- reinterpret_cast<Dart_CObject*>(allocator(sizeof(Dart_CObject)));
- ASSERT(value != NULL);
- value->type = type;
- return value;
-}
-
-Dart_CObject* ApiMessageReader::AllocateDartCObjectUnsupported() {
- return AllocateDartCObject(Dart_CObject_kUnsupported);
-}
-
-Dart_CObject* ApiMessageReader::AllocateDartCObjectNull() {
- return AllocateDartCObject(Dart_CObject_kNull);
-}
-
-Dart_CObject* ApiMessageReader::AllocateDartCObjectBool(bool val) {
- Dart_CObject* value = AllocateDartCObject(Dart_CObject_kBool);
- value->value.as_bool = val;
- return value;
-}
-
-Dart_CObject* ApiMessageReader::AllocateDartCObjectInt32(int32_t val) {
- Dart_CObject* value = AllocateDartCObject(Dart_CObject_kInt32);
- value->value.as_int32 = val;
- return value;
-}
-
-Dart_CObject* ApiMessageReader::AllocateDartCObjectInt64(int64_t val) {
- Dart_CObject* value = AllocateDartCObject(Dart_CObject_kInt64);
- value->value.as_int64 = val;
- return value;
-}
-
-Dart_CObject* ApiMessageReader::AllocateDartCObjectDouble(double val) {
- Dart_CObject* value = AllocateDartCObject(Dart_CObject_kDouble);
- value->value.as_double = val;
- return value;
-}
-
-Dart_CObject* ApiMessageReader::AllocateDartCObjectString(intptr_t length) {
- // Allocate a Dart_CObject structure followed by an array of chars
- // for the string content. The pointer to the string content is set
- // up to this area.
- Dart_CObject* value = reinterpret_cast<Dart_CObject*>(
- allocator(sizeof(Dart_CObject) + length + 1));
- ASSERT(value != NULL);
- value->value.as_string = reinterpret_cast<char*>(value) + sizeof(*value);
- value->type = Dart_CObject_kString;
- return value;
-}
-
-static int GetTypedDataSizeInBytes(Dart_TypedData_Type type) {
- switch (type) {
- case Dart_TypedData_kInt8:
- case Dart_TypedData_kUint8:
- case Dart_TypedData_kUint8Clamped:
- return 1;
- case Dart_TypedData_kInt16:
- case Dart_TypedData_kUint16:
- return 2;
- case Dart_TypedData_kInt32:
- case Dart_TypedData_kUint32:
- case Dart_TypedData_kFloat32:
- return 4;
- case Dart_TypedData_kInt64:
- case Dart_TypedData_kUint64:
- case Dart_TypedData_kFloat64:
- return 8;
- case Dart_TypedData_kInt32x4:
- case Dart_TypedData_kFloat32x4:
- case Dart_TypedData_kFloat64x2:
- return 16;
- default:
- break;
- }
- UNREACHABLE();
- return -1;
-}
-
-Dart_CObject* ApiMessageReader::AllocateDartCObjectTypedData(
- Dart_TypedData_Type type,
- intptr_t length) {
- // Allocate a Dart_CObject structure followed by an array of bytes
- // for the byte array content. The pointer to the byte array content
- // is set up to this area.
- intptr_t length_in_bytes = GetTypedDataSizeInBytes(type) * length;
- Dart_CObject* value = reinterpret_cast<Dart_CObject*>(
- allocator(sizeof(Dart_CObject) + length_in_bytes));
- ASSERT(value != NULL);
- value->type = Dart_CObject_kTypedData;
- value->value.as_typed_data.type = type;
- value->value.as_typed_data.length = length_in_bytes;
- if (length > 0) {
- value->value.as_typed_data.values =
- reinterpret_cast<uint8_t*>(value) + sizeof(*value);
- } else {
- value->value.as_typed_data.values = NULL;
- }
- return value;
-}
-
-Dart_CObject* ApiMessageReader::AllocateDartCObjectArray(intptr_t length) {
- // Allocate a Dart_CObject structure followed by an array of
- // pointers to Dart_CObject structures. The pointer to the array
- // content is set up to this area.
- Dart_CObject* value = reinterpret_cast<Dart_CObject*>(
- allocator(sizeof(Dart_CObject) + length * sizeof(value)));
- ASSERT(value != NULL);
- value->type = Dart_CObject_kArray;
- value->value.as_array.length = length;
- if (length > 0) {
- value->value.as_array.values = reinterpret_cast<Dart_CObject**>(value + 1);
- } else {
- value->value.as_array.values = NULL;
- }
- return value;
-}
-
-Dart_CObject* ApiMessageReader::AllocateDartCObjectVmIsolateObj(intptr_t id) {
- ObjectPtr raw = VmIsolateSnapshotObject(id);
- intptr_t cid = raw->GetClassId();
- switch (cid) {
- case kOneByteStringCid: {
- OneByteStringPtr raw_str = static_cast<OneByteStringPtr>(raw);
- const char* str = reinterpret_cast<const char*>(raw_str->untag()->data());
- ASSERT(str != NULL);
- Dart_CObject* object = NULL;
- for (intptr_t i = 0; i < vm_isolate_references_.length(); i++) {
- object = vm_isolate_references_.At(i);
- if (object->type == Dart_CObject_kString) {
- if (strcmp(str, object->value.as_string) == 0) {
- return object;
- }
- }
- }
- object = CreateDartCObjectString(raw);
- vm_isolate_references_.Add(object);
- return object;
- }
-
- case kMintCid: {
- const Mint& obj = Mint::Handle(static_cast<MintPtr>(raw));
- int64_t value64 = obj.value();
- if ((kMinInt32 <= value64) && (value64 <= kMaxInt32)) {
- return GetCanonicalMintObject(Dart_CObject_kInt32, value64);
- } else {
- return GetCanonicalMintObject(Dart_CObject_kInt64, value64);
- }
- }
-
- default:
- UNREACHABLE();
- return NULL;
- }
-}
-
-Dart_CObject_Internal* ApiMessageReader::AllocateDartCObjectInternal(
- Dart_CObject_Internal::Type type) {
- Dart_CObject_Internal* value = reinterpret_cast<Dart_CObject_Internal*>(
- allocator(sizeof(Dart_CObject_Internal)));
- ASSERT(value != NULL);
- value->type = static_cast<Dart_CObject_Type>(type);
- return value;
-}
-
-Dart_CObject_Internal* ApiMessageReader::AllocateDartCObjectClass() {
- return AllocateDartCObjectInternal(Dart_CObject_Internal::kClass);
-}
-
-ApiMessageReader::BackRefNode* ApiMessageReader::AllocateBackRefNode(
- Dart_CObject* reference,
- DeserializeState state) {
- BackRefNode* value =
- reinterpret_cast<BackRefNode*>(allocator(sizeof(BackRefNode)));
- value->set_reference(reference);
- value->set_state(state);
- return value;
-}
-
-Dart_CObject* ApiMessageReader::ReadInlinedObject(intptr_t object_id) {
- // Read the class header information and lookup the class.
- intptr_t class_header = Read<int32_t>();
- intptr_t tags = ReadTags();
- USE(tags);
- intptr_t class_id;
-
- // There is limited support for reading regular dart instances. Only
- // typed data views are currently handled.
- if (SerializedHeaderData::decode(class_header) == kInstanceObjectId) {
- Dart_CObject_Internal* object =
- reinterpret_cast<Dart_CObject_Internal*>(GetBackRef(object_id));
- if (object == NULL) {
- object =
- AllocateDartCObjectInternal(Dart_CObject_Internal::kUninitialized);
- AddBackRef(object_id, object, kIsDeserialized);
- // Read class of object.
- object->cls = reinterpret_cast<Dart_CObject_Internal*>(ReadObjectImpl());
- ASSERT(object->cls->type ==
- static_cast<Dart_CObject_Type>(Dart_CObject_Internal::kClass));
- }
- ASSERT(object->type == static_cast<Dart_CObject_Type>(
- Dart_CObject_Internal::kUninitialized));
- return object;
- }
-
- ASSERT((class_header & kSmiTagMask) != 0);
- class_id = LookupInternalClass(class_header);
- if ((class_id == kArrayCid) || (class_id == kImmutableArrayCid)) {
- intptr_t len = ReadSmiValue();
- Dart_CObject* value = GetBackRef(object_id);
- if (value == NULL) {
- value = AllocateDartCObjectArray(len);
- AddBackRef(object_id, value, kIsDeserialized);
- }
- // Skip type arguments.
- // TODO(sjesse): Remove this when message serialization format is
- // updated (currently type_arguments is leaked).
- Dart_CObject* type_arguments = ReadObjectImpl();
- if (type_arguments != &type_arguments_marker &&
- type_arguments->type != Dart_CObject_kNull) {
- return AllocateDartCObjectUnsupported();
- }
- for (int i = 0; i < len; i++) {
- value->value.as_array.values[i] = ReadObjectRef();
- }
- return value;
- }
-
- return ReadInternalVMObject(class_id, object_id);
-}
-
-Dart_CObject* ApiMessageReader::ReadPredefinedSymbol(intptr_t object_id) {
- ASSERT(Symbols::IsPredefinedSymbolId(object_id));
- intptr_t symbol_id = object_id - kMaxPredefinedObjectIds;
- Dart_CObject* object;
- if (vm_symbol_references_ != NULL &&
- (object = vm_symbol_references_[symbol_id]) != NULL) {
- return object;
- }
-
- if (vm_symbol_references_ == NULL) {
- intptr_t size =
- (sizeof(*vm_symbol_references_) * Symbols::kMaxPredefinedId);
- vm_symbol_references_ = reinterpret_cast<Dart_CObject**>(allocator(size));
- memset(vm_symbol_references_, 0, size);
- }
-
- object = CreateDartCObjectString(Symbols::GetPredefinedSymbol(object_id));
- ASSERT(vm_symbol_references_[symbol_id] == NULL);
- vm_symbol_references_[symbol_id] = object;
- return object;
-}
-
-intptr_t ApiMessageReader::NextAvailableObjectId() const {
- return backward_references_.length() + kMaxPredefinedObjectIds;
-}
-
-Dart_CObject* ApiMessageReader::CreateDartCObjectString(ObjectPtr raw) {
- ASSERT(IsOneByteStringClassId(raw->GetClassId()));
- OneByteStringPtr raw_str = static_cast<OneByteStringPtr>(raw);
- intptr_t len = Smi::Value(raw_str->untag()->length());
- Dart_CObject* object = AllocateDartCObjectString(len);
- char* p = object->value.as_string;
- memmove(p, raw_str->untag()->data(), len);
- p[len] = '\0';
- return object;
-}
-
-Dart_CObject* ApiMessageReader::GetCanonicalMintObject(Dart_CObject_Type type,
- int64_t value64) {
- Dart_CObject* object = NULL;
- for (intptr_t i = 0; i < vm_isolate_references_.length(); i++) {
- object = vm_isolate_references_.At(i);
- if (object->type == type) {
- if (value64 == object->value.as_int64) {
- return object;
- }
- }
- }
- if (type == Dart_CObject_kInt32) {
- object = AllocateDartCObjectInt32(static_cast<int32_t>(value64));
- } else {
- object = AllocateDartCObjectInt64(value64);
- }
- vm_isolate_references_.Add(object);
- return object;
-}
-
-Dart_CObject* ApiMessageReader::ReadObjectRef() {
- int64_t value64 = Read<int64_t>();
- if ((value64 & kSmiTagMask) == 0) {
- int64_t untagged_value = value64 >> kSmiTagShift;
- if ((kMinInt32 <= untagged_value) && (untagged_value <= kMaxInt32)) {
- return AllocateDartCObjectInt32(static_cast<int32_t>(untagged_value));
- } else {
- return AllocateDartCObjectInt64(untagged_value);
- }
- }
- ASSERT((value64 <= kIntptrMax) && (value64 >= kIntptrMin));
- intptr_t value = static_cast<intptr_t>(value64);
- if (IsVMIsolateObject(value)) {
- return ReadVMIsolateObject(value);
- }
- if (SerializedHeaderTag::decode(value) == kObjectId) {
- return ReadIndexedObject(SerializedHeaderData::decode(value));
- }
- ASSERT(SerializedHeaderTag::decode(value) == kInlined);
- // Read the class header information and lookup the class.
- intptr_t class_header = Read<int32_t>();
-
- intptr_t object_id = SerializedHeaderData::decode(value);
- if (object_id == kOmittedObjectId) {
- object_id = NextAvailableObjectId();
- }
-
- intptr_t tags = ReadTags();
- USE(tags);
-
- // Reading of regular dart instances has limited support in order to
- // read typed data views.
- if (SerializedHeaderData::decode(class_header) == kInstanceObjectId) {
- Dart_CObject_Internal* object =
- AllocateDartCObjectInternal(Dart_CObject_Internal::kUninitialized);
- AddBackRef(object_id, object, kIsNotDeserialized);
- // Read class of object.
- object->cls = reinterpret_cast<Dart_CObject_Internal*>(ReadObjectImpl());
- ASSERT(object->cls->type ==
- static_cast<Dart_CObject_Type>(Dart_CObject_Internal::kClass));
- return object;
- }
- ASSERT((class_header & kSmiTagMask) != 0);
- intptr_t class_id = LookupInternalClass(class_header);
- if ((class_id == kArrayCid) || (class_id == kImmutableArrayCid)) {
- ASSERT(GetBackRef(object_id) == NULL);
- intptr_t len = ReadSmiValue();
- Dart_CObject* value = AllocateDartCObjectArray(len);
- AddBackRef(object_id, value, kIsNotDeserialized);
- return value;
- }
- return ReadInternalVMObject(class_id, object_id);
-}
-
-Dart_CObject* ApiMessageReader::ReadVMIsolateObject(intptr_t value) {
- intptr_t object_id = GetVMIsolateObjectId(value);
- if (object_id == kNullObject) {
- return AllocateDartCObjectNull();
- }
- if (object_id == kTrueValue) {
- return AllocateDartCObjectBool(true);
- }
- if (object_id == kFalseValue) {
- return AllocateDartCObjectBool(false);
- }
- if (object_id == kDoubleObject) {
- return AllocateDartCObjectDouble(ReadDouble());
- }
- if (Symbols::IsPredefinedSymbolId(object_id)) {
- return ReadPredefinedSymbol(object_id);
- }
- // No other VM isolate objects are supported.
- return AllocateDartCObjectNull();
-}
-
-Dart_CObject* ApiMessageReader::ReadInternalVMObject(intptr_t class_id,
- intptr_t object_id) {
- switch (class_id) {
- case kClassCid: {
- Dart_CObject_Internal* object = AllocateDartCObjectClass();
- AddBackRef(object_id, object, kIsDeserialized);
- object->internal.as_class.library_url = ReadObjectImpl();
- ASSERT(object->internal.as_class.library_url->type ==
- Dart_CObject_kString);
- object->internal.as_class.class_name = ReadObjectImpl();
- ASSERT(object->internal.as_class.class_name->type ==
- Dart_CObject_kString);
- return object;
- }
- case kTypeArgumentsCid: {
- // TODO(sjesse): Remove this when message serialization format is
- // updated (currently length is leaked).
- Dart_CObject* value = &type_arguments_marker;
- AddBackRef(object_id, value, kIsDeserialized);
- Dart_CObject* length = ReadObjectImpl();
- ASSERT(length->type == Dart_CObject_kInt32);
- // The instantiations_ field is only written to a full snapshot.
- for (int i = 0; i < length->value.as_int32; i++) {
- Dart_CObject* type = ReadObjectImpl();
- if (type != &dynamic_type_marker) {
- return AllocateDartCObjectUnsupported();
- }
- }
- return value;
- }
- case kTypeParameterCid: {
- Dart_CObject* value = &dynamic_type_marker;
- AddBackRef(object_id, value, kIsDeserialized);
- intptr_t index = Read<int32_t>();
- USE(index);
- intptr_t token_index = Read<int32_t>();
- USE(token_index);
- int8_t type_state = Read<int8_t>();
- USE(type_state);
- Dart_CObject* parameterized_class = ReadObjectImpl();
- // The type parameter is finalized, therefore parameterized_class is null.
- ASSERT(parameterized_class->type == Dart_CObject_kNull);
- Dart_CObject* name = ReadObjectImpl();
- ASSERT(name->type == Dart_CObject_kString);
- return value;
- }
- case kMintCid: {
- int64_t value64 = Read<int64_t>();
- Dart_CObject* object;
- if ((kMinInt32 <= value64) && (value64 <= kMaxInt32)) {
- object = AllocateDartCObjectInt32(static_cast<int32_t>(value64));
- } else {
- object = AllocateDartCObjectInt64(value64);
- }
- AddBackRef(object_id, object, kIsDeserialized);
- return object;
- }
- case kDoubleCid: {
- // Doubles are handled specially when being sent as part of message
- // snapshots.
- UNREACHABLE();
- }
- case kOneByteStringCid: {
- intptr_t len = ReadSmiValue();
- uint8_t* latin1 =
- reinterpret_cast<uint8_t*>(allocator(len * sizeof(uint8_t)));
- intptr_t utf8_len = 0;
- for (intptr_t i = 0; i < len; i++) {
- latin1[i] = Read<uint8_t>();
- utf8_len += Utf8::Length(latin1[i]);
- }
- Dart_CObject* object = AllocateDartCObjectString(utf8_len);
- AddBackRef(object_id, object, kIsDeserialized);
- char* p = object->value.as_string;
- for (intptr_t i = 0; i < len; i++) {
- p += Utf8::Encode(latin1[i], p);
- }
- *p = '\0';
- ASSERT(p == (object->value.as_string + utf8_len));
- return object;
- }
- case kTwoByteStringCid: {
- intptr_t len = ReadSmiValue();
- uint16_t* utf16 =
- reinterpret_cast<uint16_t*>(allocator(len * sizeof(uint16_t)));
- intptr_t utf8_len = 0;
- // Read all the UTF-16 code units.
- for (intptr_t i = 0; i < len; i++) {
- utf16[i] = Read<uint16_t>();
- }
- // Calculate the UTF-8 length and check if the string can be
- // UTF-8 encoded.
- bool valid = true;
- intptr_t i = 0;
- while (i < len && valid) {
- int32_t ch = Utf16::Next(utf16, &i, len);
- utf8_len += Utf8::Length(ch);
- valid = !Utf16::IsSurrogate(ch);
- }
- if (!valid) {
- return AllocateDartCObjectUnsupported();
- }
- Dart_CObject* object = AllocateDartCObjectString(utf8_len);
- AddBackRef(object_id, object, kIsDeserialized);
- char* p = object->value.as_string;
- i = 0;
- while (i < len) {
- p += Utf8::Encode(Utf16::Next(utf16, &i, len), p);
- }
- *p = '\0';
- ASSERT(p == (object->value.as_string + utf8_len));
- return object;
- }
- case kSendPortCid: {
- int64_t value64 = Read<int64_t>();
- int64_t originId = Read<uint64_t>();
- Dart_CObject* object = AllocateDartCObject(Dart_CObject_kSendPort);
- object->value.as_send_port.id = value64;
- object->value.as_send_port.origin_id = originId;
- AddBackRef(object_id, object, kIsDeserialized);
- return object;
- }
- case kCapabilityCid: {
- int64_t id = Read<int64_t>();
- Dart_CObject* object = AllocateDartCObject(Dart_CObject_kCapability);
- object->value.as_capability.id = id;
- AddBackRef(object_id, object, kIsDeserialized);
- return object;
- }
-
-#define READ_TYPED_DATA(tname, ctype) \
- { \
- intptr_t len = ReadSmiValue(); \
- auto type = Dart_TypedData_k##tname; \
- intptr_t length_in_bytes = GetTypedDataSizeInBytes(type) * len; \
- Dart_CObject* object = \
- reinterpret_cast<Dart_CObject*>(allocator(sizeof(Dart_CObject))); \
- ASSERT(object != NULL); \
- object->type = Dart_CObject_kTypedData; \
- object->value.as_typed_data.type = type; \
- object->value.as_typed_data.length = length_in_bytes; \
- if (len > 0) { \
- Align(Zone::kAlignment); \
- object->value.as_typed_data.values = \
- const_cast<uint8_t*>(CurrentBufferAddress()); \
- Advance(length_in_bytes); \
- } else { \
- object->value.as_typed_data.values = NULL; \
- } \
- AddBackRef(object_id, object, kIsDeserialized); \
- return object; \
- }
-
-#define READ_EXTERNAL_TYPED_DATA(tname, ctype) \
- { \
- intptr_t len = ReadSmiValue(); \
- auto type = Dart_TypedData_k##tname; \
- intptr_t length_in_bytes = GetTypedDataSizeInBytes(type) * len; \
- Dart_CObject* object = \
- reinterpret_cast<Dart_CObject*>(allocator(sizeof(Dart_CObject))); \
- ASSERT(object != NULL); \
- object->type = Dart_CObject_kTypedData; \
- object->value.as_typed_data.type = type; \
- object->value.as_typed_data.length = length_in_bytes; \
- object->value.as_typed_data.values = \
- reinterpret_cast<uint8_t*>(finalizable_data_->Get().data); \
- AddBackRef(object_id, object, kIsDeserialized); \
- return object; \
- }
-
-#define READ_TYPED_DATA_VIEW(tname, ctype) \
- { \
- Dart_CObject_Internal* object = \
- AllocateDartCObjectInternal(Dart_CObject_Internal::kUninitialized); \
- AddBackRef(object_id, object, kIsDeserialized); \
- object->type = \
- static_cast<Dart_CObject_Type>(Dart_CObject_Internal::kView); \
- object->internal.as_view.offset_in_bytes = ReadSmiValue(); \
- object->internal.as_view.length = ReadSmiValue(); \
- object->internal.as_view.buffer = ReadObjectImpl(); \
- Dart_CObject* buffer = object->internal.as_view.buffer; \
- RELEASE_ASSERT(buffer->type == Dart_CObject_kTypedData); \
- \
- /* Now turn the view into a byte array.*/ \
- const Dart_TypedData_Type type = Dart_TypedData_k##tname; \
- object->type = Dart_CObject_kTypedData; \
- object->value.as_typed_data.type = type; \
- object->value.as_typed_data.length = \
- object->internal.as_view.length * GetTypedDataSizeInBytes(type); \
- object->value.as_typed_data.values = \
- buffer->value.as_typed_data.values + \
- object->internal.as_view.offset_in_bytes; \
- return object; \
- }
-
-#define TYPED_DATA_LIST(V) \
- V(Int8, int8_t) \
- V(Uint8, uint8_t) \
- V(Uint8Clamped, uint8_t) \
- V(Int16, int16_t) \
- V(Uint16, uint16_t) \
- V(Int32, int32_t) \
- V(Uint32, uint32_t) \
- V(Int64, int64_t) \
- V(Uint64, uint64_t) \
- V(Float32, float) \
- V(Float64, double) \
- V(Int32x4, simd128_value_t) \
- V(Float32x4, simd128_value_t) \
- V(Float64x2, simd128_value_t)
-
-#define EMIT_TYPED_DATA_CASES(type, c_type) \
- case kTypedData##type##ArrayCid: \
- READ_TYPED_DATA(type, c_type); \
- case kExternalTypedData##type##ArrayCid: \
- READ_EXTERNAL_TYPED_DATA(type, c_type); \
- case kTypedData##type##ArrayViewCid: \
- READ_TYPED_DATA_VIEW(type, c_type);
-
- TYPED_DATA_LIST(EMIT_TYPED_DATA_CASES)
-#undef EMIT_TYPED_DATA_CASES
-#undef TYPED_DATA_LIST
-#undef READ_TYPED_DATA
-#undef READ_EXTERNAL_TYPED_DATA
-#undef READ_TYPED_DATA_VIEW
-
- case kGrowableObjectArrayCid: {
- // A GrowableObjectArray is serialized as its type arguments and
- // length followed by its backing store. The backing store is an
- // array with a length which might be longer than the length of
- // the GrowableObjectArray.
- Dart_CObject* value = GetBackRef(object_id);
- ASSERT(value == NULL);
- // Allocate an empty array for the GrowableObjectArray which
- // will be updated to point to the content when the backing
- // store has been deserialized.
- value = AllocateDartCObjectArray(0);
- AddBackRef(object_id, value, kIsDeserialized);
-
- // Read and skip the type arguments field.
- // TODO(sjesse): Remove this when message serialization format is
- // updated (currently type_arguments is leaked).
- Dart_CObject* type_arguments = ReadObjectImpl();
- if (type_arguments != &type_arguments_marker &&
- type_arguments->type != Dart_CObject_kNull) {
- return AllocateDartCObjectUnsupported();
- }
-
- // Read the length field.
- intptr_t len = ReadSmiValue();
-
- // Read the content of the GrowableObjectArray.
- Dart_CObject* content = ReadObjectRef();
- ASSERT(content->type == Dart_CObject_kArray);
- // Make the empty array allocated point to the backing store content.
- value->value.as_array.length = len;
- value->value.as_array.values = content->value.as_array.values;
- return value;
- }
- default:
- // Everything else not supported.
- Dart_CObject* value = AllocateDartCObjectUnsupported();
- AddBackRef(object_id, value, kIsDeserialized);
- return value;
- }
-}
-
-Dart_CObject* ApiMessageReader::ReadIndexedObject(intptr_t object_id) {
- if (object_id >= kFirstTypeSnapshotId && object_id <= kLastTypeSnapshotId) {
- // Always return dynamic type (this is only a marker).
- return &dynamic_type_marker;
- }
- if (object_id >= kFirstTypeArgumentsSnapshotId &&
- object_id <= kLastTypeArgumentsSnapshotId) {
- return &type_arguments_marker;
- }
-
- intptr_t index = object_id - kMaxPredefinedObjectIds;
- ASSERT((0 <= index) && (index < backward_references_.length()));
- ASSERT(backward_references_[index]->reference() != NULL);
- return backward_references_[index]->reference();
-}
-
-Dart_CObject* ApiMessageReader::ReadObject() {
- Dart_CObject* value = ReadObjectImpl();
- for (intptr_t i = 0; i < backward_references_.length(); i++) {
- if (!backward_references_[i]->is_deserialized()) {
- ReadObjectImpl();
- backward_references_[i]->set_state(kIsDeserialized);
- }
- }
- return value;
-}
-
-Dart_CObject* ApiMessageReader::ReadObjectImpl() {
- int64_t value64 = Read<int64_t>();
- if ((value64 & kSmiTagMask) == 0) {
- int64_t untagged_value = value64 >> kSmiTagShift;
- if ((kMinInt32 <= untagged_value) && (untagged_value <= kMaxInt32)) {
- return AllocateDartCObjectInt32(static_cast<int32_t>(untagged_value));
- } else {
- return AllocateDartCObjectInt64(untagged_value);
- }
- }
- ASSERT((value64 <= kIntptrMax) && (value64 >= kIntptrMin));
- intptr_t value = static_cast<intptr_t>(value64);
- if (IsVMIsolateObject(value)) {
- return ReadVMIsolateObject(value);
- }
- if (SerializedHeaderTag::decode(value) == kObjectId) {
- return ReadIndexedObject(SerializedHeaderData::decode(value));
- }
- ASSERT(SerializedHeaderTag::decode(value) == kInlined);
-
- intptr_t object_id = SerializedHeaderData::decode(value);
- if (object_id == kOmittedObjectId) {
- object_id = NextAvailableObjectId();
- }
- return ReadInlinedObject(object_id);
-}
-
-void ApiMessageReader::AddBackRef(intptr_t id,
- Dart_CObject* obj,
- DeserializeState state) {
- intptr_t index = (id - kMaxPredefinedObjectIds);
- ASSERT(index == backward_references_.length());
- BackRefNode* node = AllocateBackRefNode(obj, state);
- ASSERT(node != NULL);
- backward_references_.Add(node);
-}
-
-Dart_CObject* ApiMessageReader::GetBackRef(intptr_t id) {
- ASSERT(id >= kMaxPredefinedObjectIds);
- intptr_t index = (id - kMaxPredefinedObjectIds);
- if (index < backward_references_.length()) {
- return backward_references_[index]->reference();
- }
- return NULL;
-}
-
-ApiMessageWriter::ApiMessageWriter()
- : BaseWriter(kInitialSize),
- object_id_(0),
- forward_list_(NULL),
- forward_list_length_(0),
- forward_id_(0),
- finalizable_data_(new MessageFinalizableData()) {
- ASSERT(kDartCObjectTypeMask >= Dart_CObject_kNumberOfTypes - 1);
-}
-
-ApiMessageWriter::~ApiMessageWriter() {
- ::free(forward_list_);
- delete finalizable_data_;
-}
-
-NO_SANITIZE_UNDEFINED(
- "enum") // TODO(https://github.com/dart-lang/sdk/issues/39427)
-void ApiMessageWriter::MarkCObject(Dart_CObject* object, intptr_t object_id) {
- // Mark the object as serialized by adding the object id to the
- // upper bits of the type field in the Dart_CObject structure. Add
- // an offset for making marking of object id 0 possible.
- ASSERT(!IsCObjectMarked(object));
- intptr_t mark_value = object_id + kDartCObjectMarkOffset;
- object->type = static_cast<Dart_CObject_Type>(
- ((mark_value) << kDartCObjectTypeBits) | object->type);
-}
-
-NO_SANITIZE_UNDEFINED(
- "enum") // TODO(https://github.com/dart-lang/sdk/issues/39427)
-void ApiMessageWriter::UnmarkCObject(Dart_CObject* object) {
- ASSERT(IsCObjectMarked(object));
- object->type =
- static_cast<Dart_CObject_Type>(object->type & kDartCObjectTypeMask);
-}
-
-NO_SANITIZE_UNDEFINED(
- "enum") // TODO(https://github.com/dart-lang/sdk/issues/39427)
-bool ApiMessageWriter::IsCObjectMarked(Dart_CObject* object) {
- return (object->type & kDartCObjectMarkMask) != 0;
-}
-
-NO_SANITIZE_UNDEFINED(
- "enum") // TODO(https://github.com/dart-lang/sdk/issues/39427)
-intptr_t ApiMessageWriter::GetMarkedCObjectMark(Dart_CObject* object) {
- ASSERT(IsCObjectMarked(object));
- intptr_t mark_value =
- ((object->type & kDartCObjectMarkMask) >> kDartCObjectTypeBits);
- // An offset was added to object id for making marking object id 0 possible.
- return mark_value - kDartCObjectMarkOffset;
-}
-
-void ApiMessageWriter::UnmarkAllCObjects(Dart_CObject* object) {
- if (!IsCObjectMarked(object)) return;
- UnmarkCObject(object);
- if (object->type == Dart_CObject_kArray) {
- for (int i = 0; i < object->value.as_array.length; i++) {
- Dart_CObject* element = object->value.as_array.values[i];
- UnmarkAllCObjects(element);
- }
- }
-}
-
-void ApiMessageWriter::AddToForwardList(Dart_CObject* object) {
- if (forward_id_ >= forward_list_length_) {
- void* new_list = NULL;
- if (forward_list_length_ == 0) {
- forward_list_length_ = 4;
- intptr_t new_size = forward_list_length_ * sizeof(object);
- new_list = dart::malloc(new_size);
- } else {
- forward_list_length_ *= 2;
- intptr_t new_size = (forward_list_length_ * sizeof(object));
- new_list = dart::realloc(forward_list_, new_size);
- }
- ASSERT(new_list != NULL);
- forward_list_ = reinterpret_cast<Dart_CObject**>(new_list);
- }
- forward_list_[forward_id_] = object;
- forward_id_ += 1;
-}
-
-void ApiMessageWriter::WriteSmi(int64_t value) {
- ASSERT(Smi::IsValid(value));
- Write<ObjectPtr>(Smi::New(static_cast<intptr_t>(value)));
-}
-
-void ApiMessageWriter::WriteNullObject() {
- WriteVMIsolateObject(kNullObject);
-}
-
-void ApiMessageWriter::WriteMint(Dart_CObject* object, int64_t value) {
- ASSERT(!Smi::IsValid(value));
- // Write out the serialization header value for mint object.
- WriteInlinedHeader(object);
- // Write out the class and tags information.
- WriteIndexedObject(kMintCid);
- WriteTags(0);
- // Write the 64-bit value.
- Write<int64_t>(value);
-}
-
-void ApiMessageWriter::WriteInt32(Dart_CObject* object) {
- int64_t value = object->value.as_int32;
- if (Smi::IsValid(value)) {
- WriteSmi(value);
- } else {
- WriteMint(object, value);
- }
-}
-
-void ApiMessageWriter::WriteInt64(Dart_CObject* object) {
- int64_t value = object->value.as_int64;
- if (Smi::IsValid(value)) {
- WriteSmi(value);
- } else {
- WriteMint(object, value);
- }
-}
-
-void ApiMessageWriter::WriteInlinedHeader(Dart_CObject* object) {
- // Write out the serialization header value for this object.
- WriteInlinedObjectHeader(kMaxPredefinedObjectIds + object_id_);
- // Mark object with its object id.
- MarkCObject(object, object_id_);
- // Advance object id.
- object_id_++;
-}
-
-bool ApiMessageWriter::WriteCObject(Dart_CObject* object) {
- if (IsCObjectMarked(object)) {
- intptr_t object_id = GetMarkedCObjectMark(object);
- WriteIndexedObject(kMaxPredefinedObjectIds + object_id);
- return true;
- }
-
- Dart_CObject_Type type = object->type;
- if (type == Dart_CObject_kArray) {
- const intptr_t array_length = object->value.as_array.length;
- if (!Array::IsValidLength(array_length)) {
- return false;
- }
-
- // Write out the serialization header value for this object.
- WriteInlinedHeader(object);
- // Write out the class and tags information.
- WriteIndexedObject(kArrayCid);
- WriteTags(0);
- // Write out the length information.
- WriteSmi(array_length);
- // Write out the type arguments.
- WriteNullObject();
- // Write out array elements.
- for (int i = 0; i < array_length; i++) {
- bool success = WriteCObjectRef(object->value.as_array.values[i]);
- if (!success) return false;
- }
- return true;
- }
- return WriteCObjectInlined(object, type);
-}
-
-bool ApiMessageWriter::WriteCObjectRef(Dart_CObject* object) {
- if (IsCObjectMarked(object)) {
- intptr_t object_id = GetMarkedCObjectMark(object);
- WriteIndexedObject(kMaxPredefinedObjectIds + object_id);
- return true;
- }
-
- Dart_CObject_Type type = object->type;
- if (type == Dart_CObject_kArray) {
- const intptr_t array_length = object->value.as_array.length;
- if (!Array::IsValidLength(array_length)) {
- return false;
- }
- // Write out the serialization header value for this object.
- WriteInlinedHeader(object);
- // Write out the class information.
- WriteIndexedObject(kArrayCid);
- WriteTags(0);
- // Write out the length information.
- WriteSmi(array_length);
- // Add object to forward list so that this object is serialized later.
- AddToForwardList(object);
- return true;
- }
- return WriteCObjectInlined(object, type);
-}
-
-NO_SANITIZE_UNDEFINED(
- "enum") // TODO(https://github.com/dart-lang/sdk/issues/39427)
-bool ApiMessageWriter::WriteForwardedCObject(Dart_CObject* object) {
- ASSERT(IsCObjectMarked(object));
- Dart_CObject_Type type =
- static_cast<Dart_CObject_Type>(object->type & kDartCObjectTypeMask);
- ASSERT(type == Dart_CObject_kArray);
- const intptr_t array_length = object->value.as_array.length;
- if (!Array::IsValidLength(array_length)) {
- return false;
- }
-
- // Write out the serialization header value for this object.
- intptr_t object_id = GetMarkedCObjectMark(object);
- WriteInlinedObjectHeader(kMaxPredefinedObjectIds + object_id);
- // Write out the class and tags information.
- WriteIndexedObject(kArrayCid);
- WriteTags(0);
- // Write out the length information.
- WriteSmi(array_length);
- // Write out the type arguments.
- WriteNullObject();
- // Write out array elements.
- for (int i = 0; i < array_length; i++) {
- bool success = WriteCObjectRef(object->value.as_array.values[i]);
- if (!success) return false;
- }
- return true;
-}
-
-bool ApiMessageWriter::WriteCObjectInlined(Dart_CObject* object,
- Dart_CObject_Type type) {
- switch (type) {
- case Dart_CObject_kNull:
- WriteNullObject();
- break;
- case Dart_CObject_kBool:
- if (object->value.as_bool) {
- WriteVMIsolateObject(kTrueValue);
- } else {
- WriteVMIsolateObject(kFalseValue);
- }
- break;
- case Dart_CObject_kInt32:
- WriteInt32(object);
- break;
- case Dart_CObject_kInt64:
- WriteInt64(object);
- break;
- case Dart_CObject_kDouble:
- WriteVMIsolateObject(kDoubleObject);
- WriteDouble(object->value.as_double);
- break;
- case Dart_CObject_kString: {
- const uint8_t* utf8_str =
- reinterpret_cast<const uint8_t*>(object->value.as_string);
- intptr_t utf8_len = strlen(object->value.as_string);
- if (!Utf8::IsValid(utf8_str, utf8_len)) {
- return false;
- }
-
- Utf8::Type type = Utf8::kLatin1;
- intptr_t len = Utf8::CodeUnitCount(utf8_str, utf8_len, &type);
- if (len > String::kMaxElements) {
- return false;
- }
-
- // Write out the serialization header value for this object.
- WriteInlinedHeader(object);
- // Write out the class and tags information.
- WriteIndexedObject(type == Utf8::kLatin1 ? kOneByteStringCid
- : kTwoByteStringCid);
- WriteTags(0);
- // Write string length and content.
- WriteSmi(len);
- if (type == Utf8::kLatin1) {
- uint8_t* latin1_str =
- reinterpret_cast<uint8_t*>(dart::malloc(len * sizeof(uint8_t)));
- bool success =
- Utf8::DecodeToLatin1(utf8_str, utf8_len, latin1_str, len);
- ASSERT(success);
- for (intptr_t i = 0; i < len; i++) {
- Write<uint8_t>(latin1_str[i]);
- }
- ::free(latin1_str);
- } else {
- uint16_t* utf16_str =
- reinterpret_cast<uint16_t*>(dart::malloc(len * sizeof(uint16_t)));
- bool success = Utf8::DecodeToUTF16(utf8_str, utf8_len, utf16_str, len);
- ASSERT(success);
- for (intptr_t i = 0; i < len; i++) {
- Write<uint16_t>(utf16_str[i]);
- }
- ::free(utf16_str);
- }
- break;
- }
- case Dart_CObject_kTypedData: {
- // Write out the serialization header value for this object.
- WriteInlinedHeader(object);
- // Write out the class and tags information.
- intptr_t class_id;
- switch (object->value.as_typed_data.type) {
- case Dart_TypedData_kInt8:
- class_id = kTypedDataInt8ArrayCid;
- break;
- case Dart_TypedData_kUint8:
- class_id = kTypedDataUint8ArrayCid;
- break;
- case Dart_TypedData_kUint32:
- class_id = kTypedDataUint32ArrayCid;
- break;
- default:
- class_id = kTypedDataUint8ArrayCid;
- UNIMPLEMENTED();
- }
-
- intptr_t len = object->value.as_typed_data.length;
- if (len < 0 || len > TypedData::MaxElements(class_id)) {
- return false;
- }
-
- WriteIndexedObject(class_id);
- WriteTags(0);
- WriteSmi(len);
- switch (class_id) {
- case kTypedDataInt8ArrayCid:
- case kTypedDataUint8ArrayCid: {
- uint8_t* bytes = object->value.as_typed_data.values;
- Align(Zone::kAlignment);
- WriteBytes(bytes, len);
- break;
- }
- case kTypedDataUint32ArrayCid: {
- uint8_t* bytes = object->value.as_typed_data.values;
- Align(Zone::kAlignment);
- WriteBytes(bytes, len * sizeof(uint32_t));
- break;
- }
- default:
- UNIMPLEMENTED();
- }
- break;
- }
- case Dart_CObject_kExternalTypedData: {
- // TODO(ager): we are writing C pointers into the message in
- // order to post external arrays through ports. We need to make
- // sure that messages containing pointers can never be posted
- // to other processes.
-
- // Write out serialization header value for this object.
- WriteInlinedHeader(object);
- // Write out the class and tag information.
- WriteIndexedObject(kExternalTypedDataUint8ArrayCid);
- WriteTags(0);
- intptr_t length = object->value.as_external_typed_data.length;
- if (length < 0 || length > ExternalTypedData::MaxElements(
- kExternalTypedDataUint8ArrayCid)) {
- return false;
- }
- uint8_t* data = object->value.as_external_typed_data.data;
- void* peer = object->value.as_external_typed_data.peer;
- Dart_HandleFinalizer callback =
- object->value.as_external_typed_data.callback;
- if (callback == NULL) {
- return false;
- }
- WriteSmi(length);
- finalizable_data_->Put(length, reinterpret_cast<void*>(data), peer,
- callback);
- break;
- }
- case Dart_CObject_kSendPort: {
- WriteInlinedHeader(object);
- WriteIndexedObject(kSendPortCid);
- WriteTags(0);
- Write<int64_t>(object->value.as_send_port.id);
- Write<uint64_t>(object->value.as_send_port.origin_id);
- break;
- }
- case Dart_CObject_kCapability: {
- WriteInlinedHeader(object);
- WriteIndexedObject(kCapabilityCid);
- WriteTags(0);
- Write<uint64_t>(object->value.as_capability.id);
- break;
- }
- default:
- FATAL1("Unexpected Dart_CObject_Type %d\n", type);
- }
-
- return true;
-}
-
-std::unique_ptr<Message> ApiMessageWriter::WriteCMessage(
- Dart_CObject* object,
- Dart_Port dest_port,
- Message::Priority priority) {
- bool success = WriteCObject(object);
- if (!success) {
- UnmarkAllCObjects(object);
- intptr_t unused;
- free(Steal(&unused));
- return nullptr;
- }
-
- // Write out all objects that were added to the forward list and have
- // not been serialized yet. These would typically be fields of arrays.
- // NOTE: The forward list might grow as we process the list.
- for (intptr_t i = 0; i < forward_id_; i++) {
- success = WriteForwardedCObject(forward_list_[i]);
- if (!success) {
- UnmarkAllCObjects(object);
- intptr_t unused;
- free(Steal(&unused));
- return nullptr;
- }
- }
-
- UnmarkAllCObjects(object);
- MessageFinalizableData* finalizable_data = finalizable_data_;
- finalizable_data_ = nullptr;
- intptr_t size;
- uint8_t* buffer = Steal(&size);
- return Message::New(dest_port, buffer, size, finalizable_data, priority);
-}
-
-} // namespace dart
diff --git a/runtime/vm/dart_api_message.h b/runtime/vm/dart_api_message.h
index ace7dd3..f5994ce 100644
--- a/runtime/vm/dart_api_message.h
+++ b/runtime/vm/dart_api_message.h
@@ -15,185 +15,6 @@
namespace dart {
-// Use this C structure for reading internal objects in the serialized
-// data. These are objects that we need to process in order to
-// generate the Dart_CObject graph but that we don't want to expose in
-// that graph.
-struct Dart_CObject_Internal : public Dart_CObject {
- enum Type {
- kTypeArguments = Dart_CObject_kNumberOfTypes,
- kDynamicType,
- kClass,
- kView,
- kUninitialized,
- };
- struct Dart_CObject_Internal* cls;
- union {
- struct {
- struct _Dart_CObject* library_url;
- struct _Dart_CObject* class_name;
- } as_class;
- struct {
- struct _Dart_CObject* buffer;
- int offset_in_bytes;
- int length;
- } as_view;
- } internal;
-};
-
-// Reads a message snapshot into a C structure.
-class ApiMessageReader : public BaseReader {
- public:
- // The ApiMessageReader object must be enclosed by an ApiNativeScope.
- // Allocation of all C Heap objects is done in the zone associated with
- // the enclosing ApiNativeScope.
- explicit ApiMessageReader(Message* message);
- ~ApiMessageReader();
-
- Dart_CObject* ReadMessage();
-
- private:
- class BackRefNode {
- public:
- BackRefNode(Dart_CObject* reference, DeserializeState state)
- : reference_(reference), state_(state) {}
- Dart_CObject* reference() const { return reference_; }
- void set_reference(Dart_CObject* reference) { reference_ = reference; }
- bool is_deserialized() const { return state_ == kIsDeserialized; }
- void set_state(DeserializeState value) { state_ = value; }
-
- private:
- Dart_CObject* reference_;
- DeserializeState state_;
-
- DISALLOW_COPY_AND_ASSIGN(BackRefNode);
- };
-
- // Allocates a Dart_CObject object.
- Dart_CObject* AllocateDartCObject();
- // Allocates a Dart_CObject object with the specified type.
- Dart_CObject* AllocateDartCObject(Dart_CObject_Type type);
- // Allocates a Dart_CObject object representing an unsupported
- // object in the API message.
- Dart_CObject* AllocateDartCObjectUnsupported();
- // Allocates a Dart_CObject object for the null object.
- Dart_CObject* AllocateDartCObjectNull();
- // Allocates a Dart_CObject object for a boolean object.
- Dart_CObject* AllocateDartCObjectBool(bool value);
- // Allocates a Dart_CObject object for for a 32-bit integer.
- Dart_CObject* AllocateDartCObjectInt32(int32_t value);
- // Allocates a Dart_CObject object for for a 64-bit integer.
- Dart_CObject* AllocateDartCObjectInt64(int64_t value);
- // Allocates a Dart_CObject object for a double.
- Dart_CObject* AllocateDartCObjectDouble(double value);
- // Allocates a Dart_CObject object for string data.
- Dart_CObject* AllocateDartCObjectString(intptr_t length);
- // Allocates a C Dart_CObject object for a typed data.
- Dart_CObject* AllocateDartCObjectTypedData(Dart_TypedData_Type type,
- intptr_t length);
- // Allocates a C array of Dart_CObject objects.
- Dart_CObject* AllocateDartCObjectArray(intptr_t length);
- // Allocate a C Dart_CObject object for a VM isolate object.
- Dart_CObject* AllocateDartCObjectVmIsolateObj(intptr_t id);
- // Allocates a Dart_CObject_Internal object with the specified type.
- Dart_CObject_Internal* AllocateDartCObjectInternal(
- Dart_CObject_Internal::Type type);
- // Allocates a Dart_CObject_Internal object for a class object.
- Dart_CObject_Internal* AllocateDartCObjectClass();
- // Allocates a backwards reference node.
- BackRefNode* AllocateBackRefNode(Dart_CObject* ref, DeserializeState state);
-
- void Init();
-
- intptr_t LookupInternalClass(intptr_t class_header);
- Dart_CObject* ReadVMIsolateObject(intptr_t value);
- Dart_CObject* ReadInternalVMObject(intptr_t class_id, intptr_t object_id);
- Dart_CObject* ReadInlinedObject(intptr_t object_id);
- Dart_CObject* ReadObjectImpl();
- Dart_CObject* ReadIndexedObject(intptr_t object_id);
- Dart_CObject* ReadPredefinedSymbol(intptr_t object_id);
- Dart_CObject* ReadObjectRef();
- Dart_CObject* ReadObject();
-
- // Add object to backward references.
- void AddBackRef(intptr_t id, Dart_CObject* obj, DeserializeState state);
-
- // Get an object from the backward references list.
- Dart_CObject* GetBackRef(intptr_t id);
-
- intptr_t NextAvailableObjectId() const;
-
- Dart_CObject_Internal* AsInternal(Dart_CObject* object) {
- ASSERT(object->type >= Dart_CObject_kNumberOfTypes);
- return reinterpret_cast<Dart_CObject_Internal*>(object);
- }
-
- ObjectPtr VmIsolateSnapshotObject(intptr_t index) const {
- return Object::vm_isolate_snapshot_object_table().At(index);
- }
-
- Dart_CObject* CreateDartCObjectString(ObjectPtr raw);
- Dart_CObject* GetCanonicalMintObject(Dart_CObject_Type type, int64_t value64);
-
- uint8_t* allocator(intptr_t size) {
- return zone_->Realloc<uint8_t>(NULL, 0, size);
- }
-
- Zone* zone_; // Zone in which C heap objects are allocated.
- ApiGrowableArray<BackRefNode*> backward_references_;
- ApiGrowableArray<Dart_CObject*> vm_isolate_references_;
- Dart_CObject** vm_symbol_references_;
-
- Dart_CObject type_arguments_marker;
- Dart_CObject dynamic_type_marker;
-
- MessageFinalizableData* finalizable_data_;
-};
-
-class ApiMessageWriter : public BaseWriter {
- public:
- static const intptr_t kInitialSize = 512;
- ApiMessageWriter();
- ~ApiMessageWriter();
-
- // Writes a message with a single object.
- std::unique_ptr<Message> WriteCMessage(Dart_CObject* object,
- Dart_Port dest_port,
- Message::Priority priority);
-
- private:
- static const intptr_t kDartCObjectTypeBits = 4;
- static const intptr_t kDartCObjectTypeMask = (1 << kDartCObjectTypeBits) - 1;
- static const intptr_t kDartCObjectMarkMask = ~kDartCObjectTypeMask;
- static const intptr_t kDartCObjectMarkOffset = 1;
-
- void MarkCObject(Dart_CObject* object, intptr_t object_id);
- void UnmarkCObject(Dart_CObject* object);
- bool IsCObjectMarked(Dart_CObject* object);
- intptr_t GetMarkedCObjectMark(Dart_CObject* object);
- void UnmarkAllCObjects(Dart_CObject* object);
- void AddToForwardList(Dart_CObject* object);
-
- void WriteSmi(int64_t value);
- void WriteNullObject();
- void WriteMint(Dart_CObject* object, int64_t value);
- void WriteInt32(Dart_CObject* object);
- void WriteInt64(Dart_CObject* object);
- void WriteInlinedHeader(Dart_CObject* object);
- bool WriteCObject(Dart_CObject* object);
- bool WriteCObjectRef(Dart_CObject* object);
- bool WriteForwardedCObject(Dart_CObject* object);
- bool WriteCObjectInlined(Dart_CObject* object, Dart_CObject_Type type);
-
- intptr_t object_id_;
- Dart_CObject** forward_list_;
- intptr_t forward_list_length_;
- intptr_t forward_id_;
- MessageFinalizableData* finalizable_data_;
-
- DISALLOW_COPY_AND_ASSIGN(ApiMessageWriter);
-};
-
// This class handles translation of certain RawObjects to CObjects for
// NativeMessageHandlers.
//
diff --git a/runtime/vm/dart_entry.cc b/runtime/vm/dart_entry.cc
index 461d575..f062909 100644
--- a/runtime/vm/dart_entry.cc
+++ b/runtime/vm/dart_entry.cc
@@ -222,7 +222,7 @@
if (matches && type_args_len > 0 && function.IsClosureFunction()) {
// Though the closure function is generic, the closure itself may
// not be because it closes over delayed function type arguments.
- matches = Closure::Cast(instance).IsGeneric(thread);
+ matches = Closure::Cast(instance).IsGeneric();
}
if (matches) {
@@ -633,17 +633,10 @@
ObjectPtr DartLibraryCalls::ToString(const Instance& receiver) {
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
- Function& function = Function::Handle(
+ const auto& function = Function::Handle(
zone,
thread->isolate_group()->object_store()->_object_to_string_function());
- if (function.IsNull()) {
- const Library& core_lib = Library::Handle(zone, Library::CoreLibrary());
- ASSERT(!core_lib.IsNull());
- function = core_lib.LookupFunctionAllowPrivate(Symbols::_objectToString());
- ASSERT(!function.IsNull());
- thread->isolate_group()->object_store()->set__object_to_string_function(
- function);
- }
+ ASSERT(!function.IsNull());
const int kNumArguments = 1;
const Array& args = Array::Handle(zone, Array::New(kNumArguments));
args.SetAt(0, receiver);
@@ -656,17 +649,10 @@
ObjectPtr DartLibraryCalls::HashCode(const Instance& receiver) {
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
- Function& function = Function::Handle(
+ const auto& function = Function::Handle(
zone,
thread->isolate_group()->object_store()->_object_hash_code_function());
- if (function.IsNull()) {
- const Library& core_lib = Library::Handle(zone, Library::CoreLibrary());
- ASSERT(!core_lib.IsNull());
- function = core_lib.LookupFunctionAllowPrivate(Symbols::_objectHashCode());
- ASSERT(!function.IsNull());
- thread->isolate_group()->object_store()->set__object_hash_code_function(
- function);
- }
+ ASSERT(!function.IsNull());
const int kNumArguments = 1;
const Array& args = Array::Handle(zone, Array::New(kNumArguments));
args.SetAt(0, receiver);
@@ -680,16 +666,9 @@
const Instance& right) {
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
- Function& function = Function::Handle(
+ const auto& function = Function::Handle(
zone, thread->isolate_group()->object_store()->_object_equals_function());
- if (function.IsNull()) {
- const Library& core_lib = Library::Handle(zone, Library::CoreLibrary());
- ASSERT(!core_lib.IsNull());
- function = core_lib.LookupFunctionAllowPrivate(Symbols::_objectEquals());
- ASSERT(!function.IsNull());
- thread->isolate_group()->object_store()->set__object_equals_function(
- function);
- }
+ ASSERT(!function.IsNull());
const int kNumArguments = 2;
const Array& args = Array::Handle(zone, Array::New(kNumArguments));
args.SetAt(0, left);
@@ -721,23 +700,10 @@
ObjectPtr DartLibraryCalls::LookupHandler(Dart_Port port_id) {
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
- Function& function = Function::Handle(
+ const auto& function = Function::Handle(
zone, thread->isolate_group()->object_store()->lookup_port_handler());
- const int kTypeArgsLen = 0;
const int kNumArguments = 1;
- if (function.IsNull()) {
- Library& isolate_lib = Library::Handle(zone, Library::IsolateLibrary());
- ASSERT(!isolate_lib.IsNull());
- const String& class_name = String::Handle(
- zone, isolate_lib.PrivateName(Symbols::_RawReceivePortImpl()));
- const String& function_name = String::Handle(
- zone, isolate_lib.PrivateName(Symbols::_lookupHandler()));
- function = Resolver::ResolveStatic(isolate_lib, class_name, function_name,
- kTypeArgsLen, kNumArguments,
- Object::empty_array());
- ASSERT(!function.IsNull());
- thread->isolate_group()->object_store()->set_lookup_port_handler(function);
- }
+ ASSERT(!function.IsNull());
Array& args = Array::Handle(
zone, thread->isolate()->isolate_object_store()->dart_args_1());
if (args.IsNull()) {
@@ -755,21 +721,7 @@
Zone* zone = thread->zone();
Function& function = Function::Handle(
zone, thread->isolate_group()->object_store()->lookup_open_ports());
- const int kTypeArgsLen = 0;
- const int kNumArguments = 0;
- if (function.IsNull()) {
- Library& isolate_lib = Library::Handle(zone, Library::IsolateLibrary());
- ASSERT(!isolate_lib.IsNull());
- const String& class_name = String::Handle(
- zone, isolate_lib.PrivateName(Symbols::_RawReceivePortImpl()));
- const String& function_name = String::Handle(
- zone, isolate_lib.PrivateName(Symbols::_lookupOpenPorts()));
- function = Resolver::ResolveStatic(isolate_lib, class_name, function_name,
- kTypeArgsLen, kNumArguments,
- Object::empty_array());
- ASSERT(!function.IsNull());
- thread->isolate_group()->object_store()->set_lookup_open_ports(function);
- }
+ ASSERT(!function.IsNull());
const Object& result = Object::Handle(
zone, DartEntry::InvokeFunction(function, Object::empty_array()));
return result.ptr();
@@ -781,23 +733,10 @@
auto zone = thread->zone();
auto isolate = thread->isolate();
auto object_store = thread->isolate_group()->object_store();
- Function& function =
+ const auto& function =
Function::Handle(zone, object_store->handle_message_function());
- const int kTypeArgsLen = 0;
const int kNumArguments = 2;
- if (function.IsNull()) {
- Library& isolate_lib = Library::Handle(zone, Library::IsolateLibrary());
- ASSERT(!isolate_lib.IsNull());
- const String& class_name = String::Handle(
- zone, isolate_lib.PrivateName(Symbols::_RawReceivePortImpl()));
- const String& function_name = String::Handle(
- zone, isolate_lib.PrivateName(Symbols::_handleMessage()));
- function = Resolver::ResolveStatic(isolate_lib, class_name, function_name,
- kTypeArgsLen, kNumArguments,
- Object::empty_array());
- ASSERT(!function.IsNull());
- object_store->set_handle_message_function(function);
- }
+ ASSERT(!function.IsNull());
Array& args =
Array::Handle(zone, isolate->isolate_object_store()->dart_args_2());
if (args.IsNull()) {
diff --git a/runtime/vm/dart_entry.h b/runtime/vm/dart_entry.h
index 57025df..5740337 100644
--- a/runtime/vm/dart_entry.h
+++ b/runtime/vm/dart_entry.h
@@ -180,8 +180,6 @@
// A cache of VM heap allocated arguments descriptors.
static ArrayPtr cached_args_descriptors_[kCachedDescriptorCount];
- friend class SnapshotReader;
- friend class SnapshotWriter;
friend class Serializer;
friend class Deserializer;
friend class Simulator;
diff --git a/runtime/vm/elf.cc b/runtime/vm/elf.cc
index 942ed59..a4f550f 100644
--- a/runtime/vm/elf.cc
+++ b/runtime/vm/elf.cc
@@ -22,15 +22,24 @@
class ElfWriteStream : public ValueObject {
public:
explicit ElfWriteStream(BaseWriteStream* stream, const Elf& elf)
- : stream_(ASSERT_NOTNULL(stream)), elf_(elf) {}
+ : stream_(ASSERT_NOTNULL(stream)),
+ elf_(elf),
+ start_(stream_->Position()) {
+ // So that we can use the underlying stream's Align, as all alignments
+ // will be less than or equal to this alignment.
+ ASSERT(Utils::IsAligned(start_, Elf::kPageSize));
+ }
// Subclasses of Section may need to query the Elf object during Write(),
// so we store it in the ElfWriteStream for easy access.
const Elf& elf() const { return elf_; }
- intptr_t Position() const { return stream_->Position(); }
+ // We return positions in terms of the ELF content that has been written,
+ // ignoring any previous content on the stream.
+ intptr_t Position() const { return stream_->Position() - start_; }
void Align(const intptr_t alignment) {
ASSERT(Utils::IsPowerOfTwo(alignment));
+ ASSERT(alignment <= Elf::kPageSize);
stream_->Align(alignment);
}
void WriteBytes(const uint8_t* b, intptr_t size) {
@@ -48,6 +57,7 @@
private:
BaseWriteStream* const stream_;
const Elf& elf_;
+ const intptr_t start_;
};
static constexpr intptr_t kLinearInitValue = -1;
@@ -66,10 +76,24 @@
#define DEFINE_LINEAR_FIELD(name) intptr_t name##_ = kLinearInitValue;
+// We only allow for dynamic casting to a subset of section types, since
+// these are the only ones we need to distinguish at runtime.
+#define FOR_EACH_SECTION_TYPE(V) \
+ V(ReservedSection) \
+ V(SymbolTable) \
+ V(DynamicTable) \
+ V(BitsContainer) \
+ V(TextSection) V(DataSection) V(BssSection) V(PseudoSection) V(SectionTable)
+#define DEFINE_TYPE_CHECK_FOR(Type) \
+ bool Is##Type() const { return true; }
+
+#define DECLARE_SECTION_TYPE_CLASS(Type) class Type;
+FOR_EACH_SECTION_TYPE(DECLARE_SECTION_TYPE_CLASS)
+#undef DECLARE_SECTION_TYPE_CLASS
+
class BitsContainer;
class Segment;
-static constexpr intptr_t kDefaultAlignment = -1;
// Align note sections and segments to 4 byte boundries.
static constexpr intptr_t kNoteAlignment = 4;
@@ -79,14 +103,16 @@
bool allocate,
bool executable,
bool writable,
- intptr_t align = kDefaultAlignment)
+ intptr_t align = compiler::target::kWordSize)
: type(t),
flags(EncodeFlags(allocate, executable, writable)),
- alignment(align == kDefaultAlignment ? DefaultAlignment(t) : align),
+ alignment(align),
// Non-segments will never have a memory offset, here represented by 0.
memory_offset_(allocate ? kLinearInitValue : 0) {
- // Only sections with type SHT_NULL are allowed to have an alignment of 0.
- ASSERT(type == elf::SectionHeaderType::SHT_NULL || alignment > 0);
+ // Only SHT_NULL sections (namely, the reserved section) are allowed to have
+ // an alignment of 0 (as the written section header entry for the reserved
+ // section must be all 0s).
+ ASSERT(alignment > 0 || type == elf::SectionHeaderType::SHT_NULL);
// Non-zero alignments must be a power of 2.
ASSERT(alignment == 0 || Utils::IsPowerOfTwo(alignment));
}
@@ -94,6 +120,7 @@
virtual ~Section() {}
// Linker view.
+
const elf::SectionHeaderType type;
const intptr_t flags;
const intptr_t alignment;
@@ -103,26 +130,38 @@
intptr_t link = elf::SHN_UNDEF;
intptr_t info = 0;
intptr_t entry_size = 0;
- const char* symbol_name = nullptr;
+ // This field is set for all sections, but due to reordering, we may set it
+ // more than once.
+ intptr_t index = elf::SHN_UNDEF;
#define FOR_EACH_SECTION_LINEAR_FIELD(M) \
M(name) \
- M(index) \
M(file_offset)
FOR_EACH_SECTION_LINEAR_FIELD(DEFINE_LINEAR_FIELD_METHODS);
- virtual intptr_t FileSize() const = 0;
+ // Only needs to be overridden for sections that may not be allocated or
+ // for allocated sections where MemorySize() and FileSize() may differ.
+ virtual intptr_t FileSize() const {
+ if (!IsAllocated()) {
+ UNREACHABLE();
+ }
+ return MemorySize();
+ }
// Loader view.
+
#define FOR_EACH_SEGMENT_LINEAR_FIELD(M) M(memory_offset)
FOR_EACH_SEGMENT_LINEAR_FIELD(DEFINE_LINEAR_FIELD_METHODS);
- // Each section belongs to at most one PT_LOAD segment.
- Segment* load_segment = nullptr;
-
- virtual intptr_t MemorySize() const = 0;
+ // Only needs to be overridden for sections that may be allocated.
+ virtual intptr_t MemorySize() const {
+ if (IsAllocated()) {
+ UNREACHABLE();
+ }
+ return 0;
+ }
// Other methods.
@@ -137,23 +176,37 @@
// Returns whether the size of a section can change.
bool HasBeenFinalized() const {
// Sections can grow or shrink up until Elf::ComputeOffsets has been run,
- // which sets the file offset (and memory offset for allocated sections).
+ // which sets the file (and memory, if applicable) offsets.
return file_offset_is_set();
}
- virtual const BitsContainer* AsBitsContainer() const { return nullptr; }
+#define DEFINE_BASE_TYPE_CHECKS(Type) \
+ Type* As##Type() { \
+ return Is##Type() ? reinterpret_cast<Type*>(this) : nullptr; \
+ } \
+ const Type* As##Type() const { \
+ return const_cast<Type*>(const_cast<Section*>(this)->As##Type()); \
+ } \
+ virtual bool Is##Type() const { return false; }
+
+ FOR_EACH_SECTION_TYPE(DEFINE_BASE_TYPE_CHECKS)
+#undef DEFINE_BASE_TYPE_CHECKS
+
+ // Only some sections support merging.
+ virtual bool CanMergeWith(const Section& other) const { return false; }
+ virtual void Merge(const Section& other) { UNREACHABLE(); }
// Writes the file contents of the section.
- virtual void Write(ElfWriteStream* stream) = 0;
+ virtual void Write(ElfWriteStream* stream) const { UNREACHABLE(); }
- virtual void WriteSectionHeader(ElfWriteStream* stream) {
+ virtual void WriteSectionHeader(ElfWriteStream* stream) const {
#if defined(TARGET_ARCH_IS_32_BIT)
stream->WriteWord(name());
stream->WriteWord(static_cast<uint32_t>(type));
stream->WriteWord(flags);
stream->WriteAddr(memory_offset());
stream->WriteOff(file_offset());
- stream->WriteWord(FileSize()); // Has different meaning for BSS.
+ stream->WriteWord(FileSize());
stream->WriteWord(link);
stream->WriteWord(info);
stream->WriteWord(alignment);
@@ -164,7 +217,7 @@
stream->WriteXWord(flags);
stream->WriteAddr(memory_offset());
stream->WriteOff(file_offset());
- stream->WriteXWord(FileSize()); // Has different meaning for BSS.
+ stream->WriteXWord(FileSize());
stream->WriteWord(link);
stream->WriteWord(info);
stream->WriteXWord(alignment);
@@ -174,25 +227,17 @@
private:
static intptr_t EncodeFlags(bool allocate, bool executable, bool writable) {
+ // Executable and writable only make sense if this is an allocated section.
+ ASSERT(allocate || (!executable && !writable));
if (!allocate) return 0;
intptr_t flags = elf::SHF_ALLOC;
+ // We currently don't allow sections that are both executable and writable.
+ ASSERT(!executable || !writable);
if (executable) flags |= elf::SHF_EXECINSTR;
if (writable) flags |= elf::SHF_WRITE;
return flags;
}
- static intptr_t DefaultAlignment(elf::SectionHeaderType type) {
- switch (type) {
- case elf::SectionHeaderType::SHT_SYMTAB:
- case elf::SectionHeaderType::SHT_DYNSYM:
- case elf::SectionHeaderType::SHT_HASH:
- case elf::SectionHeaderType::SHT_DYNAMIC:
- return compiler::target::kWordSize;
- default:
- return 1;
- }
- }
-
FOR_EACH_SECTION_LINEAR_FIELD(DEFINE_LINEAR_FIELD);
FOR_EACH_SEGMENT_LINEAR_FIELD(DEFINE_LINEAR_FIELD);
@@ -217,49 +262,52 @@
// so we never should pass this value.
ASSERT(segment_type != elf::ProgramHeaderType::PT_NULL);
// All segments should have at least one section.
+ ASSERT(initial_section != nullptr);
ASSERT(initial_section->IsAllocated());
sections_.Add(initial_section);
- if (type == elf::ProgramHeaderType::PT_LOAD) {
- ASSERT(initial_section->load_segment == nullptr);
- }
}
virtual ~Segment() {}
- static intptr_t Alignment(elf::ProgramHeaderType segment_type) {
- switch (segment_type) {
+ const GrowableArray<Section*>& sections() const { return sections_; }
+
+ intptr_t Alignment() const {
+ switch (type) {
+ case elf::ProgramHeaderType::PT_LOAD:
+ return Elf::kPageSize;
case elf::ProgramHeaderType::PT_PHDR:
case elf::ProgramHeaderType::PT_DYNAMIC:
return compiler::target::kWordSize;
case elf::ProgramHeaderType::PT_NOTE:
return kNoteAlignment;
default:
- return Elf::kPageSize;
+ UNREACHABLE();
+ return 0;
}
}
bool IsExecutable() const { return (flags & elf::PF_X) == elf::PF_X; }
bool IsWritable() const { return (flags & elf::PF_W) == elf::PF_W; }
- void WriteProgramHeader(ElfWriteStream* stream) {
+ void WriteProgramHeader(ElfWriteStream* stream) const {
#if defined(TARGET_ARCH_IS_32_BIT)
stream->WriteWord(static_cast<uint32_t>(type));
stream->WriteOff(FileOffset());
stream->WriteAddr(MemoryOffset()); // Virtual address.
- stream->WriteAddr(MemoryOffset()); // Physical address, not used.
+ stream->WriteAddr(MemoryOffset()); // Physical address.
stream->WriteWord(FileSize());
stream->WriteWord(MemorySize());
stream->WriteWord(flags);
- stream->WriteWord(Alignment(type));
+ stream->WriteWord(Alignment());
#else
stream->WriteWord(static_cast<uint32_t>(type));
stream->WriteWord(flags);
stream->WriteOff(FileOffset());
stream->WriteAddr(MemoryOffset()); // Virtual address.
- stream->WriteAddr(MemoryOffset()); // Physical address, not used.
+ stream->WriteAddr(MemoryOffset()); // Physical address.
stream->WriteXWord(FileSize());
stream->WriteXWord(MemorySize());
- stream->WriteXWord(Alignment(type));
+ stream->WriteXWord(Alignment());
#endif
}
@@ -267,36 +315,16 @@
// section was successfully added.
bool Add(Section* section) {
ASSERT(section != nullptr);
+ // We can't add if memory offsets have already been calculated.
+ ASSERT(!section->memory_offset_is_set());
// We only add additional sections to load segments.
ASSERT(type == elf::ProgramHeaderType::PT_LOAD);
- // Don't use this to change a section's segment.
- ASSERT(section->load_segment == nullptr);
// We only add sections with the same executable and writable bits.
if (IsExecutable() != section->IsExecutable() ||
IsWritable() != section->IsWritable()) {
return false;
}
sections_.Add(section);
- section->load_segment = this;
- return true;
- }
-
- bool Merge(Segment* other) {
- ASSERT(other != nullptr);
- // We only add additional sections to load segments.
- ASSERT(type == elf::ProgramHeaderType::PT_LOAD);
- // We only merge segments with the same executable and writable bits.
- if (IsExecutable() != other->IsExecutable() ||
- IsWritable() != other->IsWritable()) {
- return false;
- }
- for (auto* section : other->sections_) {
- // Don't merge segments where the memory offsets have already been
- // calculated.
- ASSERT(!section->memory_offset_is_set());
- sections_.Add(section);
- section->load_segment = this;
- }
return true;
}
@@ -318,10 +346,10 @@
intptr_t MemoryEnd() const { return MemoryOffset() + MemorySize(); }
- private:
- static constexpr intptr_t kInitValue = -1;
- static_assert(kInitValue < 0, "init value must be negative");
+ const elf::ProgramHeaderType type;
+ const intptr_t flags;
+ private:
static intptr_t EncodeFlags(bool executable, bool writable) {
intptr_t flags = elf::PF_R;
if (executable) flags |= elf::PF_X;
@@ -329,11 +357,6 @@
return flags;
}
- public:
- const elf::ProgramHeaderType type;
- const intptr_t flags;
-
- private:
GrowableArray<Section*> sections_;
};
@@ -347,84 +370,11 @@
/*executable=*/false,
/*writable=*/false,
/*alignment=*/0) {
- set_name(0);
- set_index(0);
set_file_offset(0);
}
+ DEFINE_TYPE_CHECK_FOR(ReservedSection);
intptr_t FileSize() const { return 0; }
- intptr_t MemorySize() const { return 0; }
- void Write(ElfWriteStream* stream) {}
-};
-
-// Represents portions of the file/memory space which do not correspond to
-// actual sections. Should never be added to sections_.
-class PseudoSection : public Section {
- public:
- PseudoSection(bool executable,
- bool writable,
- intptr_t file_offset,
- intptr_t file_size,
- intptr_t memory_offset,
- intptr_t memory_size)
- : Section(elf::SectionHeaderType::SHT_NULL,
- /*allocate=*/true,
- executable,
- writable,
- /*alignment=*/0),
- file_size_(file_size),
- memory_size_(memory_size) {
- set_file_offset(file_offset);
- set_memory_offset(memory_offset);
- }
-
- intptr_t FileSize() const { return file_size_; }
- intptr_t MemorySize() const { return memory_size_; }
- void WriteSectionHeader(ElfWriteStream* stream) { UNREACHABLE(); }
- void Write(ElfWriteStream* stream) { UNREACHABLE(); }
-
- private:
- const intptr_t file_size_;
- const intptr_t memory_size_;
-};
-
-// A segment for representing the program header table self-reference in the
-// program header table.
-class ProgramTableSelfSegment : public Segment {
- public:
- ProgramTableSelfSegment(Zone* zone, intptr_t offset, intptr_t size)
- : Segment(zone,
- new (zone) PseudoSection(/*executable=*/false,
- /*writable=*/false,
- offset,
- size,
- offset,
- size),
- elf::ProgramHeaderType::PT_PHDR) {}
-};
-
-// A segment for representing the program header table load segment in the
-// program header table.
-class ProgramTableLoadSegment : public Segment {
- public:
- // The Android dynamic linker in Jelly Bean incorrectly assumes that all
- // non-writable segments are continguous. Since the BSS segment comes directly
- // after the program header segment, we must make this segment writable so
- // later non-writable segments does not cause the BSS to be also marked as
- // read-only.
- //
- // The bug is here:
- // https://github.com/aosp-mirror/platform_bionic/blob/94963af28e445384e19775a838a29e6a71708179/linker/linker.c#L1991-L2001
- explicit ProgramTableLoadSegment(Zone* zone, intptr_t size)
- : Segment(zone,
- // This segment should always start at address 0.
- new (zone) PseudoSection(/*executable=*/false,
- /*writable=*/true,
- 0,
- size,
- 0,
- size),
- elf::ProgramHeaderType::PT_LOAD) {}
};
class StringTable : public Section {
@@ -437,18 +387,18 @@
dynamic_(allocate),
text_(zone, 128),
text_indices_(zone) {
- AddString("");
+ Add("");
}
intptr_t FileSize() const { return text_.length(); }
intptr_t MemorySize() const { return dynamic_ ? FileSize() : 0; }
- void Write(ElfWriteStream* stream) {
+ void Write(ElfWriteStream* stream) const {
stream->WriteBytes(reinterpret_cast<const uint8_t*>(text_.buffer()),
text_.length());
}
- intptr_t AddString(const char* str) {
+ intptr_t Add(const char* str) {
ASSERT(str != nullptr);
if (auto const kv = text_indices_.Lookup(str)) {
return kv->value;
@@ -460,8 +410,8 @@
return offset;
}
- const char* At(intptr_t index) {
- ASSERT(index < text_.length());
+ const char* At(intptr_t index) const {
+ if (index >= text_.length()) return nullptr;
return text_.buffer() + index;
}
@@ -491,51 +441,31 @@
dynamic_(dynamic),
symbols_(zone, 1),
by_name_index_(zone) {
+ link = table_->index;
entry_size = sizeof(elf::Symbol);
// The first symbol table entry is reserved and must be all zeros.
// (String tables always have the empty string at the 0th index.)
- const char* const kReservedName = "";
- AddSymbol(kReservedName, elf::STB_LOCAL, elf::STT_NOTYPE, elf::SHN_UNDEF,
- /*size=*/0);
- FinalizeSymbol(kReservedName, elf::SHN_UNDEF, /*offset=*/0);
+ ASSERT_EQUAL(table_->Lookup(""), 0);
+ symbols_.Add({/*name_index=*/0, elf::STB_LOCAL, elf::STT_NOTYPE, /*size=*/0,
+ elf::SHN_UNDEF, /*offset=*/0});
+ // The info field on a symbol table section holds the index of the first
+ // non-local symbol, so since there are none yet, it points past the single
+ // symbol we do have.
+ info = 1;
}
- intptr_t FileSize() const { return Length() * entry_size; }
+ DEFINE_TYPE_CHECK_FOR(SymbolTable)
+ const StringTable& strtab() const { return *table_; }
+ intptr_t FileSize() const { return symbols_.length() * entry_size; }
intptr_t MemorySize() const { return dynamic_ ? FileSize() : 0; }
- class Symbol : public ZoneAllocated {
- public:
- Symbol(const char* cstr,
- intptr_t name,
- intptr_t binding,
- intptr_t type,
- intptr_t initial_section_index,
- intptr_t size)
- : name_index(name),
- binding(binding),
- type(type),
- size(size),
- section_index(initial_section_index),
- cstr_(cstr) {}
-
- void Finalize(intptr_t final_section_index, intptr_t offset) {
- ASSERT(!HasBeenFinalized()); // No symbol should be re-finalized.
- section_index = final_section_index;
- offset_ = offset;
- }
- bool HasBeenFinalized() const { return offset_ != kNotFinalizedMarker; }
- intptr_t offset() const {
- ASSERT(HasBeenFinalized());
- // Only the reserved initial symbol should have an offset of 0.
- ASSERT_EQUAL(type == elf::STT_NOTYPE, offset_ == 0);
- return offset_;
- }
-
+ struct Symbol {
void Write(ElfWriteStream* stream) const {
const intptr_t start = stream->Position();
+ ASSERT(section_index == elf::SHN_UNDEF || offset > 0);
stream->WriteWord(name_index);
#if defined(TARGET_ARCH_IS_32_BIT)
- stream->WriteAddr(offset());
+ stream->WriteAddr(offset);
stream->WriteWord(size);
stream->WriteByte(elf::SymbolInfo(binding, type));
stream->WriteByte(0);
@@ -544,35 +474,34 @@
stream->WriteByte(elf::SymbolInfo(binding, type));
stream->WriteByte(0);
stream->WriteHalf(section_index);
- stream->WriteAddr(offset());
+ stream->WriteAddr(offset);
stream->WriteXWord(size);
#endif
ASSERT_EQUAL(stream->Position() - start, sizeof(elf::Symbol));
}
- const intptr_t name_index;
- const intptr_t binding;
- const intptr_t type;
- const intptr_t size;
- // Is set twice: once in Elf::AddSection to the section's initial index into
- // sections_, and then in Elf::FinalizeSymbols to the section's final index
- // into sections_ after reordering.
+ intptr_t name_index;
+ intptr_t binding;
+ intptr_t type;
+ intptr_t size;
+ // Must be updated whenever sections are reordered.
intptr_t section_index;
+ // Initialized to the section-relative offset, must be updated to the
+ // snapshot-relative offset before writing.
+ intptr_t offset;
private:
- static const intptr_t kNotFinalizedMarker = -1;
-
- const char* const cstr_;
- intptr_t offset_ = kNotFinalizedMarker;
-
- friend class SymbolHashTable; // For cstr_ access.
+ DISALLOW_ALLOCATION();
};
- void Write(ElfWriteStream* stream) {
- for (intptr_t i = 0; i < Length(); i++) {
- auto const symbol = At(i);
+ const GrowableArray<Symbol>& symbols() const { return symbols_; }
+
+ void Initialize(const GrowableArray<Section*>& sections);
+
+ void Write(ElfWriteStream* stream) const {
+ for (const auto& symbol : symbols_) {
const intptr_t start = stream->Position();
- symbol->Write(stream);
+ symbol.Write(stream);
ASSERT_EQUAL(stream->Position() - start, entry_size);
}
}
@@ -580,131 +509,162 @@
void AddSymbol(const char* name,
intptr_t binding,
intptr_t type,
- intptr_t section_index,
- intptr_t size) {
+ intptr_t size,
+ intptr_t index,
+ intptr_t offset) {
ASSERT(!table_->HasBeenFinalized());
- auto const name_index = table_->AddString(name);
- ASSERT(by_name_index_.Lookup(name_index) == nullptr);
- auto const symbol = new (zone_)
- Symbol(name, name_index, binding, type, section_index, size);
- symbols_.Add(symbol);
- by_name_index_.Insert(name_index, symbol);
+ auto const name_index = table_->Add(name);
+ ASSERT(name_index != 0);
+ const intptr_t new_index = symbols_.length();
+ symbols_.Add({name_index, binding, type, size, index, offset});
+ by_name_index_.Insert(name_index, new_index);
// The info field on a symbol table section holds the index of the first
// non-local symbol, so they can be skipped if desired. Thus, we need to
// make sure local symbols are before any non-local ones.
if (binding == elf::STB_LOCAL) {
- if (info != symbols_.length() - 1) {
+ if (info != new_index) {
// There are non-local symbols, as otherwise [info] would be the
// index of the new symbol. Since the order doesn't otherwise matter,
// swap the new local symbol with the value at index [info], so when
// [info] is incremented it will point just past the new local symbol.
- ASSERT(symbols_[info]->binding != elf::STB_LOCAL);
- symbols_.Swap(info, symbols_.length() - 1);
+ ASSERT(symbols_[info].binding != elf::STB_LOCAL);
+ symbols_.Swap(info, new_index);
+ // Since by_name_index has indices into symbols_, we need to update it.
+ by_name_index_.Update({symbols_[info].name_index, info});
+ by_name_index_.Update({symbols_[new_index].name_index, new_index});
}
info += 1;
}
}
- void FinalizeSymbol(const char* name,
- intptr_t final_section_index,
- intptr_t offset) {
- const intptr_t name_index = table_->Lookup(name);
- ASSERT(name_index != StringTable::kNotIndexed);
- Symbol* symbol = by_name_index_.Lookup(name_index);
- ASSERT(symbol != nullptr);
- symbol->Finalize(final_section_index, offset);
+ void UpdateSectionIndices(const GrowableArray<intptr_t>& index_map) {
+#if defined(DEBUG)
+ const intptr_t map_size = index_map.length();
+ // The first entry must be 0 so that symbols with index SHN_UNDEF, like
+ // the initial reserved symbol, are unchanged.
+ ASSERT_EQUAL(index_map[0], 0);
+ for (intptr_t i = 1; i < map_size; i++) {
+ ASSERT(index_map[i] != 0);
+ ASSERT(index_map[i] < map_size);
+ }
+#endif
+ for (auto& symbol : symbols_) {
+ DEBUG_ASSERT(symbol.section_index < map_size);
+ symbol.section_index = index_map[symbol.section_index];
+ }
}
- intptr_t Length() const { return symbols_.length(); }
- const Symbol* At(intptr_t i) const { return symbols_[i]; }
+ void Finalize(const GrowableArray<intptr_t>& address_map) {
+#if defined(DEBUG)
+ const intptr_t map_size = address_map.length();
+ // The first entry must be 0 so that symbols with index SHN_UNDEF, like
+ // the initial reserved symbol, are unchanged.
+ ASSERT_EQUAL(address_map[0], 0);
+ for (intptr_t i = 1; i < map_size; i++) {
+ // No section begins at the start of the snapshot.
+ ASSERT(address_map[i] != 0);
+ }
+#endif
+ for (auto& symbol : symbols_) {
+ DEBUG_ASSERT(symbol.section_index < map_size);
+ symbol.offset += address_map[symbol.section_index];
+ }
+ }
const Symbol* Find(const char* name) const {
ASSERT(name != nullptr);
- auto const name_index = table_->Lookup(name);
- return by_name_index_.Lookup(name_index);
+ const intptr_t name_index = table_->Lookup(name);
+ // 0 is kNoValue for by_name_index, but luckily that's the name of the
+ // initial reserved symbol.
+ if (name_index == 0) return &symbols_[0];
+ const intptr_t symbols_index = by_name_index_.Lookup(name_index);
+ if (symbols_index == 0) return nullptr; // Not found.
+ return &symbols_[symbols_index];
}
private:
Zone* const zone_;
StringTable* const table_;
const bool dynamic_;
- GrowableArray<Symbol*> symbols_;
- mutable IntMap<Symbol*> by_name_index_;
+ GrowableArray<Symbol> symbols_;
+ // Maps name indexes in table_ to indexes in symbols_. Does not include an
+ // entry for the reserved symbol (name ""), as 0 is kNoValue.
+ IntMap<intptr_t> by_name_index_;
};
-static uint32_t ElfHash(const unsigned char* name) {
- uint32_t h = 0;
- while (*name != '\0') {
- h = (h << 4) + *name++;
- uint32_t g = h & 0xf0000000;
- h ^= g;
- h ^= g >> 24;
- }
- return h;
-}
-
class SymbolHashTable : public Section {
public:
- SymbolHashTable(Zone* zone, StringTable* strtab, SymbolTable* symtab)
+ SymbolHashTable(Zone* zone, SymbolTable* symtab)
: Section(elf::SectionHeaderType::SHT_HASH,
/*allocate=*/true,
/*executable=*/false,
- /*writable=*/false) {
+ /*writable=*/false),
+ buckets_(zone, 0),
+ chains_(zone, 0) {
+ link = symtab->index;
entry_size = sizeof(int32_t);
- nchain_ = symtab->Length();
- nbucket_ = symtab->Length();
+ const auto& symbols = symtab->symbols();
+ const intptr_t num_symbols = symbols.length();
+ buckets_.FillWith(elf::STN_UNDEF, 0, num_symbols);
+ chains_.FillWith(elf::STN_UNDEF, 0, num_symbols);
- bucket_ = zone->Alloc<int32_t>(nbucket_);
- for (intptr_t i = 0; i < nbucket_; i++) {
- bucket_[i] = elf::STN_UNDEF;
- }
-
- chain_ = zone->Alloc<int32_t>(nchain_);
- for (intptr_t i = 0; i < nchain_; i++) {
- chain_[i] = elf::STN_UNDEF;
- }
-
- for (intptr_t i = 1; i < symtab->Length(); i++) {
- auto const symbol = symtab->At(i);
- uint32_t hash = ElfHash((const unsigned char*)symbol->cstr_);
- uint32_t probe = hash % nbucket_;
- chain_[i] = bucket_[probe]; // next = head
- bucket_[probe] = i; // head = symbol
+ for (intptr_t i = 1; i < num_symbols; i++) {
+ const auto& symbol = symbols[i];
+ uint32_t hash = HashSymbolName(symtab->strtab().At(symbol.name_index));
+ uint32_t probe = hash % num_symbols;
+ chains_[i] = buckets_[probe]; // next = head
+ buckets_[probe] = i; // head = symbol
}
}
- intptr_t FileSize() const { return entry_size * (nbucket_ + nchain_ + 2); }
- intptr_t MemorySize() const { return FileSize(); }
+ intptr_t MemorySize() const {
+ return entry_size * (buckets_.length() + chains_.length() + 2);
+ }
- void Write(ElfWriteStream* stream) {
- stream->WriteWord(nbucket_);
- stream->WriteWord(nchain_);
- for (intptr_t i = 0; i < nbucket_; i++) {
- stream->WriteWord(bucket_[i]);
+ void Write(ElfWriteStream* stream) const {
+ stream->WriteWord(buckets_.length());
+ stream->WriteWord(chains_.length());
+ for (const int32_t bucket : buckets_) {
+ stream->WriteWord(bucket);
}
- for (intptr_t i = 0; i < nchain_; i++) {
- stream->WriteWord(chain_[i]);
+ for (const int32_t chain : chains_) {
+ stream->WriteWord(chain);
}
}
+ static uint32_t HashSymbolName(const void* p) {
+ auto* name = reinterpret_cast<const uint8_t*>(p);
+ uint32_t h = 0;
+ while (*name != '\0') {
+ h = (h << 4) + *name++;
+ uint32_t g = h & 0xf0000000;
+ h ^= g;
+ h ^= g >> 24;
+ }
+ return h;
+ }
+
private:
- int32_t nbucket_;
- int32_t nchain_;
- int32_t* bucket_; // "Head"
- int32_t* chain_; // "Next"
+ GrowableArray<int32_t> buckets_; // "Head"
+ GrowableArray<int32_t> chains_; // "Next"
};
class DynamicTable : public Section {
public:
- explicit DynamicTable(Zone* zone)
+ // .dynamic section is expected to be writable on most Linux systems
+ // unless dynamic linker is explicitly built with support for an read-only
+ // .dynamic section (DL_RO_DYN_SECTION).
+ DynamicTable(Zone* zone, SymbolTable* symtab, SymbolHashTable* hash)
: Section(elf::SectionHeaderType::SHT_DYNAMIC,
/*allocate=*/true,
/*executable=*/false,
- /*writable=*/true) {
+ /*writable=*/true),
+ symtab_(symtab),
+ hash_(hash) {
+ link = strtab().index;
entry_size = sizeof(elf::DynamicEntry);
- // Entries that are not constants are fixed during Elf::Finalize().
AddEntry(zone, elf::DynamicEntryType::DT_HASH, kInvalidEntry);
AddEntry(zone, elf::DynamicEntryType::DT_STRTAB, kInvalidEntry);
AddEntry(zone, elf::DynamicEntryType::DT_STRSZ, kInvalidEntry);
@@ -715,19 +675,30 @@
static constexpr intptr_t kInvalidEntry = -1;
- intptr_t FileSize() const { return entries_.length() * entry_size; }
- intptr_t MemorySize() const { return FileSize(); }
+ DEFINE_TYPE_CHECK_FOR(DynamicTable)
+ const SymbolHashTable& hash() const { return *hash_; }
+ const SymbolTable& symtab() const { return *symtab_; }
+ const StringTable& strtab() const { return symtab().strtab(); }
+ intptr_t MemorySize() const { return entries_.length() * entry_size; }
- void Write(ElfWriteStream* stream) {
+ void Write(ElfWriteStream* stream) const {
for (intptr_t i = 0; i < entries_.length(); i++) {
entries_[i]->Write(stream);
}
}
+ void Finalize() {
+ FinalizeEntry(elf::DynamicEntryType::DT_HASH, hash().memory_offset());
+ FinalizeEntry(elf::DynamicEntryType::DT_STRTAB, strtab().memory_offset());
+ FinalizeEntry(elf::DynamicEntryType::DT_STRSZ, strtab().MemorySize());
+ FinalizeEntry(elf::DynamicEntryType::DT_SYMTAB, symtab().memory_offset());
+ }
+
+ private:
struct Entry : public ZoneAllocated {
Entry(elf::DynamicEntryType tag, intptr_t value) : tag(tag), value(value) {}
- void Write(ElfWriteStream* stream) {
+ void Write(ElfWriteStream* stream) const {
ASSERT(value != kInvalidEntry);
const intptr_t start = stream->Position();
#if defined(TARGET_ARCH_IS_32_BIT)
@@ -758,74 +729,28 @@
}
}
- void FinalizeEntries(StringTable* strtab,
- SymbolTable* symtab,
- SymbolHashTable* hash) {
- FinalizeEntry(elf::DynamicEntryType::DT_HASH, hash->memory_offset());
- FinalizeEntry(elf::DynamicEntryType::DT_STRTAB, strtab->memory_offset());
- FinalizeEntry(elf::DynamicEntryType::DT_STRSZ, strtab->MemorySize());
- FinalizeEntry(elf::DynamicEntryType::DT_SYMTAB, symtab->memory_offset());
- }
-
- private:
+ SymbolTable* const symtab_;
+ SymbolHashTable* const hash_;
GrowableArray<Entry*> entries_;
};
-// A segment for representing the dynamic table segment in the program header
-// table. There is no corresponding section for this segment.
-class DynamicSegment : public Segment {
- public:
- explicit DynamicSegment(Zone* zone, DynamicTable* dynamic)
- : Segment(zone, dynamic, elf::ProgramHeaderType::PT_DYNAMIC) {}
-};
-
-// A segment for representing the dynamic table segment in the program header
-// table. There is no corresponding section for this segment.
-class NoteSegment : public Segment {
- public:
- NoteSegment(Zone* zone, Section* note)
- : Segment(zone, note, elf::ProgramHeaderType::PT_NOTE) {
- ASSERT_EQUAL(static_cast<uint32_t>(note->type),
- static_cast<uint32_t>(elf::SectionHeaderType::SHT_NOTE));
- }
-};
-
class BitsContainer : public Section {
public:
- // Fully specified BitsContainer information.
+ // Fully specified BitsContainer information. Unless otherwise specified,
+ // BitContainers are aligned on byte boundaries (i.e., no padding is used).
BitsContainer(elf::SectionHeaderType type,
bool allocate,
bool executable,
bool writable,
- intptr_t size,
- const uint8_t* bytes,
- const ZoneGrowableArray<Elf::Relocation>* relocations,
- const ZoneGrowableArray<Elf::SymbolData>* symbols,
- int alignment = kDefaultAlignment)
- : Section(type, allocate, executable, writable, alignment),
- file_size_(type == elf::SectionHeaderType::SHT_NOBITS ? 0 : size),
- memory_size_(allocate ? size : 0),
- bytes_(bytes),
- relocations_(relocations),
- symbols_(symbols) {
- ASSERT(type == elf::SectionHeaderType::SHT_NOBITS || bytes != nullptr);
- }
+ int alignment = 1)
+ : Section(type, allocate, executable, writable, alignment) {}
- // For BitsContainers used only as sections.
- BitsContainer(elf::SectionHeaderType type,
- intptr_t size,
- const uint8_t* bytes,
- const ZoneGrowableArray<Elf::Relocation>* relocations,
- const ZoneGrowableArray<Elf::SymbolData>* symbols,
- intptr_t alignment = kDefaultAlignment)
+ // For BitsContainers used only as unallocated sections.
+ explicit BitsContainer(elf::SectionHeaderType type, intptr_t alignment = 1)
: BitsContainer(type,
/*allocate=*/false,
/*executable=*/false,
/*writable=*/false,
- size,
- bytes,
- relocations,
- symbols,
alignment) {}
// For BitsContainers used as segments whose type differ on the type of the
@@ -834,61 +759,54 @@
BitsContainer(Elf::Type t,
bool executable,
bool writable,
- intptr_t size,
- const uint8_t* bytes,
- const ZoneGrowableArray<Elf::Relocation>* relocations,
- const ZoneGrowableArray<Elf::SymbolData>* symbols,
- intptr_t alignment = kDefaultAlignment)
+ intptr_t alignment = 1)
: BitsContainer(t == Elf::Type::Snapshot
? elf::SectionHeaderType::SHT_PROGBITS
: elf::SectionHeaderType::SHT_NOBITS,
/*allocate=*/true,
executable,
writable,
- size,
- bytes,
- relocations,
- symbols,
alignment) {}
- const BitsContainer* AsBitsContainer() const { return this; }
- const ZoneGrowableArray<Elf::SymbolData>* symbols() const { return symbols_; }
+ DEFINE_TYPE_CHECK_FOR(BitsContainer)
- void Write(ElfWriteStream* stream) {
- if (type == elf::SectionHeaderType::SHT_NOBITS) return;
- if (relocations_ == nullptr) {
- return stream->WriteBytes(bytes(), FileSize());
- }
- const SymbolTable* symtab = ASSERT_NOTNULL(stream->elf().symtab());
- // Resolve relocations as we write.
- intptr_t current_pos = 0;
- for (const auto& reloc : *relocations_) {
- // We assume here that the relocations are sorted in increasing order,
- // with unique section offsets.
- ASSERT(current_pos <= reloc.section_offset);
- if (current_pos < reloc.section_offset) {
- stream->WriteBytes(bytes_ + current_pos,
- reloc.section_offset - current_pos);
+ bool IsNoBits() const { return type == elf::SectionHeaderType::SHT_NOBITS; }
+ bool HasBytes() const {
+ return portions_.length() != 0 && portions_[0].bytes != nullptr;
+ }
+
+ struct Portion {
+ void Write(ElfWriteStream* stream, intptr_t section_start) const {
+ ASSERT(bytes != nullptr);
+ if (relocations == nullptr) {
+ stream->WriteBytes(bytes, size);
+ return;
}
- intptr_t source_address = reloc.source_offset;
- intptr_t target_address = reloc.target_offset;
- // Null symbols denote that the corresponding offset should be treated
- // as an absolute offset in the ELF memory space.
- if (reloc.source_symbol != nullptr) {
- if (strcmp(reloc.source_symbol, ".") == 0) {
- source_address += memory_offset() + reloc.section_offset;
- } else {
- auto* const source_symbol = symtab->Find(reloc.source_symbol);
- ASSERT(source_symbol != nullptr);
- source_address += source_symbol->offset();
+ const SymbolTable& symtab = stream->elf().symtab();
+ // Resolve relocations as we write.
+ intptr_t current_pos = 0;
+ for (const auto& reloc : *relocations) {
+ // We assume here that the relocations are sorted in increasing order,
+ // with unique section offsets.
+ ASSERT(current_pos <= reloc.section_offset);
+ if (current_pos < reloc.section_offset) {
+ stream->WriteBytes(bytes + current_pos,
+ reloc.section_offset - current_pos);
}
- }
- if (reloc.target_symbol != nullptr) {
- if (strcmp(reloc.target_symbol, ".") == 0) {
- target_address += memory_offset() + reloc.section_offset;
+ intptr_t source_address = reloc.source_offset;
+ if (reloc.source_symbol != nullptr) {
+ auto* const source_symbol = symtab.Find(reloc.source_symbol);
+ ASSERT(source_symbol != nullptr);
+ source_address += source_symbol->offset;
} else {
- auto* const target_symbol = symtab->Find(reloc.target_symbol);
- if (target_symbol == nullptr) {
+ source_address += section_start + offset + reloc.section_offset;
+ }
+ ASSERT(reloc.size_in_bytes <= kWordSize);
+ word to_write = reloc.target_offset - source_address;
+ if (reloc.target_symbol != nullptr) {
+ if (auto* const symbol = symtab.Find(reloc.target_symbol)) {
+ to_write += symbol->offset;
+ } else {
ASSERT_EQUAL(strcmp(reloc.target_symbol, kSnapshotBuildIdAsmSymbol),
0);
ASSERT_EQUAL(reloc.target_offset, 0);
@@ -897,142 +815,378 @@
// TODO(dartbug.com/43516): Special case for snapshots with deferred
// sections that handles the build ID relocation in an
// InstructionsSection when there is no build ID.
- const word to_write = Image::kNoRelocatedAddress;
- stream->WriteBytes(reinterpret_cast<const uint8_t*>(&to_write),
- reloc.size_in_bytes);
- current_pos = reloc.section_offset + reloc.size_in_bytes;
- continue;
+ to_write = Image::kNoRelocatedAddress;
}
- target_address += target_symbol->offset();
+ } else {
+ to_write += section_start + offset + reloc.section_offset;
}
+ ASSERT(Utils::IsInt(reloc.size_in_bytes * kBitsPerByte, to_write));
+ stream->WriteBytes(reinterpret_cast<const uint8_t*>(&to_write),
+ reloc.size_in_bytes);
+ current_pos = reloc.section_offset + reloc.size_in_bytes;
}
- ASSERT(reloc.size_in_bytes <= kWordSize);
- const word to_write = target_address - source_address;
- ASSERT(Utils::IsInt(reloc.size_in_bytes * kBitsPerByte, to_write));
- stream->WriteBytes(reinterpret_cast<const uint8_t*>(&to_write),
- reloc.size_in_bytes);
- current_pos = reloc.section_offset + reloc.size_in_bytes;
+ stream->WriteBytes(bytes + current_pos, size - current_pos);
}
- stream->WriteBytes(bytes_ + current_pos, FileSize() - current_pos);
+
+ intptr_t offset;
+ const char* symbol_name;
+ const uint8_t* bytes;
+ intptr_t size;
+ const ZoneGrowableArray<Elf::Relocation>* relocations;
+ const ZoneGrowableArray<Elf::SymbolData>* symbols;
+
+ private:
+ DISALLOW_ALLOCATION();
+ };
+
+ const GrowableArray<Portion>& portions() const { return portions_; }
+
+ const Portion& AddPortion(
+ const uint8_t* bytes,
+ intptr_t size,
+ const ZoneGrowableArray<Elf::Relocation>* relocations = nullptr,
+ const ZoneGrowableArray<Elf::SymbolData>* symbols = nullptr,
+ const char* symbol_name = nullptr) {
+ ASSERT(IsNoBits() || bytes != nullptr);
+ ASSERT(bytes != nullptr || relocations == nullptr);
+ // Make sure all portions are consistent in containing bytes.
+ ASSERT(portions_.is_empty() || HasBytes() == (bytes != nullptr));
+ const intptr_t offset = Utils::RoundUp(total_size_, alignment);
+ portions_.Add({offset, symbol_name, bytes, size, relocations, symbols});
+ const Portion& portion = portions_.Last();
+ total_size_ = offset + size;
+ return portion;
}
- uint32_t Hash() const {
- ASSERT(bytes() != nullptr);
- return Utils::StringHash(bytes(), MemorySize());
+ void Write(ElfWriteStream* stream) const {
+ if (type == elf::SectionHeaderType::SHT_NOBITS) return;
+ intptr_t start_position = stream->Position(); // Used for checks.
+ for (const auto& portion : portions_) {
+ stream->Align(alignment);
+ ASSERT_EQUAL(stream->Position(), start_position + portion.offset);
+ portion.Write(stream, memory_offset());
+ }
+ ASSERT_EQUAL(stream->Position(), start_position + total_size_);
}
- intptr_t FileSize() const { return file_size_; }
- intptr_t MemorySize() const { return memory_size_; }
- const uint8_t* bytes() const { return bytes_; }
+ // Returns the hash for the portion corresponding to symbol_name.
+ // Returns 0 if the portion has no bytes or no portions have that name.
+ uint32_t Hash(const char* symbol_name) const {
+ for (const auto& portion : portions_) {
+ if (strcmp(symbol_name, portion.symbol_name) == 0) {
+ if (portion.bytes == nullptr) return 0;
+ const uint32_t hash = Utils::StringHash(portion.bytes, portion.size);
+ // Ensure a non-zero return.
+ return hash == 0 ? 1 : hash;
+ }
+ }
+ return 0;
+ }
+
+ intptr_t FileSize() const { return IsNoBits() ? 0 : total_size_; }
+ intptr_t MemorySize() const { return IsAllocated() ? total_size_ : 0; }
private:
- const intptr_t file_size_;
- const intptr_t memory_size_;
- const uint8_t* const bytes_;
- const ZoneGrowableArray<Elf::Relocation>* const relocations_;
- const ZoneGrowableArray<Elf::SymbolData>* const symbols_;
+ GrowableArray<Portion> portions_;
+ intptr_t total_size_ = 0;
};
+class NoteSection : public BitsContainer {
+ public:
+ NoteSection()
+ : BitsContainer(elf::SectionHeaderType::SHT_NOTE,
+ /*allocate=*/true,
+ /*executable=*/false,
+ /*writable=*/false,
+ kNoteAlignment) {}
+};
+
+// Abstract bits container that allows merging by just appending the portion
+// information (with properly adjusted offsets) of the other to this one.
+class ConcatenableBitsContainer : public BitsContainer {
+ public:
+ ConcatenableBitsContainer(Elf::Type type,
+ bool executable,
+ bool writable,
+ intptr_t alignment)
+ : BitsContainer(type, executable, writable, alignment) {}
+
+ virtual bool CanMergeWith(const Section& other) const = 0;
+ virtual void Merge(const Section& other) {
+ ASSERT(other.IsBitsContainer());
+ ASSERT(CanMergeWith(other));
+ for (const auto& portion : other.AsBitsContainer()->portions()) {
+ AddPortion(portion.bytes, portion.size, portion.relocations,
+ portion.symbols, portion.symbol_name);
+ }
+ }
+};
+
+class TextSection : public ConcatenableBitsContainer {
+ public:
+ explicit TextSection(Elf::Type t)
+ : ConcatenableBitsContainer(t,
+ /*executable=*/true,
+ /*writable=*/false,
+ ImageWriter::kTextAlignment) {}
+
+ DEFINE_TYPE_CHECK_FOR(TextSection);
+
+ virtual bool CanMergeWith(const Section& other) const {
+ return other.IsTextSection();
+ }
+};
+
+class DataSection : public ConcatenableBitsContainer {
+ public:
+ explicit DataSection(Elf::Type t)
+ : ConcatenableBitsContainer(t,
+ /*executable=*/false,
+ /*writable=*/false,
+ ImageWriter::kRODataAlignment) {}
+
+ DEFINE_TYPE_CHECK_FOR(DataSection);
+
+ virtual bool CanMergeWith(const Section& other) const {
+ return other.IsDataSection();
+ }
+};
+
+class BssSection : public ConcatenableBitsContainer {
+ public:
+ explicit BssSection(Elf::Type t)
+ : ConcatenableBitsContainer(t,
+ /*executable=*/false,
+ /*writable=*/true,
+ ImageWriter::kBssAlignment) {}
+
+ DEFINE_TYPE_CHECK_FOR(BssSection);
+
+ virtual bool CanMergeWith(const Section& other) const {
+ return other.IsBssSection();
+ }
+};
+
+// Represents portions of the file/memory space which do not correspond to
+// sections from the section header. Should never be added to the section table,
+// but may be added to segments.
+class PseudoSection : public Section {
+ public:
+ // All PseudoSections are aligned to target word size.
+ static const intptr_t kAlignment = compiler::target::kWordSize;
+
+ PseudoSection(bool allocate, bool executable, bool writable)
+ : Section(elf::SectionHeaderType::SHT_NULL,
+ allocate,
+ executable,
+ writable,
+ kAlignment) {}
+
+ DEFINE_TYPE_CHECK_FOR(PseudoSection)
+
+ void Write(ElfWriteStream* stream) const = 0;
+};
+
+class ProgramTable : public PseudoSection {
+ public:
+ explicit ProgramTable(Zone* zone)
+ : PseudoSection(/*allocate=*/true,
+ /*executable=*/false,
+ /*writable=*/false),
+ segments_(zone, 0) {
+ entry_size = sizeof(elf::ProgramHeader);
+ }
+
+ const GrowableArray<Segment*>& segments() const { return segments_; }
+ intptr_t SegmentCount() const { return segments_.length(); }
+ intptr_t MemorySize() const {
+ return segments_.length() * sizeof(elf::ProgramHeader);
+ }
+
+ void Add(Segment* segment) {
+ ASSERT(segment != nullptr);
+ segments_.Add(segment);
+ }
+
+ void Write(ElfWriteStream* stream) const;
+
+ private:
+ GrowableArray<Segment*> segments_;
+};
+
+// This particular PseudoSection should not appear in segments either (hence
+// being marked non-allocated), but is directly held by the Elf object.
+class SectionTable : public PseudoSection {
+ public:
+ explicit SectionTable(Zone* zone)
+ : PseudoSection(/*allocate=*/false,
+ /*executable=*/false,
+ /*writable=*/false),
+ zone_(zone),
+ sections_(zone_, 2),
+ shstrtab_(zone_, /*allocate=*/false) {
+ entry_size = sizeof(elf::SectionHeader);
+ // The section at index 0 (elf::SHN_UNDEF) must be all 0s.
+ ASSERT_EQUAL(shstrtab_.Lookup(""), 0);
+ Add(new (zone_) ReservedSection(), "");
+ Add(&shstrtab_, ".shstrtab");
+ }
+
+ const GrowableArray<Section*>& sections() const { return sections_; }
+ intptr_t SectionCount() const { return sections_.length(); }
+ intptr_t StringTableIndex() const { return shstrtab_.index; }
+
+ bool HasSectionNamed(const char* name) {
+ return shstrtab_.Lookup(name) != StringTable::kNotIndexed;
+ }
+
+ void Add(Section* section, const char* name = nullptr) {
+ ASSERT(!section->IsPseudoSection());
+ ASSERT(name != nullptr || section->name_is_set());
+ if (name != nullptr) {
+ // First, check for an existing section with the same table name.
+ if (auto* const old_section = Find(name)) {
+ ASSERT(old_section->CanMergeWith(*section));
+ old_section->Merge(*section);
+ return;
+ }
+ // No existing section with this name.
+ const intptr_t name_index = shstrtab_.Add(name);
+ section->set_name(name_index);
+ }
+ section->index = sections_.length();
+ sections_.Add(section);
+ }
+
+ Section* Find(const char* name) {
+ const intptr_t name_index = shstrtab_.Lookup(name);
+ if (name_index == StringTable::kNotIndexed) {
+ // We're guaranteed that no section with this name has been added yet.
+ return nullptr;
+ }
+ // We check walk all sections to check for uniqueness in DEBUG mode.
+ Section* result = nullptr;
+ for (Section* const section : sections_) {
+ if (section->name() == name_index) {
+#if defined(DEBUG)
+ ASSERT(result == nullptr);
+ result = section;
+#else
+ return section;
+#endif
+ }
+ }
+ return result;
+ }
+
+ intptr_t FileSize() const {
+ return sections_.length() * sizeof(elf::SectionHeader);
+ }
+
+ void Write(ElfWriteStream* stream) const;
+
+ // Reorders the sections for creating a minimal amount of segments and
+ // creates and returns an appropriate program table.
+ //
+ // Also takes and adjusts section indices in the static symbol table, since it
+ // is not recorded in sections_ for stripped outputs.
+ ProgramTable* CreateProgramTable(SymbolTable* symtab);
+
+ private:
+ Zone* const zone_;
+ GrowableArray<Section*> sections_;
+ StringTable shstrtab_;
+};
+
+class ElfHeader : public PseudoSection {
+ public:
+ ElfHeader(const ProgramTable& program_table,
+ const SectionTable& section_table)
+ : PseudoSection(/*allocate=*/true,
+ /*executable=*/false,
+ /*writable=*/false),
+ program_table_(program_table),
+ section_table_(section_table) {}
+
+ intptr_t MemorySize() const { return sizeof(elf::ElfHeader); }
+
+ void Write(ElfWriteStream* stream) const;
+
+ private:
+ const ProgramTable& program_table_;
+ const SectionTable& section_table_;
+};
+
+#undef DEFINE_TYPE_CHECK_FOR
+#undef FOR_EACH_SECTION_TYPE
+
Elf::Elf(Zone* zone, BaseWriteStream* stream, Type type, Dwarf* dwarf)
: zone_(zone),
unwrapped_stream_(stream),
type_(type),
dwarf_(dwarf),
- shstrtab_(new (zone) StringTable(zone, /*allocate=*/false)),
- dynstrtab_(new (zone) StringTable(zone, /*allocate=*/true)),
- dynsym_(new (zone) SymbolTable(zone, dynstrtab_, /*dynamic=*/true)),
- strtab_(new (zone_) StringTable(zone_, /*allocate=*/false)),
- symtab_(new (zone_) SymbolTable(zone, strtab_, /*dynamic=*/false)) {
+ section_table_(new (zone) SectionTable(zone)) {
// Separate debugging information should always have a Dwarf object.
ASSERT(type_ == Type::Snapshot || dwarf_ != nullptr);
// Assumed by various offset logic in this file.
ASSERT_EQUAL(unwrapped_stream_->Position(), 0);
}
-void Elf::AddSection(Section* section,
- const char* name,
- const char* symbol_name) {
- ASSERT(section_table_file_size_ < 0);
- ASSERT(!shstrtab_->HasBeenFinalized());
- section->set_name(shstrtab_->AddString(name));
- // We do not set the section index yet, that will be done during Finalize().
- sections_.Add(section);
- // We do set the initial section index in initialized symbols for quick lookup
- // until reordering happens.
- const intptr_t initial_section_index = sections_.length() - 1;
- if (symbol_name != nullptr) {
- ASSERT(section->IsAllocated());
- section->symbol_name = symbol_name;
- // While elf::STT_SECTION might seem more appropriate, section symbols are
- // usually local and dlsym won't return them.
- ASSERT(!dynsym_->HasBeenFinalized());
- dynsym_->AddSymbol(symbol_name, elf::STB_GLOBAL, elf::STT_FUNC,
- initial_section_index, section->MemorySize());
- // Some tools assume the static symbol table is a superset of the dynamic
- // symbol table when it exists (see dartbug.com/41783).
- ASSERT(!symtab_->HasBeenFinalized());
- symtab_->AddSymbol(symbol_name, elf::STB_GLOBAL, elf::STT_FUNC,
- initial_section_index, section->FileSize());
- }
- if (auto const container = section->AsBitsContainer()) {
- if (container->symbols() != nullptr) {
- ASSERT(section->IsAllocated());
- for (const auto& symbol_data : *container->symbols()) {
- ASSERT(!symtab_->HasBeenFinalized());
- symtab_->AddSymbol(symbol_data.name, elf::STB_LOCAL, symbol_data.type,
- initial_section_index, symbol_data.size);
- }
- }
- }
-}
-
void Elf::AddText(const char* name,
const uint8_t* bytes,
intptr_t size,
const ZoneGrowableArray<Relocation>* relocations,
const ZoneGrowableArray<SymbolData>* symbols) {
- auto const image =
- new (zone_) BitsContainer(type_, /*executable=*/true,
- /*writable=*/false, size, bytes, relocations,
- symbols, ImageWriter::kTextAlignment);
- AddSection(image, ".text", name);
+ auto* const container = new (zone_) TextSection(type_);
+ container->AddPortion(bytes, size, relocations, symbols, name);
+ section_table_->Add(container, kTextName);
}
-// Here, both VM and isolate will be compiled into a single snapshot.
-// In assembly generation, each serialized text section gets a separate
-// pointer into the BSS segment and BSS slots are created for each, since
-// we may not serialize both VM and isolate. Here, we always serialize both,
-// so make a BSS segment large enough for both, with the VM entries coming
-// first.
-static constexpr intptr_t kBssVmSize =
- BSS::kVmEntryCount * compiler::target::kWordSize;
-static constexpr intptr_t kBssIsolateSize =
- BSS::kIsolateEntryCount * compiler::target::kWordSize;
-static constexpr intptr_t kBssSize = kBssVmSize + kBssIsolateSize;
-
void Elf::CreateBSS() {
- uint8_t* bytes = nullptr;
- if (type_ == Type::Snapshot) {
- // Ideally the BSS segment would take no space in the object, but Android's
- // "strip" utility truncates the memory-size of our segments to their
- // file-size.
- //
- // Therefore we must insert zero-filled data for the BSS.
- bytes = zone_->Alloc<uint8_t>(kBssSize);
- memset(bytes, 0, kBssSize);
+ // Not idempotent.
+ ASSERT(section_table_->Find(kBssName) == nullptr);
+ // No text section means no BSS section.
+ auto* const text_section = section_table_->Find(kTextName);
+ if (text_section == nullptr) return;
+ ASSERT(text_section->IsTextSection());
+
+ auto* const bss_container = new (zone_) BssSection(type_);
+ for (const auto& portion : text_section->AsBitsContainer()->portions()) {
+ size_t size;
+ const char* symbol_name;
+ // First determine whether this is the VM's text portion or the isolate's.
+ if (strcmp(portion.symbol_name, kVmSnapshotInstructionsAsmSymbol) == 0) {
+ size = BSS::kVmEntryCount * compiler::target::kWordSize;
+ symbol_name = kVmSnapshotBssAsmSymbol;
+ } else if (strcmp(portion.symbol_name,
+ kIsolateSnapshotInstructionsAsmSymbol) == 0) {
+ size = BSS::kIsolateEntryCount * compiler::target::kWordSize;
+ symbol_name = kIsolateSnapshotBssAsmSymbol;
+ } else {
+ // Not VM or isolate text.
+ UNREACHABLE();
+ continue;
+ }
+
+ uint8_t* bytes = nullptr;
+ if (type_ == Type::Snapshot) {
+ // Ideally the BSS segment would take no space in the object, but
+ // Android's "strip" utility truncates the memory-size of our segments to
+ // their file-size.
+ //
+ // Therefore we must insert zero-filled data for the BSS.
+ bytes = zone_->Alloc<uint8_t>(size);
+ memset(bytes, 0, size);
+ }
+ // For the BSS section, we add the section symbols as local symbols in the
+ // static symbol table, as these addresses are only used for relocation.
+ // (This matches the behavior in the assembly output.)
+ auto* symbols = new (zone_) ZoneGrowableArray<Elf::SymbolData>();
+ symbols->Add({symbol_name, elf::STT_SECTION, 0, size});
+ bss_container->AddPortion(bytes, size, /*relocations=*/nullptr, symbols);
}
- // For the BSS section, we add two local symbols to the static symbol table,
- // one for each isolate. We use local symbols because these addresses are only
- // used for relocation. (This matches the behavior in the assembly output,
- // where these symbols are also local.)
- auto* bss_symbols = new (zone_) ZoneGrowableArray<Elf::SymbolData>();
- bss_symbols->Add({kVmSnapshotBssAsmSymbol, elf::STT_SECTION, 0, kBssVmSize});
- bss_symbols->Add({kIsolateSnapshotBssAsmSymbol, elf::STT_SECTION, kBssVmSize,
- kBssIsolateSize});
- bss_ = new (zone_) BitsContainer(
- type_, /*executable=*/false, /*writable=*/true, kBssSize, bytes,
- /*relocations=*/nullptr, bss_symbols, ImageWriter::kBssAlignment);
- AddSection(bss_, ".bss");
+
+ section_table_->Add(bss_container, kBssName);
}
void Elf::AddROData(const char* name,
@@ -1040,11 +1194,9 @@
intptr_t size,
const ZoneGrowableArray<Relocation>* relocations,
const ZoneGrowableArray<SymbolData>* symbols) {
- auto const image =
- new (zone_) BitsContainer(type_, /*executable=*/false,
- /*writable=*/false, size, bytes, relocations,
- symbols, ImageWriter::kRODataAlignment);
- AddSection(image, ".rodata", name);
+ auto* const container = new (zone_) DataSection(type_);
+ container->AddPortion(bytes, size, relocations, symbols, name);
+ section_table_->Add(container, kDataName);
}
#if defined(DART_PRECOMPILER)
@@ -1057,6 +1209,7 @@
const uint8_t* buffer() const { return stream_->buffer(); }
intptr_t bytes_written() const { return stream_->bytes_written(); }
+ intptr_t Position() const { return stream_->Position(); }
void sleb128(intptr_t value) { stream_->WriteSLEB128(value); }
void uleb128(uintptr_t value) { stream_->WriteLEB128(value); }
@@ -1092,12 +1245,12 @@
void OffsetFromSymbol(const char* symbol, intptr_t offset) {
relocations_->Add(
- {kAddressSize, stream_->Position(), nullptr, 0, symbol, offset});
+ {kAddressSize, stream_->Position(), "", 0, symbol, offset});
addr(0); // Resolved later.
}
template <typename T>
void RelativeSymbolOffset(const char* symbol) {
- relocations_->Add({sizeof(T), stream_->Position(), ".", 0, symbol, 0});
+ relocations_->Add({sizeof(T), stream_->Position(), nullptr, 0, symbol, 0});
stream_->WriteFixed<T>(0); // Resolved later.
}
void InitializeAbstractOrigins(intptr_t size) {
@@ -1143,43 +1296,79 @@
static constexpr intptr_t kInitialDwarfBufferSize = 64 * KB;
#endif
-const Section* Elf::FindSectionBySymbolName(const char* name) const {
- auto* const symbol = symtab_->Find(name);
- if (symbol == nullptr) return nullptr;
- // Should not be run between OrderSectionsAndCreateSegments (when section
- // indices may change) and FinalizeSymbols() (sets the final section index).
- ASSERT(segments_.length() == 0 || symbol->HasBeenFinalized());
- const Section* const section = sections_[symbol->section_index];
- ASSERT_EQUAL(strcmp(section->symbol_name, name), 0);
- return section;
-}
-
-void Elf::FinalizeSymbols() {
- // Must be run after OrderSectionsAndCreateSegments and ComputeOffsets.
- ASSERT(segments_.length() > 0);
- ASSERT(section_table_file_offset_ > 0);
- for (const auto& section : sections_) {
- if (section->symbol_name != nullptr) {
- dynsym_->FinalizeSymbol(section->symbol_name, section->index(),
- section->memory_offset());
- symtab_->FinalizeSymbol(section->symbol_name, section->index(),
- section->memory_offset());
- }
- if (auto const container = section->AsBitsContainer()) {
- if (container->symbols() != nullptr) {
- for (const auto& symbol_data : *container->symbols()) {
- symtab_->FinalizeSymbol(
- symbol_data.name, section->index(),
- section->memory_offset() + symbol_data.offset);
+void SymbolTable::Initialize(const GrowableArray<Section*>& sections) {
+ for (auto* const section : sections) {
+ // The values of all added symbols are memory addresses.
+ if (!section->IsAllocated()) continue;
+ if (auto* const bits = section->AsBitsContainer()) {
+ for (const auto& portion : section->AsBitsContainer()->portions()) {
+ if (portion.symbol_name != nullptr) {
+ // Global dynamic symbols for the content of a given section, which is
+ // always a single structured element (and thus we use STT_OBJECT).
+ const intptr_t binding = elf::STB_GLOBAL;
+ const intptr_t type = elf::STT_OBJECT;
+ // Some tools assume the static symbol table is a superset of the
+ // dynamic symbol table when it exists and only use it, so put all
+ // dynamic symbols there also. (see dartbug.com/41783).
+ AddSymbol(portion.symbol_name, binding, type, portion.size,
+ section->index, portion.offset);
+ }
+ if (!dynamic_ && portion.symbols != nullptr) {
+ for (const auto& symbol_data : *portion.symbols) {
+ // Local static-only symbols, e.g., code payloads or RO objects.
+ AddSymbol(symbol_data.name, elf::STB_LOCAL, symbol_data.type,
+ symbol_data.size, section->index,
+ portion.offset + symbol_data.offset);
+ }
}
}
}
}
}
+void Elf::InitializeSymbolTables() {
+ // Not idempotent.
+ ASSERT(symtab_ == nullptr);
+
+ // Create static and dynamic symbol tables.
+ auto* const dynstrtab = new (zone_) StringTable(zone_, /*allocate=*/true);
+ section_table_->Add(dynstrtab, ".dynstr");
+ auto* const dynsym =
+ new (zone_) SymbolTable(zone_, dynstrtab, /*dynamic=*/true);
+ section_table_->Add(dynsym, ".dynsym");
+ dynsym->Initialize(section_table_->sections());
+ // Now the dynamic symbol table is populated, set up the hash table and
+ // dynamic table.
+ auto* const hash = new (zone_) SymbolHashTable(zone_, dynsym);
+ section_table_->Add(hash, ".hash");
+ auto* const dynamic = new (zone_) DynamicTable(zone_, dynsym, hash);
+ section_table_->Add(dynamic, kDynamicTableName);
+
+ // We only add the static string and symbol tables to the section table if
+ // this is an unstripped output, but we always create them as they are used
+ // to resolve relocations.
+ auto* const strtab = new (zone_) StringTable(zone_, /*allocate=*/false);
+ if (!IsStripped()) {
+ section_table_->Add(strtab, ".strtab");
+ }
+ symtab_ = new (zone_) SymbolTable(zone_, strtab, /*dynamic=*/false);
+ if (!IsStripped()) {
+ section_table_->Add(symtab_, ".symtab");
+ }
+ symtab_->Initialize(section_table_->sections());
+}
+
void Elf::FinalizeEhFrame() {
-#if defined(DART_PRECOMPILER) && \
- (defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64))
+#if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64)
+ // No text section added means no .eh_frame.
+ TextSection* text_section = nullptr;
+ if (auto* const section = section_table_->Find(kTextName)) {
+ text_section = section->AsTextSection();
+ ASSERT(text_section != nullptr);
+ }
+ // No text section added means no .eh_frame.
+ if (text_section == nullptr) return;
+
// Multiplier which will be used to scale operands of DW_CFA_offset and
// DW_CFA_val_offset.
const intptr_t kDataAlignment = compiler::target::kWordSize;
@@ -1211,17 +1400,15 @@
});
// Emit an FDE covering each .text section.
- const auto text_name = shstrtab_->Lookup(".text");
- ASSERT(text_name != StringTable::kNotIndexed);
- for (auto section : sections_) {
- if (section->name() != text_name) continue;
+ for (const auto& portion : text_section->portions()) {
+ ASSERT(portion.symbol_name != nullptr); // Needed for relocations.
dwarf_stream.WritePrefixedLength([&]() {
// Offset to CIE. Note that unlike pcrel this offset is encoded
// backwards: it will be subtracted from the current position.
dwarf_stream.u4(stream.Position() - cie_start);
// Start address as a PC relative reference.
- dwarf_stream.RelativeSymbolOffset<int32_t>(section->symbol_name);
- dwarf_stream.u4(section->MemorySize()); // Size.
+ dwarf_stream.RelativeSymbolOffset<int32_t>(portion.symbol_name);
+ dwarf_stream.u4(portion.size); // Size.
dwarf_stream.u1(0); // Augmentation Data length.
// FP at FP+kSavedCallerPcSlotFromFp*kWordSize
@@ -1248,25 +1435,28 @@
});
}
- dwarf_stream.u4(0); // end of section
+ dwarf_stream.u4(0); // end of section (FDE with zero length)
- auto const eh_frame = new (zone_)
- BitsContainer(type_, /*writable=*/false, /*executable=*/false,
- dwarf_stream.bytes_written(), dwarf_stream.buffer(),
- dwarf_stream.relocations(), /*symbols=*/nullptr);
- AddSection(eh_frame, ".eh_frame");
-#endif // defined(DART_PRECOMPILER) && \
- // (defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64))
+ auto* const eh_frame = new (zone_)
+ BitsContainer(type_, /*writable=*/false, /*executable=*/false);
+ eh_frame->AddPortion(dwarf_stream.buffer(), dwarf_stream.bytes_written(),
+ dwarf_stream.relocations());
+ section_table_->Add(eh_frame, ".eh_frame");
+#endif // defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64)
}
void Elf::FinalizeDwarfSections() {
if (dwarf_ == nullptr) return;
-#if defined(DART_PRECOMPILER)
+
+ // Currently we only output DWARF information involving code.
+ ASSERT(section_table_->HasSectionNamed(kTextName));
+
auto add_debug = [&](const char* name, const DwarfElfStream& stream) {
- auto const image = new (zone_) BitsContainer(
- elf::SectionHeaderType::SHT_PROGBITS, stream.bytes_written(),
- stream.buffer(), stream.relocations(), /*symbols=*/nullptr);
- AddSection(image, name);
+ auto const container =
+ new (zone_) BitsContainer(elf::SectionHeaderType::SHT_PROGBITS);
+ container->AddPortion(stream.buffer(), stream.bytes_written(),
+ stream.relocations());
+ section_table_->Add(container, name);
};
{
ZoneWriteStream stream(zone(), kInitialDwarfBufferSize);
@@ -1288,148 +1478,240 @@
dwarf_->WriteLineNumberProgram(&dwarf_stream);
add_debug(".debug_line", dwarf_stream);
}
-#endif
}
-void Elf::OrderSectionsAndCreateSegments() {
- GrowableArray<Section*> reordered_sections;
- // The first section in the section header table is always a reserved
- // entry containing only 0 values.
- reordered_sections.Add(new (zone_) ReservedSection());
+ProgramTable* SectionTable::CreateProgramTable(SymbolTable* symtab) {
+ const intptr_t num_sections = sections_.length();
+ // Should have at least the reserved entry in sections_.
+ ASSERT(!sections_.is_empty());
+ ASSERT_EQUAL(sections_[0]->alignment, 0);
+
+ // The new program table that collects the segments for allocated sections
+ // and a few special segments.
+ auto* const program_table = new (zone_) ProgramTable(zone_);
+
+ GrowableArray<Section*> reordered_sections(zone_, num_sections);
+ // Maps the old indices of sections to the new ones.
+ GrowableArray<intptr_t> index_map(zone_, num_sections);
+ index_map.FillWith(0, 0, num_sections);
Segment* current_segment = nullptr;
+ // Only called for sections in the section table (i.e., not special sections
+ // appearing in segments only or the section table itself).
auto add_to_reordered_sections = [&](Section* section) {
- section->set_index(reordered_sections.length());
+ intptr_t new_index = reordered_sections.length();
+ index_map[section->index] = new_index;
+ section->index = new_index;
reordered_sections.Add(section);
- if (!section->IsAllocated()) return;
- const bool was_added =
- current_segment == nullptr ? false : current_segment->Add(section);
- if (!was_added) {
- // There is no current segment or it is incompatible for merging, so
- // following compatible segments will be merged into this one if possible.
- current_segment =
- new (zone_) Segment(zone_, section, elf::ProgramHeaderType::PT_LOAD);
- section->load_segment = current_segment;
- segments_.Add(current_segment);
+ if (section->IsAllocated()) {
+ ASSERT(current_segment != nullptr);
+ if (!current_segment->Add(section)) {
+ // The current segment is incompatible for the current sectioni, so
+ // create a new one.
+ current_segment = new (zone_)
+ Segment(zone_, section, elf::ProgramHeaderType::PT_LOAD);
+ program_table->Add(current_segment);
+ }
}
};
- // Add writable, non-executable sections first, due to a bug in Jelly Bean's
- // ELF loader when a writable segment is placed between two non-writable
- // segments. See also Elf::WriteProgramTable(), which double-checks this.
- for (auto* const section : sections_) {
- if (section->IsAllocated() && section->IsWritable() &&
- !section->IsExecutable()) {
- add_to_reordered_sections(section);
- }
+ // The first section in the section header table is always a reserved
+ // entry containing only 0 values, so copy it over from sections_.
+ add_to_reordered_sections(sections_[0]);
+
+ // There are few important invariants originating from Android idiosyncrasies
+ // we are trying to maintain when ordering sections:
+ //
+ // - Android requires the program header table be in the first load segment,
+ // so create PseudoSections representing the ELF header and program header
+ // table to initialize that segment.
+ //
+ // - The Android dynamic linker in Jelly Bean incorrectly assumes that all
+ // non-writable segments are continguous. Thus we write them all together.
+ // The bug is here: https://github.com/aosp-mirror/platform_bionic/blob/94963af28e445384e19775a838a29e6a71708179/linker/linker.c#L1991-L2001
+ //
+ // - On Android native libraries can be mapped directly from an APK
+ // they are stored uncompressed in it. In such situations the name
+ // of the mapping no longer provides enough information for libunwindstack
+ // to find the original ELF file and instead it has to rely on heuristics
+ // to locate program header table. These heuristics currently assume that
+ // program header table will be located in the RO mapping which precedes
+ // RX mapping.
+ //
+ // These invariants imply the following order of segments: RO (program
+ // header, .note.gnu.build-id, .dynstr, .dynsym, .hash, .rodata
+ // and .eh_frame), RX (.text), RW (.dynamic and .bss).
+ //
+ auto* const elf_header = new (zone_) ElfHeader(*program_table, *this);
+
+ // Self-reference to program header table. Required by Android but not by
+ // Linux. Must appear before any PT_LOAD entries.
+ program_table->Add(new (zone_) Segment(zone_, program_table,
+ elf::ProgramHeaderType::PT_PHDR));
+
+ // Create the initial load segment which contains the ELF header and program
+ // table.
+ current_segment =
+ new (zone_) Segment(zone_, elf_header, elf::ProgramHeaderType::PT_LOAD);
+ program_table->Add(current_segment);
+ current_segment->Add(program_table);
+
+ // We now do several passes over the collected sections to reorder them in
+ // a way that minimizes segments (and thus padding) in the resulting snapshot.
+
+ // If a build ID was created, we put it after the program table so it can
+ // be read with a minimum number of bytes from the ELF file.
+ auto* const build_id = Find(Elf::kBuildIdNoteName);
+ if (build_id != nullptr) {
+ ASSERT(build_id->type == elf::SectionHeaderType::SHT_NOTE);
+ add_to_reordered_sections(build_id);
}
- // Now add the non-writable, non-executable allocated sections in a new
- // segment, starting with the data sections.
+ // Now add the other non-writable, non-executable allocated sections.
for (auto* const section : sections_) {
+ if (section == build_id) continue; // Already added.
if (section->IsAllocated() && !section->IsWritable() &&
!section->IsExecutable()) {
add_to_reordered_sections(section);
}
}
- // Now add the non-writable, executable sections in a new segment.
+ // Now add the executable sections in a new segment.
for (auto* const section : sections_) {
- if (section->IsAllocated() && !section->IsWritable() &&
- section->IsExecutable()) {
+ if (section->IsExecutable()) { // Implies IsAllocated() && !IsWritable()
add_to_reordered_sections(section);
}
}
- // We put all unallocated sections last because otherwise, they would
+ // Now add all the writable sections.
+ for (auto* const section : sections_) {
+ if (section->IsWritable()) { // Implies IsAllocated() && !IsExecutable()
+ add_to_reordered_sections(section);
+ }
+ }
+
+ // We put all non-reserved unallocated sections last. Otherwise, they would
// affect the file offset but not the memory offset of any following allocated
// sections. Doing it in this order makes it easier to keep file and memory
// offsets page-aligned with respect to each other, which is required for
// some loaders.
- for (auto* const section : sections_) {
- if (!section->IsAllocated()) {
- add_to_reordered_sections(section);
- }
+ for (intptr_t i = 1; i < num_sections; i++) {
+ auto* const section = sections_[i];
+ if (section->IsAllocated()) continue;
+ add_to_reordered_sections(section);
}
- // Now replace sections_.
+ // All sections should have been accounted for in the loops above.
+ ASSERT_EQUAL(sections_.length(), reordered_sections.length());
+ // Replace the content of sections_ with the reordered sections.
sections_.Clear();
sections_.AddArray(reordered_sections);
-}
-void Elf::Finalize() {
- ASSERT(program_table_file_size_ < 0);
+ // This must be true for uses of the map to be correct.
+ ASSERT_EQUAL(index_map[elf::SHN_UNDEF], elf::SHN_UNDEF);
- // Generate the build ID now that we have all user-provided sections.
- // Generating it at this point also means it'll be the first writable
- // non-executable section added to sections_ and thus end up right after the
- // program table after reordering. This limits how much of the ELF file needs
- // to be read to get the build ID (header + program table + note segment).
- GenerateBuildId();
-
- // We add BSS in all cases, even to the separate debugging information ELF,
- // to ensure that relocated addresses are consistent between ELF snapshots
- // and ELF separate debugging information.
- CreateBSS();
-
- // Adding the dynamic symbol table and associated sections.
- AddSection(dynstrtab_, ".dynstr");
- AddSection(dynsym_, ".dynsym");
-
- auto const hash = new (zone_) SymbolHashTable(zone_, dynstrtab_, dynsym_);
- AddSection(hash, ".hash");
-
- auto const dynamic = new (zone_) DynamicTable(zone_);
- AddSection(dynamic, ".dynamic");
-
- if (!IsStripped()) {
- AddSection(strtab_, ".strtab");
- AddSection(symtab_, ".symtab");
+ // Since the section indices have been updated, change links to match
+ // and update the indexes of symbols in any symbol tables.
+ for (auto* const section : sections_) {
+ // SHN_UNDEF maps to SHN_UNDEF, so no need to check for it.
+ section->link = index_map[section->link];
+ if (auto* const table = section->AsSymbolTable()) {
+ table->UpdateSectionIndices(index_map);
+ }
}
- AddSection(shstrtab_, ".shstrtab");
- FinalizeEhFrame();
- FinalizeDwarfSections();
-
- OrderSectionsAndCreateSegments();
-
- // Now that the sections have indices, set up links between them as needed.
- dynsym_->link = dynstrtab_->index();
- hash->link = dynsym_->index();
- dynamic->link = dynstrtab_->index();
- if (!IsStripped()) {
- symtab_->link = strtab_->index();
+ if (symtab->index == elf::SHN_UNDEF) {
+ // The output is stripped, so this wasn't finalized during the loop above.
+ symtab->UpdateSectionIndices(index_map);
}
- // Now add any special non-load segments.
-
- if (build_id_ != nullptr) {
+ // Add any special non-load segments.
+ if (build_id != nullptr) {
// Add a PT_NOTE segment for the build ID.
- segments_.Add(new (zone_) NoteSegment(zone_, build_id_));
+ program_table->Add(
+ new (zone_) Segment(zone_, build_id, elf::ProgramHeaderType::PT_NOTE));
}
// Add a PT_DYNAMIC segment for the dynamic symbol table.
- segments_.Add(new (zone_) DynamicSegment(zone_, dynamic));
+ ASSERT(HasSectionNamed(Elf::kDynamicTableName));
+ auto* const dynamic = Find(Elf::kDynamicTableName)->AsDynamicTable();
+ program_table->Add(
+ new (zone_) Segment(zone_, dynamic, elf::ProgramHeaderType::PT_DYNAMIC));
- // At this point, all sections have been added and ordered and all sections
- // appropriately grouped into segments. Add the program table and then
- // calculate file and memory offsets.
- FinalizeProgramTable();
+ return program_table;
+}
+
+void Elf::Finalize() {
+ // Generate the build ID now that we have all user-provided sections.
+ GenerateBuildId();
+
+ // We add a BSS section in all cases, even to the separate debugging
+ // information, to ensure that relocated addresses are consistent between ELF
+ // snapshots and the corresponding separate debugging information.
+ CreateBSS();
+
+ FinalizeEhFrame();
+ FinalizeDwarfSections();
+
+ // Create and initialize the dynamic and static symbol tables and any
+ // other associated sections now that all other sections have been added.
+ InitializeSymbolTables();
+ // Creates an appropriate program table containing load segments for allocated
+ // sections and any other segments needed. May reorder sections to minimize
+ // the number of load segments, so also takes the static symbol table so
+ // symbol section indices can be adjusted if needed.
+ program_table_ = section_table_->CreateProgramTable(symtab_);
+ // Calculate file and memory offsets, and finalizes symbol values in any
+ // symbol tables.
ComputeOffsets();
- // Now that we have reordered the sections and set memory offsets, we can
- // update the symbol tables to add index and address information. This must
- // be done prior to writing the symbol tables and any sections with
- // relocations.
- FinalizeSymbols();
- // Also update the entries in the dynamic table.
- dynamic->FinalizeEntries(dynstrtab_, dynsym_, hash);
+#if defined(DEBUG)
+ if (type_ == Type::Snapshot) {
+ // For files that will be dynamically loaded, ensure the file offsets
+ // of allocated sections are page aligned to the memory offsets.
+ for (auto* const segment : program_table_->segments()) {
+ for (auto* const section : segment->sections()) {
+ ASSERT_EQUAL(section->file_offset() % Elf::kPageSize,
+ section->memory_offset() % Elf::kPageSize);
+ }
+ }
+ }
+#endif
// Finally, write the ELF file contents.
ElfWriteStream wrapped(unwrapped_stream_, *this);
- WriteHeader(&wrapped);
- WriteProgramTable(&wrapped);
- WriteSections(&wrapped);
- WriteSectionTable(&wrapped);
+
+ auto write_section = [&](const Section* section) {
+ wrapped.Align(section->alignment);
+ ASSERT_EQUAL(wrapped.Position(), section->file_offset());
+ section->Write(&wrapped);
+ ASSERT_EQUAL(wrapped.Position(),
+ section->file_offset() + section->FileSize());
+ };
+
+ // To match ComputeOffsets, first we write allocated sections and then
+ // unallocated sections. We access the allocated sections via the load
+ // segments so we can properly align the stream for each entered segment.
+ intptr_t section_index = 1; // We don't visit the reserved section.
+ for (auto* const segment : program_table_->segments()) {
+ if (segment->type != elf::ProgramHeaderType::PT_LOAD) continue;
+ wrapped.Align(segment->Alignment());
+ for (auto* const section : segment->sections()) {
+ ASSERT(section->IsAllocated());
+ write_section(section);
+ if (!section->IsPseudoSection()) {
+ ASSERT_EQUAL(section->index, section_index);
+ section_index++;
+ }
+ }
+ }
+ const auto& sections = section_table_->sections();
+ for (; section_index < sections.length(); section_index++) {
+ auto* const section = sections[section_index];
+ ASSERT(!section->IsAllocated());
+ write_section(section);
+ }
+ // Finally, write the section table.
+ write_section(section_table_);
}
// For the build ID, we generate a 128-bit hash, where each 32 bits is a hash of
@@ -1449,32 +1731,40 @@
sizeof(elf::Note) + sizeof(elf::ELF_NOTE_GNU);
void Elf::GenerateBuildId() {
+ // Not idempotent.
+ ASSERT(section_table_->Find(kBuildIdNoteName) == nullptr);
uint32_t hashes[kBuildIdSegmentNamesLength];
+ // Currently, we construct the build ID out of data from two different
+ // sections: the .text section and the .rodata section. We only create
+ // a build ID when we have all four sections and when we have the actual
+ // bytes from those sections.
+ //
+ // TODO(dartbug.com/43274): Generate build IDs for separate debugging
+ // information for assembly snapshots.
+ //
+ // TODO(dartbug.com/43516): Generate build IDs for snapshots with deferred
+ // sections.
+ auto* const text_section = section_table_->Find(kTextName);
+ if (text_section == nullptr) return;
+ ASSERT(text_section->IsTextSection());
+ auto* const text_bits = text_section->AsBitsContainer();
+ auto* const data_section = section_table_->Find(kDataName);
+ if (data_section == nullptr) return;
+ ASSERT(data_section->IsDataSection());
+ auto* const data_bits = data_section->AsBitsContainer();
+ // Now try to find
for (intptr_t i = 0; i < kBuildIdSegmentNamesLength; i++) {
- auto const name = kBuildIdSegmentNames[i];
- auto const section = FindSectionBySymbolName(name);
- // If we're missing a section, then we don't generate a final build ID.
- if (section == nullptr) return;
- auto const bits = section->AsBitsContainer();
- if (bits == nullptr) {
- FATAL1("Section for symbol %s is not a BitsContainer", name);
+ auto* const name = kBuildIdSegmentNames[i];
+ hashes[i] = text_bits->Hash(name);
+ if (hashes[i] == 0) {
+ hashes[i] = data_bits->Hash(name);
}
- // For now, if we don't have section contents (because we're generating
- // assembly), don't generate a final build ID, as we'll have different
- // build IDs in the snapshot and the separate debugging information.
- //
- // TODO(dartbug.com/43274): Change once we generate consistent build IDs
- // between assembly snapshots and their debugging information.
- if (bits->bytes() == nullptr) return;
- hashes[i] = bits->Hash();
+ // The symbol wasn't found in either section or there were no bytes
+ // associated with the symbol.
+ if (hashes[i] == 0) return;
}
auto const description_bytes = reinterpret_cast<uint8_t*>(hashes);
const size_t description_length = sizeof(hashes);
- // To ensure we can quickly check for a final build ID, we ensure the first
- // byte contains a non-zero value.
- if (description_bytes[0] == 0) {
- description_bytes[0] = 1;
- }
// Now that we have the description field contents, create the section.
ZoneWriteStream stream(zone(), kBuildIdHeaderSize + description_length);
stream.WriteFixed<decltype(elf::Note::name_size)>(sizeof(elf::ELF_NOTE_GNU));
@@ -1484,101 +1774,93 @@
stream.WriteBytes(elf::ELF_NOTE_GNU, sizeof(elf::ELF_NOTE_GNU));
ASSERT_EQUAL(stream.bytes_written(), kBuildIdHeaderSize);
stream.WriteBytes(description_bytes, description_length);
- // While the build ID section does not need to be writable, the first segment
- // in our ELF files is writable (see Elf::WriteProgramTable) and so this
- // ensures we can put it right after the program table without padding.
- build_id_ = new (zone_) BitsContainer(
- elf::SectionHeaderType::SHT_NOTE,
- /*allocate=*/true, /*executable=*/false,
- /*writable=*/true, stream.bytes_written(), stream.buffer(),
- /*relocations=*/nullptr, /*symbols=*/nullptr, kNoteAlignment);
- AddSection(build_id_, kBuildIdNoteName, kSnapshotBuildIdAsmSymbol);
+ auto* const container = new (zone_) NoteSection();
+ container->AddPortion(stream.buffer(), stream.bytes_written(),
+ /*relocations=*/nullptr, /*symbols=*/nullptr,
+ kSnapshotBuildIdAsmSymbol);
+ section_table_->Add(container, kBuildIdNoteName);
}
-void Elf::FinalizeProgramTable() {
- ASSERT(program_table_file_size_ < 0);
-
- program_table_file_offset_ = sizeof(elf::ElfHeader);
-
- // There is one additional segment we need the size of the program table to
- // create, so calculate it as if that segment were already in place.
- program_table_file_size_ =
- (1 + segments_.length()) * sizeof(elf::ProgramHeader);
-
- auto const program_table_segment_size =
- program_table_file_offset_ + program_table_file_size_;
-
- // Segment for loading the initial part of the ELF file, including the
- // program header table. Required by Android but not by Linux.
- Segment* const initial_load =
- new (zone_) ProgramTableLoadSegment(zone_, program_table_segment_size);
- // Merge the initial writable segment into this one and replace it (so it
- // doesn't change the number of segments).
- const bool was_merged = initial_load->Merge(segments_[0]);
- ASSERT(was_merged);
- segments_[0] = initial_load;
-
- // Self-reference to program header table. Required by Android but not by
- // Linux. Must appear before any PT_LOAD entries.
- segments_.InsertAt(
- 0, new (zone_) ProgramTableSelfSegment(zone_, program_table_file_offset_,
- program_table_file_size_));
-}
-
-static const intptr_t kElfSectionTableAlignment = compiler::target::kWordSize;
-
void Elf::ComputeOffsets() {
- // We calculate the size and offset of the program header table during
- // finalization.
- ASSERT(program_table_file_offset_ > 0 && program_table_file_size_ > 0);
- intptr_t file_offset = program_table_file_offset_ + program_table_file_size_;
- // Program table memory size is same as file size.
- intptr_t memory_offset = file_offset;
+ intptr_t file_offset = 0;
+ intptr_t memory_offset = 0;
- // When calculating memory and file offsets for sections, we'll need to know
- // if we've changed segments. Start with the one for the program table.
- ASSERT(segments_[0]->type != elf::ProgramHeaderType::PT_LOAD);
- const auto* current_segment = segments_[1];
- ASSERT(current_segment->type == elf::ProgramHeaderType::PT_LOAD);
+ // Maps indices of allocated sections in the section table to memory offsets.
+ const intptr_t num_sections = section_table_->SectionCount();
+ GrowableArray<intptr_t> address_map(zone_, num_sections);
+ address_map.Add(0); // Don't adjust offsets for symbols with index SHN_UNDEF.
- // The non-reserved sections are output to the file in order after the program
- // header table. If we're entering a new segment, then we need to align
- // according to the PT_LOAD segment alignment as well to keep the file offsets
- // aligned with the memory addresses.
- for (intptr_t i = 1; i < sections_.length(); i++) {
- auto const section = sections_[i];
+ auto calculate_section_offsets = [&](Section* section) {
file_offset = Utils::RoundUp(file_offset, section->alignment);
- memory_offset = Utils::RoundUp(memory_offset, section->alignment);
- if (section->IsAllocated() && section->load_segment != current_segment) {
- current_segment = section->load_segment;
- ASSERT(current_segment->type == elf::ProgramHeaderType::PT_LOAD);
- const intptr_t load_align = Segment::Alignment(current_segment->type);
- file_offset = Utils::RoundUp(file_offset, load_align);
- memory_offset = Utils::RoundUp(memory_offset, load_align);
- }
section->set_file_offset(file_offset);
- if (section->IsAllocated()) {
- section->set_memory_offset(memory_offset);
-#if defined(DEBUG)
- if (type_ == Type::Snapshot) {
- // For files that will be dynamically loaded, make sure the file offsets
- // of allocated sections are page aligned to the memory offsets.
- ASSERT_EQUAL(section->file_offset() % Elf::kPageSize,
- section->memory_offset() % Elf::kPageSize);
- }
-#endif
- }
file_offset += section->FileSize();
- memory_offset += section->MemorySize();
+ if (section->IsAllocated()) {
+ memory_offset = Utils::RoundUp(memory_offset, section->alignment);
+ section->set_memory_offset(memory_offset);
+ memory_offset += section->MemorySize();
+ }
+ };
+
+ intptr_t section_index = 1; // We don't visit the reserved section.
+ for (auto* const segment : program_table_->segments()) {
+ if (segment->type != elf::ProgramHeaderType::PT_LOAD) continue;
+ // Adjust file and memory offsets for segment alignment on entry.
+ file_offset = Utils::RoundUp(file_offset, segment->Alignment());
+ memory_offset = Utils::RoundUp(memory_offset, segment->Alignment());
+ for (auto* const section : segment->sections()) {
+ ASSERT(section->IsAllocated());
+ calculate_section_offsets(section);
+ if (!section->IsPseudoSection()) {
+ // Note: this assumes that the sections in the section header has all
+ // allocated sections before all (non-reserved) unallocated sections and
+ // in the same order as the load segments in in the program table.
+ address_map.Add(section->memory_offset());
+ ASSERT_EQUAL(section->index, section_index);
+ section_index++;
+ }
+ }
}
- file_offset = Utils::RoundUp(file_offset, kElfSectionTableAlignment);
- section_table_file_offset_ = file_offset;
- section_table_file_size_ = sections_.length() * sizeof(elf::SectionHeader);
- file_offset += section_table_file_size_;
+ const auto& sections = section_table_->sections();
+ for (; section_index < sections.length(); section_index++) {
+ auto* const section = sections[section_index];
+ ASSERT(!section->IsAllocated());
+ calculate_section_offsets(section);
+ }
+
+ ASSERT_EQUAL(section_index, sections.length());
+ // Now that all sections have been handled, set the file offset for the
+ // section table, as it will be written after the last section.
+ calculate_section_offsets(section_table_);
+
+#if defined(DEBUG)
+ // Double check that segment starts are aligned as expected.
+ for (auto* const segment : program_table_->segments()) {
+ ASSERT(Utils::IsAligned(segment->MemoryOffset(), segment->Alignment()));
+ }
+#endif
+
+ // This must be true for uses of the map to be correct.
+ ASSERT_EQUAL(address_map[elf::SHN_UNDEF], 0);
+ // Adjust addresses in symbol tables as we now have section memory offsets.
+ // Also finalize the entries of the dynamic table, as some are memory offsets.
+ for (auto* const section : sections) {
+ if (auto* const table = section->AsSymbolTable()) {
+ table->Finalize(address_map);
+ } else if (auto* const dynamic = section->AsDynamicTable()) {
+ dynamic->Finalize();
+ }
+ }
+ // Also adjust addresses in symtab for stripped snapshots.
+ if (IsStripped()) {
+ ASSERT_EQUAL(symtab_->index, elf::SHN_UNDEF);
+ symtab_->Finalize(address_map);
+ }
}
-void Elf::WriteHeader(ElfWriteStream* stream) {
+void ElfHeader::Write(ElfWriteStream* stream) const {
+ ASSERT_EQUAL(file_offset(), 0);
+ ASSERT_EQUAL(memory_offset(), 0);
#if defined(TARGET_ARCH_IS_32_BIT)
uint8_t size = elf::ELFCLASS32;
#else
@@ -1618,8 +1900,8 @@
stream->WriteWord(elf::EV_CURRENT); // Version
stream->WriteAddr(0); // "Entry point"
- stream->WriteOff(program_table_file_offset_);
- stream->WriteOff(section_table_file_offset_);
+ stream->WriteOff(program_table_.file_offset());
+ stream->WriteOff(section_table_.file_offset());
#if defined(TARGET_ARCH_ARM)
uword flags = elf::EF_ARM_ABI | (TargetCPUFeatures::hardfp_supported()
@@ -1631,26 +1913,32 @@
stream->WriteWord(flags);
stream->WriteHalf(sizeof(elf::ElfHeader));
- stream->WriteHalf(sizeof(elf::ProgramHeader));
- stream->WriteHalf(segments_.length());
- stream->WriteHalf(sizeof(elf::SectionHeader));
- stream->WriteHalf(sections_.length());
- stream->WriteHalf(shstrtab_->index());
-
- ASSERT_EQUAL(stream->Position(), sizeof(elf::ElfHeader));
+ stream->WriteHalf(program_table_.entry_size);
+ stream->WriteHalf(program_table_.SegmentCount());
+ stream->WriteHalf(section_table_.entry_size);
+ stream->WriteHalf(section_table_.SectionCount());
+ stream->WriteHalf(stream->elf().section_table().StringTableIndex());
}
-void Elf::WriteProgramTable(ElfWriteStream* stream) {
- ASSERT(program_table_file_size_ >= 0); // Check for finalization.
- ASSERT(stream->Position() == program_table_file_offset_);
+void ProgramTable::Write(ElfWriteStream* stream) const {
+ ASSERT(segments_.length() > 0);
+ // Make sure all relevant segments were created by checking the type of the
+ // first.
+ ASSERT(segments_[0]->type == elf::ProgramHeaderType::PT_PHDR);
+ const intptr_t start = stream->Position();
+ // Should be immediately following the ELF header.
+ ASSERT_EQUAL(start, sizeof(elf::ElfHeader));
#if defined(DEBUG)
// Here, we count the number of times that a PT_LOAD writable segment is
- // followed by a non-writable segment. We initialize last_writable to true so
- // that we catch the case where the first segment is non-writable.
+ // followed by a non-writable segment. We initialize last_writable to true
+ // so that we catch the case where the first segment is non-writable.
bool last_writable = true;
int non_writable_groups = 0;
#endif
- for (auto const segment : segments_) {
+ for (intptr_t i = 0; i < segments_.length(); i++) {
+ const Segment* const segment = segments_[i];
+ ASSERT(segment->type != elf::ProgramHeaderType::PT_NULL);
+ ASSERT_EQUAL(i == 0, segment->type == elf::ProgramHeaderType::PT_PHDR);
#if defined(DEBUG)
if (segment->type == elf::ProgramHeaderType::PT_LOAD) {
if (last_writable && !segment->IsWritable()) {
@@ -1662,7 +1950,7 @@
const intptr_t start = stream->Position();
segment->WriteProgramHeader(stream);
const intptr_t end = stream->Position();
- ASSERT_EQUAL(end - start, sizeof(elf::ProgramHeader));
+ ASSERT_EQUAL(end - start, entry_size);
}
#if defined(DEBUG)
// All PT_LOAD non-writable segments must be contiguous. If not, some older
@@ -1672,49 +1960,16 @@
#endif
}
-void Elf::WriteSectionTable(ElfWriteStream* stream) {
- ASSERT(section_table_file_size_ >= 0); // Check for finalization.
- stream->Align(kElfSectionTableAlignment);
- ASSERT_EQUAL(stream->Position(), section_table_file_offset_);
-
- for (auto const section : sections_) {
+void SectionTable::Write(ElfWriteStream* stream) const {
+ for (intptr_t i = 0; i < sections_.length(); i++) {
+ const Section* const section = sections_[i];
+ ASSERT_EQUAL(i == 0, section->IsReservedSection());
+ ASSERT_EQUAL(section->index, i);
+ ASSERT(section->link < sections_.length());
const intptr_t start = stream->Position();
section->WriteSectionHeader(stream);
const intptr_t end = stream->Position();
- ASSERT_EQUAL(end - start, sizeof(elf::SectionHeader));
- }
-}
-
-void Elf::WriteSections(ElfWriteStream* stream) {
- ASSERT(section_table_file_size_ >= 0); // Check for finalization.
- // Should be writing the first section immediately after the program table.
- ASSERT_EQUAL(stream->Position(),
- program_table_file_offset_ + program_table_file_size_);
- // Skip the reserved first section, as its alignment is 0 (which will cause
- // stream->Align() to fail) and it never contains file contents anyway.
- ASSERT_EQUAL(static_cast<uint32_t>(sections_[0]->type),
- static_cast<uint32_t>(elf::SectionHeaderType::SHT_NULL));
- ASSERT_EQUAL(sections_[0]->alignment, 0);
- // The program table is considered part of the first load segment (the
- // second segment in segments_), so other sections in the same segment should
- // not have extra segment alignment added.
- ASSERT(segments_[0]->type != elf::ProgramHeaderType::PT_LOAD);
- const Segment* current_segment = segments_[1];
- ASSERT(current_segment->type == elf::ProgramHeaderType::PT_LOAD);
- for (intptr_t i = 1; i < sections_.length(); i++) {
- Section* section = sections_[i];
- stream->Align(section->alignment);
- if (section->IsAllocated() && section->load_segment != current_segment) {
- // Changing segments, so align accordingly.
- current_segment = section->load_segment;
- ASSERT(current_segment->type == elf::ProgramHeaderType::PT_LOAD);
- const intptr_t load_align = Segment::Alignment(current_segment->type);
- stream->Align(load_align);
- }
- ASSERT_EQUAL(stream->Position(), section->file_offset());
- section->Write(stream);
- ASSERT_EQUAL(stream->Position(),
- section->file_offset() + section->FileSize());
+ ASSERT_EQUAL(end - start, entry_size);
}
}
diff --git a/runtime/vm/elf.h b/runtime/vm/elf.h
index c98f423..579c49f 100644
--- a/runtime/vm/elf.h
+++ b/runtime/vm/elf.h
@@ -16,10 +16,9 @@
#if defined(DART_PRECOMPILER)
class Dwarf;
-class ElfWriteStream;
+class ProgramTable;
class Section;
-class Segment;
-class StringTable;
+class SectionTable;
class SymbolTable;
class Elf : public ZoneAllocated {
@@ -34,21 +33,28 @@
Elf(Zone* zone, BaseWriteStream* stream, Type type, Dwarf* dwarf = nullptr);
+ // The max page size on all supported architectures. Used to determine
+ // the alignment of load segments, so that they are guaranteed page-aligned,
+ // and no ELF section or segment should have a larger alignment.
static constexpr intptr_t kPageSize = 16 * KB;
- static constexpr uword kNoSectionStart = 0;
bool IsStripped() const { return dwarf_ == nullptr; }
Zone* zone() const { return zone_; }
const Dwarf* dwarf() const { return dwarf_; }
Dwarf* dwarf() { return dwarf_; }
- const SymbolTable* symtab() const { return symtab_; }
+ const SymbolTable& symtab() const {
+ ASSERT(symtab_ != nullptr);
+ return *symtab_;
+ }
+ const SectionTable& section_table() const { return *section_table_; }
// Stores the information needed to appropriately generate a
// relocation from the target to the source at the given section offset.
- // If a given symbol is nullptr, then the offset is absolute (from 0).
- // Both source and target symbols could be "." which is pseudosymbol
- // corresponding to the location of the relocation itself.
+ // If a given symbol name is nullptr, then the corresponding offset is
+ // relative from the location of the relocation itself.
+ // If a given symbol name is "", then the corresponding offset is relative to
+ // the start of the snapshot.
struct Relocation {
size_t size_in_bytes;
intptr_t section_offset;
@@ -81,36 +87,18 @@
void Finalize();
private:
- static constexpr const char* kBuildIdNoteName = ".note.gnu.build-id";
-
- // Adds the section and also creates a PT_LOAD segment for the section if it
- // is an allocated section.
- //
- // For allocated sections, if a symbol_name is provided, a symbol for the
- // section will be added to the dynamic table (if allocated) and static
- // table (if not stripped) during finalization.
- void AddSection(Section* section,
- const char* name,
- const char* symbol_name = nullptr);
-
- const Section* FindSectionBySymbolName(const char* symbol_name) const;
+ static constexpr const char kBuildIdNoteName[] = ".note.gnu.build-id";
+ static constexpr const char kTextName[] = ".text";
+ static constexpr const char kDataName[] = ".rodata";
+ static constexpr const char kBssName[] = ".bss";
+ static constexpr const char kDynamicTableName[] = ".dynamic";
void CreateBSS();
void GenerateBuildId();
-
- void OrderSectionsAndCreateSegments();
-
- void FinalizeSymbols();
+ void InitializeSymbolTables();
void FinalizeDwarfSections();
- void FinalizeProgramTable();
- void ComputeOffsets();
-
void FinalizeEhFrame();
-
- void WriteHeader(ElfWriteStream* stream);
- void WriteSectionTable(ElfWriteStream* stream);
- void WriteProgramTable(ElfWriteStream* stream);
- void WriteSections(ElfWriteStream* stream);
+ void ComputeOffsets();
Zone* const zone_;
BaseWriteStream* const unwrapped_stream_;
@@ -120,33 +108,18 @@
// the static symbol table (and its corresponding string table).
Dwarf* const dwarf_;
- // All our strings would fit in a single page. However, we use separate
- // .shstrtab and .dynstr to work around a bug in Android's strip utility.
- StringTable* const shstrtab_;
- StringTable* const dynstrtab_;
- SymbolTable* const dynsym_;
+ // Contains all sections that will have entries in the section header table.
+ SectionTable* const section_table_;
+
+ // Contains all segments in the program header table. Set after finalizing
+ // the section table.
+ ProgramTable* program_table_ = nullptr;
// The static tables are always created for use in relocation calculations,
// even though they may not end up in the final ELF file.
- StringTable* const strtab_;
- SymbolTable* const symtab_;
+ SymbolTable* symtab_ = nullptr;
- // We always create a BSS section for all Elf files to keep memory offsets
- // consistent, though it is NOBITS for separate debugging information.
- Section* bss_ = nullptr;
-
- // We currently create a GNU build ID for all ELF snapshots and associated
- // debugging information.
- Section* build_id_ = nullptr;
-
- GrowableArray<Section*> sections_;
- GrowableArray<Segment*> segments_;
-
- intptr_t memory_offset_;
- intptr_t section_table_file_offset_ = -1;
- intptr_t section_table_file_size_ = -1;
- intptr_t program_table_file_offset_ = -1;
- intptr_t program_table_file_size_ = -1;
+ friend class SectionTable; // For section name static fields.
};
#endif // DART_PRECOMPILER
diff --git a/runtime/vm/field_table.cc b/runtime/vm/field_table.cc
index 6809ff4..7e147c5 100644
--- a/runtime/vm/field_table.cc
+++ b/runtime/vm/field_table.cc
@@ -88,11 +88,6 @@
free_head_ = field_id;
}
-void FieldTable::SetAt(intptr_t index, ObjectPtr raw_instance) {
- ASSERT(index < capacity_);
- table_[index] = raw_instance;
-}
-
void FieldTable::AllocateIndex(intptr_t index) {
if (index >= capacity_) {
const intptr_t new_capacity = index + kCapacityIncrement;
diff --git a/runtime/vm/field_table.h b/runtime/vm/field_table.h
index 84b3b5e..71c01ef 100644
--- a/runtime/vm/field_table.h
+++ b/runtime/vm/field_table.h
@@ -58,11 +58,33 @@
// to an existing static field value.
void Free(intptr_t index);
- ObjectPtr At(intptr_t index) const {
+ ObjectPtr At(intptr_t index, bool concurrent_use = false) const {
ASSERT(IsValidIndex(index));
- return table_[index];
+ ObjectPtr* slot = &table_[index];
+ if (concurrent_use) {
+ return reinterpret_cast<AcqRelAtomic<ObjectPtr>*>(slot)->load();
+ } else {
+ // There is no concurrent access expected for this field, so we avoid
+ // using atomics. This will allow us to detect via TSAN if there are
+ // racy uses.
+ return *slot;
+ }
}
- void SetAt(intptr_t index, ObjectPtr raw_instance);
+
+ void SetAt(intptr_t index,
+ ObjectPtr raw_instance,
+ bool concurrent_use = false) {
+ ASSERT(index < capacity_);
+ ObjectPtr* slot = &table_[index];
+ if (concurrent_use) {
+ reinterpret_cast<AcqRelAtomic<ObjectPtr>*>(slot)->store(raw_instance);
+ } else {
+ // There is no concurrent access expected for this field, so we avoid
+ // using atomics. This will allow us to detect via TSAN if there are
+ // racy uses.
+ *slot = raw_instance;
+ }
+ }
FieldTable* Clone(Isolate* for_isolate);
diff --git a/runtime/vm/flag_list.h b/runtime/vm/flag_list.h
index 7e7a773..543b601 100644
--- a/runtime/vm/flag_list.h
+++ b/runtime/vm/flag_list.h
@@ -196,10 +196,6 @@
"needed in the precompiled runtime.") \
P(enable_isolate_groups, bool, false, \
"Enable isolate group support in AOT.") \
- P(experimental_enable_isolate_groups_jit, bool, false, \
- "As an experimental feature enable isolate group support in JIT" \
- "(goes into effect only when enable_isolate_groups is turned on as " \
- "well).") \
P(show_invisible_frames, bool, false, \
"Show invisible frames in stack traces.") \
D(trace_cha, bool, false, "Trace CHA operations") \
diff --git a/runtime/vm/flags.cc b/runtime/vm/flags.cc
index d082e9dc..26ff8e2 100644
--- a/runtime/vm/flags.cc
+++ b/runtime/vm/flags.cc
@@ -473,7 +473,7 @@
// graudally remove those restrictions.
#if !defined(DART_PRCOMPILED_RUNTIME)
- if (!FLAG_precompiled_mode && IsolateGroup::AreIsolateGroupsEnabled()) {
+ if (!FLAG_precompiled_mode && FLAG_enable_isolate_groups) {
// Our compiler should not make rely on a global field being initialized at
// compile-time, since that compiled code might be re-used in another
// isolate that has not yet initialized the global field.
diff --git a/runtime/vm/handles.h b/runtime/vm/handles.h
index ca6b5f4..ed4e9db 100644
--- a/runtime/vm/handles.h
+++ b/runtime/vm/handles.h
@@ -100,6 +100,13 @@
return scoped_blocks_->AllocateHandle();
}
+ bool IsEmpty() const {
+ if (zone_blocks_ != nullptr) return false;
+ if (first_scoped_block_.HandleCount() != 0) return false;
+ if (scoped_blocks_ != &first_scoped_block_) return false;
+ return true;
+ }
+
protected:
// Returns a count of active handles (used for testing purposes).
int CountScopedHandles() const;
diff --git a/runtime/vm/hash_map.h b/runtime/vm/hash_map.h
index 3273f4c..ec5ea08 100644
--- a/runtime/vm/hash_map.h
+++ b/runtime/vm/hash_map.h
@@ -631,7 +631,7 @@
DirectChainedHashMap<IntKeyRawPointerValueTrait<V> >::Insert(pair);
}
- inline V Lookup(const Key& key) {
+ inline V Lookup(const Key& key) const {
Pair* pair =
DirectChainedHashMap<IntKeyRawPointerValueTrait<V> >::Lookup(key);
if (pair == NULL) {
@@ -641,7 +641,7 @@
}
}
- inline Pair* LookupPair(const Key& key) {
+ inline Pair* LookupPair(const Key& key) const {
return DirectChainedHashMap<IntKeyRawPointerValueTrait<V> >::Lookup(key);
}
diff --git a/runtime/vm/hash_table.h b/runtime/vm/hash_table.h
index 06fbd70..318dbf4 100644
--- a/runtime/vm/hash_table.h
+++ b/runtime/vm/hash_table.h
@@ -33,6 +33,24 @@
static bool IsImmutable(const ArrayHandle& handle) {
return handle.ptr()->untag()->InVMIsolateHeap();
}
+
+ static ObjectPtr At(ArrayHandle* array, intptr_t index) {
+ return array->At(index);
+ }
+
+ static void SetAt(ArrayHandle* array, intptr_t index, const Object& value) {
+ array->SetAt(index, value);
+ }
+};
+
+struct AcqRelStorageTraits : ArrayStorageTraits {
+ static ObjectPtr At(ArrayHandle* array, intptr_t index) {
+ return array->AtAcquire(index);
+ }
+
+ static void SetAt(ArrayHandle* array, intptr_t index, const Object& value) {
+ array->SetAtRelease(index, value);
+ }
};
class HashTableBase : public ValueObject {
@@ -162,19 +180,19 @@
void Initialize() const {
ASSERT(data_->Length() >= ArrayLengthForNumOccupied(0));
*smi_handle_ = Smi::New(0);
- data_->SetAt(kOccupiedEntriesIndex, *smi_handle_);
- data_->SetAt(kDeletedEntriesIndex, *smi_handle_);
+ StorageTraits::SetAt(data_, kOccupiedEntriesIndex, *smi_handle_);
+ StorageTraits::SetAt(data_, kDeletedEntriesIndex, *smi_handle_);
#if !defined(PRODUCT)
- data_->SetAt(kNumGrowsIndex, *smi_handle_);
- data_->SetAt(kNumLT5LookupsIndex, *smi_handle_);
- data_->SetAt(kNumLT25LookupsIndex, *smi_handle_);
- data_->SetAt(kNumGT25LookupsIndex, *smi_handle_);
- data_->SetAt(kNumProbesIndex, *smi_handle_);
+ StorageTraits::SetAt(data_, kNumGrowsIndex, *smi_handle_);
+ StorageTraits::SetAt(data_, kNumLT5LookupsIndex, *smi_handle_);
+ StorageTraits::SetAt(data_, kNumLT25LookupsIndex, *smi_handle_);
+ StorageTraits::SetAt(data_, kNumGT25LookupsIndex, *smi_handle_);
+ StorageTraits::SetAt(data_, kNumProbesIndex, *smi_handle_);
#endif // !defined(PRODUCT)
for (intptr_t i = kHeaderSize; i < data_->Length(); ++i) {
- data_->SetAt(i, UnusedMarker());
+ StorageTraits::SetAt(data_, i, UnusedMarker());
}
}
@@ -298,14 +316,14 @@
ObjectPtr GetPayload(intptr_t entry, intptr_t component) const {
ASSERT(IsOccupied(entry));
return WeakSerializationReference::Unwrap(
- data_->At(PayloadIndex(entry, component)));
+ StorageTraits::At(data_, PayloadIndex(entry, component)));
}
void UpdatePayload(intptr_t entry,
intptr_t component,
const Object& value) const {
ASSERT(IsOccupied(entry));
ASSERT(0 <= component && component < kPayloadSize);
- data_->SetAt(PayloadIndex(entry, component), value);
+ StorageTraits::SetAt(data_, PayloadIndex(entry, component), value);
}
// Deletes both the key and payload of the specified entry.
void DeleteEntry(intptr_t entry) const {
@@ -411,22 +429,23 @@
}
ObjectPtr InternalGetKey(intptr_t entry) const {
- return WeakSerializationReference::Unwrap(data_->At(KeyIndex(entry)));
+ return WeakSerializationReference::Unwrap(
+ StorageTraits::At(data_, KeyIndex(entry)));
}
void InternalSetKey(intptr_t entry, const Object& key) const {
- data_->SetAt(KeyIndex(entry), key);
+ StorageTraits::SetAt(data_, KeyIndex(entry), key);
}
intptr_t GetSmiValueAt(intptr_t index) const {
ASSERT(!data_->IsNull());
- ASSERT(!data_->At(index)->IsHeapObject());
- return Smi::Value(Smi::RawCast(data_->At(index)));
+ ASSERT(!StorageTraits::At(data_, index)->IsHeapObject());
+ return Smi::Value(Smi::RawCast(StorageTraits::At(data_, index)));
}
void SetSmiValueAt(intptr_t index, intptr_t value) const {
*smi_handle_ = Smi::New(value);
- data_->SetAt(index, *smi_handle_);
+ StorageTraits::SetAt(data_, index, *smi_handle_);
}
void AdjustSmiValueAt(intptr_t index, intptr_t delta) const {
@@ -450,10 +469,13 @@
};
// Table with unspecified iteration order. No payload overhead or metadata.
-template <typename KeyTraits, intptr_t kUserPayloadSize>
-class UnorderedHashTable : public HashTable<KeyTraits, kUserPayloadSize, 0> {
+template <typename KeyTraits,
+ intptr_t kUserPayloadSize,
+ typename StorageTraits = ArrayStorageTraits>
+class UnorderedHashTable
+ : public HashTable<KeyTraits, kUserPayloadSize, 0, StorageTraits> {
public:
- typedef HashTable<KeyTraits, kUserPayloadSize, 0> BaseTable;
+ typedef HashTable<KeyTraits, kUserPayloadSize, 0, StorageTraits> BaseTable;
static const intptr_t kPayloadSize = kUserPayloadSize;
explicit UnorderedHashTable(ArrayPtr data)
: BaseTable(Thread::Current()->zone(), data) {}
@@ -776,10 +798,13 @@
}
};
-template <typename KeyTraits>
-class UnorderedHashSet : public HashSet<UnorderedHashTable<KeyTraits, 0> > {
+template <typename KeyTraits, typename TableStorageTraits = ArrayStorageTraits>
+class UnorderedHashSet
+ : public HashSet<UnorderedHashTable<KeyTraits, 0, TableStorageTraits>> {
+ using UnderlyingTable = UnorderedHashTable<KeyTraits, 0, TableStorageTraits>;
+
public:
- typedef HashSet<UnorderedHashTable<KeyTraits, 0> > BaseSet;
+ typedef HashSet<UnderlyingTable> BaseSet;
explicit UnorderedHashSet(ArrayPtr data)
: BaseSet(Thread::Current()->zone(), data) {
ASSERT(data != Array::null());
@@ -791,7 +816,8 @@
void Dump() const {
Object& entry = Object::Handle();
for (intptr_t i = 0; i < this->data_->Length(); i++) {
- entry = WeakSerializationReference::Unwrap(this->data_->At(i));
+ entry = WeakSerializationReference::Unwrap(
+ TableStorageTraits::At(this->data_, i));
if (entry.ptr() == BaseSet::UnusedMarker().ptr() ||
entry.ptr() == BaseSet::DeletedMarker().ptr() || entry.IsSmi()) {
// empty, deleted, num_used/num_deleted
diff --git a/runtime/vm/heap/heap_test.cc b/runtime/vm/heap/heap_test.cc
index ee48775..e1f9c82 100644
--- a/runtime/vm/heap/heap_test.cc
+++ b/runtime/vm/heap/heap_test.cc
@@ -16,6 +16,7 @@
#include "vm/heap/become.h"
#include "vm/heap/heap.h"
#include "vm/message_handler.h"
+#include "vm/message_snapshot.h"
#include "vm/object_graph.h"
#include "vm/port.h"
#include "vm/symbols.h"
@@ -544,8 +545,7 @@
isolate()->group()->api_state()->FreePersistentHandle(handle);
} else {
Thread* thread = Thread::Current();
- MessageSnapshotReader reader(message.get(), thread);
- response_obj = reader.ReadObject();
+ response_obj = ReadMessage(thread, message.get());
}
if (response_obj.IsString()) {
String& response = String::Handle();
@@ -575,7 +575,7 @@
VM_UNIT_TEST_CASE(CleanupBequestNeverReceived) {
// This test uses features from isolate groups
- IsolateGroup::ForceEnableIsolateGroupsForTesting();
+ FLAG_enable_isolate_groups = true;
const char* TEST_MESSAGE = "hello, world";
Dart_Isolate parent = TestCase::CreateTestIsolate("parent");
@@ -610,7 +610,7 @@
VM_UNIT_TEST_CASE(ReceivesSendAndExitMessage) {
// This test uses features from isolate groups
- IsolateGroup::ForceEnableIsolateGroupsForTesting();
+ FLAG_enable_isolate_groups = true;
const char* TEST_MESSAGE = "hello, world";
Dart_Isolate parent = TestCase::CreateTestIsolate("parent");
diff --git a/runtime/vm/heap/safepoint.cc b/runtime/vm/heap/safepoint.cc
index 4a7e5de..52da48b 100644
--- a/runtime/vm/heap/safepoint.cc
+++ b/runtime/vm/heap/safepoint.cc
@@ -155,7 +155,7 @@
if (!Thread::IsAtSafepoint(level_, state)) {
// Send OOB message to get it to safepoint.
if (current->IsMutatorThread()) {
- current->ScheduleInterruptsLocked(Thread::kVMInterrupt);
+ current->ScheduleInterrupts(Thread::kVMInterrupt);
}
MonitorLocker sl(&parked_lock_);
num_threads_not_parked_++;
diff --git a/runtime/vm/heap/scavenger.h b/runtime/vm/heap/scavenger.h
index ed36fe1..810a26e 100644
--- a/runtime/vm/heap/scavenger.h
+++ b/runtime/vm/heap/scavenger.h
@@ -12,6 +12,7 @@
#include "vm/flags.h"
#include "vm/globals.h"
#include "vm/heap/spaces.h"
+#include "vm/isolate.h"
#include "vm/lockers.h"
#include "vm/raw_object.h"
#include "vm/ring_buffer.h"
diff --git a/runtime/vm/heap/verifier.cc b/runtime/vm/heap/verifier.cc
index abeb1cc..15b26f5 100644
--- a/runtime/vm/heap/verifier.cc
+++ b/runtime/vm/heap/verifier.cc
@@ -117,23 +117,16 @@
// Therefore we disable the handle verification here.
const bool old_verify_flag = FLAG_verify_handles;
FLAG_verify_handles = false;
-
- // TODO(dartbug.com/36097): The heap walk can encounter canonical objects of
- // other isolates. We should either scan live objects from the roots of each
- // individual isolate, or wait until we are ready to share constants across
- // isolates.
- if (!IsolateGroup::AreIsolateGroupsEnabled() || FLAG_precompiled_mode) {
- if ((obj->GetClassId() >= kInstanceCid) &&
- (obj->GetClassId() != kTypeArgumentsCid)) {
- if (obj->untag()->IsCanonical()) {
- instanceHandle_ ^= obj;
- const bool is_canonical = instanceHandle_.CheckIsCanonical(thread_);
- if (!is_canonical) {
- OS::PrintErr("Instance `%s` is not canonical!\n",
- instanceHandle_.ToCString());
- }
- ASSERT(is_canonical);
+ if ((obj->GetClassId() >= kInstanceCid) &&
+ (obj->GetClassId() != kTypeArgumentsCid)) {
+ if (obj->untag()->IsCanonical()) {
+ instanceHandle_ ^= obj;
+ const bool is_canonical = instanceHandle_.CheckIsCanonical(thread_);
+ if (!is_canonical) {
+ OS::PrintErr("Instance `%s` is not canonical!\n",
+ instanceHandle_.ToCString());
}
+ ASSERT(is_canonical);
}
}
FLAG_verify_handles = old_verify_flag;
diff --git a/runtime/vm/heap/weak_table.cc b/runtime/vm/heap/weak_table.cc
index 4070590..36c903004 100644
--- a/runtime/vm/heap/weak_table.cc
+++ b/runtime/vm/heap/weak_table.cc
@@ -30,7 +30,7 @@
}
void WeakTable::SetValueExclusive(ObjectPtr key, intptr_t val) {
- intptr_t mask = size() - 1;
+ const intptr_t mask = size() - 1;
intptr_t idx = Hash(key) & mask;
intptr_t empty_idx = -1;
ObjectPtr obj = ObjectAtExclusive(idx);
@@ -74,6 +74,46 @@
}
}
+bool WeakTable::MarkValueExclusive(ObjectPtr key, intptr_t val) {
+ const intptr_t mask = size() - 1;
+ intptr_t idx = Hash(key) & mask;
+ intptr_t empty_idx = -1;
+ ObjectPtr obj = ObjectAtExclusive(idx);
+
+ while (obj != static_cast<ObjectPtr>(kNoEntry)) {
+ if (obj == key) {
+ return false;
+ } else if ((empty_idx < 0) &&
+ (static_cast<intptr_t>(obj) == kDeletedEntry)) {
+ empty_idx = idx; // Insert at this location if not found.
+ }
+ idx = (idx + 1) & mask;
+ obj = ObjectAtExclusive(idx);
+ }
+
+ ASSERT(val != 0);
+
+ if (empty_idx >= 0) {
+ // We will be reusing a slot below.
+ set_used(used() - 1);
+ idx = empty_idx;
+ }
+
+ ASSERT(!IsValidEntryAtExclusive(idx));
+ // Set the key and value.
+ SetObjectAt(idx, key);
+ SetValueAt(idx, val);
+ // Update the counts.
+ set_used(used() + 1);
+ set_count(count() + 1);
+
+ // Rehash if needed to ensure that there are empty slots available.
+ if (used_ >= limit()) {
+ Rehash();
+ }
+ return true;
+}
+
void WeakTable::Reset() {
intptr_t* old_data = data_;
used_ = 0;
diff --git a/runtime/vm/heap/weak_table.h b/runtime/vm/heap/weak_table.h
index 3062b53..ade129d 100644
--- a/runtime/vm/heap/weak_table.h
+++ b/runtime/vm/heap/weak_table.h
@@ -104,6 +104,7 @@
}
void SetValueExclusive(ObjectPtr key, intptr_t val);
+ bool MarkValueExclusive(ObjectPtr key, intptr_t val);
intptr_t GetValueExclusive(ObjectPtr key) const {
intptr_t mask = size() - 1;
@@ -203,7 +204,9 @@
void Rehash();
- static uword Hash(ObjectPtr key) { return static_cast<uword>(key) * 92821; }
+ static uword Hash(ObjectPtr key) {
+ return (static_cast<uword>(key) * 92821) ^ (static_cast<uword>(key) >> 8);
+ }
Mutex mutex_;
diff --git a/runtime/vm/image_snapshot.cc b/runtime/vm/image_snapshot.cc
index bee78c8..587267c 100644
--- a/runtime/vm/image_snapshot.cc
+++ b/runtime/vm/image_snapshot.cc
@@ -613,7 +613,6 @@
FLAG_precompiled_mode && FLAG_use_bare_instructions;
// Start snapshot at page boundary.
- ASSERT(ImageWriter::kTextAlignment >= VirtualMemory::PageSize());
if (!EnterSection(ProgramSection::Text, vm, ImageWriter::kTextAlignment)) {
return;
}
@@ -693,7 +692,7 @@
// 2) The BSS offset from this section.
text_offset += Relocation(text_offset, instructions_symbol, bss_symbol);
// 3) The relocated address of the instructions.
- text_offset += Relocation(text_offset, instructions_symbol);
+ text_offset += RelocatedAddress(text_offset, instructions_symbol);
// 4) The GNU build ID note offset from this section.
text_offset += Relocation(text_offset, instructions_symbol,
SectionSymbol(ProgramSection::BuildId, vm));
@@ -1222,10 +1221,7 @@
intptr_t source_offset,
const char* target_symbol,
intptr_t target_offset) {
- if (source_symbol == nullptr || target_symbol == nullptr) {
- // We can't use absolute addresses in assembly relocations.
- return WriteTargetWord(Image::kNoRelocatedAddress);
- }
+ ASSERT(source_symbol != nullptr);
ASSERT(target_symbol != nullptr);
// TODO(dartbug.com/43274): Remove once we generate consistent build IDs
@@ -1238,23 +1234,24 @@
// All relocations are word-sized.
assembly_stream_->Printf("%s ", kWordDirective);
- if (strcmp(target_symbol, current_section_symbol_) == 0 &&
- target_offset == section_offset) {
+ if (strcmp(target_symbol, current_section_symbol_) == 0) {
assembly_stream_->WriteString("(.)");
+ target_offset -= section_offset;
} else {
assembly_stream_->Printf("%s", target_symbol);
- if (target_offset != 0) {
- assembly_stream_->Printf(" + %" Pd "", target_offset);
- }
}
- if (strcmp(source_symbol, current_section_symbol_) == 0 &&
- source_offset == section_offset) {
+ if (target_offset != 0) {
+ assembly_stream_->Printf(" + %" Pd "", target_offset);
+ }
+
+ if (strcmp(source_symbol, current_section_symbol_) == 0) {
assembly_stream_->WriteString(" - (.)");
+ source_offset -= section_offset;
} else {
assembly_stream_->Printf(" - %s", source_symbol);
- if (source_offset != 0) {
- assembly_stream_->Printf(" - %" Pd "", source_offset);
- }
+ }
+ if (source_offset != 0) {
+ assembly_stream_->Printf(" - %" Pd "", source_offset);
}
assembly_stream_->WriteString("\n");
return compiler::target::kWordSize;
diff --git a/runtime/vm/image_snapshot.h b/runtime/vm/image_snapshot.h
index 3b2ed09..fc2bbdd 100644
--- a/runtime/vm/image_snapshot.h
+++ b/runtime/vm/image_snapshot.h
@@ -241,15 +241,8 @@
// ROData sections contain objects wrapped in an Image object.
static constexpr intptr_t kRODataAlignment = kMaxObjectAlignment;
// Text sections contain objects (even in bare instructions mode) wrapped
- // in an Image object, and for now we also align them to the same page
- // size assumed by Elf objects.
- static constexpr intptr_t kTextAlignment = 16 * KB;
-#if defined(DART_PRECOMPILER)
- static_assert(kTextAlignment == Elf::kPageSize,
- "Page alignment must be consistent with max object alignment");
- static_assert(Elf::kPageSize >= kMaxObjectAlignment,
- "Page alignment must be consistent with max object alignment");
-#endif
+ // in an Image object.
+ static constexpr intptr_t kTextAlignment = kMaxObjectAlignment;
void ResetOffsets() {
next_data_offset_ = Image::kHeaderSize;
@@ -404,13 +397,15 @@
// relocated address of the target section and S is the final relocated
// address of the source, the final value is:
// (T + target_offset + target_addend) - (S + source_offset)
- // If either symbol is nullptr, then the corresponding is treated as an
- // absolute address.
virtual intptr_t Relocation(intptr_t section_offset,
const char* source_symbol,
intptr_t source_offset,
const char* target_symbol,
intptr_t target_offset) = 0;
+ // Writes a target word-sized value that contains the relocated address
+ // pointed to by the given symbol.
+ virtual intptr_t RelocatedAddress(intptr_t section_offset,
+ const char* symbol) = 0;
// Creates a static symbol for the given Code object when appropriate.
virtual void AddCodeSymbol(const Code& code,
const char* symbol,
@@ -425,11 +420,6 @@
const char* target_symbol) {
return Relocation(section_offset, source_symbol, 0, target_symbol, 0);
}
- // An overload of Relocation for outputting the relocated address of the
- // target symbol at the given section offset.
- intptr_t Relocation(intptr_t section_offset, const char* target_symbol) {
- return Relocation(section_offset, nullptr, 0, target_symbol, 0);
- }
#endif
// Writes a fixed-sized value of type T to the section contents.
template <typename T>
@@ -556,6 +546,11 @@
intptr_t source_offset,
const char* target_symbol,
intptr_t target_offset);
+ virtual intptr_t RelocatedAddress(intptr_t section_offset,
+ const char* symbol) {
+ // Cannot calculate snapshot-relative addresses in assembly snapshots.
+ return WriteTargetWord(Image::kNoRelocatedAddress);
+ }
virtual void FrameUnwindPrologue();
virtual void FrameUnwindEpilogue();
virtual void AddCodeSymbol(const Code& code,
@@ -606,6 +601,11 @@
intptr_t source_offset,
const char* target_symbol,
intptr_t target_offset);
+ virtual intptr_t RelocatedAddress(intptr_t section_offset,
+ const char* target_symbol) {
+ // ELF symbol tables always have a reserved symbol with name "" and value 0.
+ return ImageWriter::Relocation(section_offset, "", target_symbol);
+ }
virtual void AddCodeSymbol(const Code& code,
const char* symbol,
intptr_t offset);
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index cb00d29..b1a7315 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -31,6 +31,7 @@
#include "vm/lockers.h"
#include "vm/log.h"
#include "vm/message_handler.h"
+#include "vm/message_snapshot.h"
#include "vm/object.h"
#include "vm/object_id_ring.h"
#include "vm/object_store.h"
@@ -123,18 +124,14 @@
static std::unique_ptr<Message> SerializeMessage(Dart_Port dest_port,
const Instance& obj) {
- if (ApiObjectConverter::CanConvert(obj.ptr())) {
- return Message::New(dest_port, obj.ptr(), Message::kNormalPriority);
- } else {
- MessageWriter writer(false);
- return writer.WriteMessage(obj, dest_port, Message::kNormalPriority);
- }
+ return WriteMessage(/* can_send_any_object */ false, obj, dest_port,
+ Message::kNormalPriority);
}
-static std::unique_ptr<Message> SerializeMessage(Dart_Port dest_port,
+static std::unique_ptr<Message> SerializeMessage(Zone* zone,
+ Dart_Port dest_port,
Dart_CObject* obj) {
- ApiMessageWriter writer;
- return writer.WriteCMessage(obj, dest_port, Message::kNormalPriority);
+ return WriteApiMessage(zone, obj, dest_port, Message::kNormalPriority);
}
void IsolateGroupSource::add_loaded_blob(
@@ -359,7 +356,7 @@
#if !defined(DART_PRECOMPILED_RUNTIME)
background_compiler_(new BackgroundCompiler(this)),
#endif
- symbols_lock_(new SafepointRwLock()),
+ symbols_mutex_(NOT_IN_PRODUCT("IsolateGroup::symbols_mutex_")),
type_canonicalization_mutex_(
NOT_IN_PRODUCT("IsolateGroup::type_canonicalization_mutex_")),
type_arguments_canonicalization_mutex_(NOT_IN_PRODUCT(
@@ -785,8 +782,6 @@
JSONObject jsobj(stream);
// This is the same "MemoryUsage" that the isolate-specific "getMemoryUsage"
// rpc method returns.
- // TODO(dartbug.com/36097): Once the heap moves from Isolate to IsolateGroup
- // this code needs to be adjusted to not double-count memory.
jsobj.AddProperty("type", "MemoryUsage");
jsobj.AddProperty64("heapUsage", used * kWordSize);
jsobj.AddProperty64("heapCapacity", capacity * kWordSize);
@@ -867,19 +862,6 @@
return Isolate::IsSystemIsolate(isolate);
}
-NoOOBMessageScope::NoOOBMessageScope(Thread* thread)
- : ThreadStackResource(thread) {
- if (thread->isolate() != nullptr) {
- thread->DeferOOBMessageInterrupts();
- }
-}
-
-NoOOBMessageScope::~NoOOBMessageScope() {
- if (thread()->isolate() != nullptr) {
- thread()->RestoreOOBMessageInterrupts();
- }
-}
-
Bequest::~Bequest() {
if (handle_ == nullptr) {
return;
@@ -1006,6 +988,8 @@
NoBackgroundCompilerScope no_bg_compiler(Thread::Current());
heap()->CollectAllGarbage();
Thread* thread = Thread::Current();
+ SafepointMutexLocker ml(
+ thread->isolate_group()->constant_canonicalization_mutex());
HeapIterationScope iteration(thread);
VerifyCanonicalVisitor check_canonical(thread);
iteration.IterateObjects(&check_canonical);
@@ -1023,9 +1007,8 @@
element = Capability::New(capability);
msg.SetAt(2, element);
- MessageWriter writer(false);
- PortMap::PostMessage(
- writer.WriteMessage(msg, main_port(), Message::kOOBPriority));
+ PortMap::PostMessage(WriteMessage(/* can_send_any_object */ false, msg,
+ main_port(), Message::kOOBPriority));
}
void IsolateGroup::set_object_store(ObjectStore* object_store) {
@@ -1345,11 +1328,7 @@
// Parse the message.
Object& msg_obj = Object::Handle(zone);
- if (message->IsRaw()) {
- msg_obj = message->raw_obj();
- // We should only be sending RawObjects that can be converted to CObjects.
- ASSERT(ApiObjectConverter::CanConvert(msg_obj.ptr()));
- } else if (message->IsPersistentHandle()) {
+ if (message->IsPersistentHandle()) {
// msg_array = [<message>, <object-in-message-to-rehash>]
const auto& msg_array = Array::Handle(
zone, Array::RawCast(message->persistent_handle()->ptr()));
@@ -1363,8 +1342,7 @@
}
}
} else {
- MessageSnapshotReader reader(message.get(), thread);
- msg_obj = reader.ReadObject();
+ msg_obj = ReadMessage(thread, message.get());
}
if (msg_obj.IsError()) {
// An error occurred while reading the message.
@@ -2375,7 +2353,7 @@
listener ^= listeners.At(i);
if (!listener.IsNull()) {
Dart_Port port_id = listener.Id();
- PortMap::PostMessage(SerializeMessage(port_id, &arr));
+ PortMap::PostMessage(SerializeMessage(current_zone(), port_id, &arr));
}
}
return listeners.Length() > 0;
@@ -2398,6 +2376,25 @@
reinterpret_cast<uword>(this));
}
+#if !defined(PRODUCT)
+void Isolate::set_current_sample_block(SampleBlock* current) {
+ ASSERT(current_sample_block_lock_.IsOwnedByCurrentThread());
+ if (current != nullptr) {
+ current->set_is_allocation_block(false);
+ current->set_owner(this);
+ }
+ current_sample_block_ = current;
+}
+
+void Isolate::set_current_allocation_sample_block(SampleBlock* current) {
+ if (current != nullptr) {
+ current->set_is_allocation_block(true);
+ current->set_owner(this);
+ }
+ current_allocation_sample_block_ = current;
+}
+#endif // !defined(PRODUCT)
+
// static
void Isolate::NotifyLowMemory() {
Isolate::KillAllIsolates(Isolate::kLowMemoryMsg);
@@ -2531,11 +2528,12 @@
}
void Isolate::LowLevelCleanup(Isolate* isolate) {
-#if !defined(DART_PECOMPILED_RUNTIME)
+#if !defined(DART_PRECOMPILED_RUNTIME)
if (KernelIsolate::IsKernelIsolate(isolate)) {
KernelIsolate::SetKernelIsolate(nullptr);
+ }
#endif
- } else if (ServiceIsolate::IsServiceIsolate(isolate)) {
+ if (ServiceIsolate::IsServiceIsolate(isolate)) {
ServiceIsolate::SetServiceIsolate(nullptr);
}
@@ -2553,6 +2551,26 @@
// requests anymore.
Thread::ExitIsolate();
+#if !defined(PRODUCT)
+ // Cleanup profiler state.
+ SampleBlock* cpu_block = isolate->current_sample_block();
+ if (cpu_block != nullptr) {
+ cpu_block->release_block();
+ }
+ SampleBlock* allocation_block = isolate->current_allocation_sample_block();
+ if (allocation_block != nullptr) {
+ allocation_block->release_block();
+ }
+
+ // Process the previously assigned sample blocks if we're using the
+ // profiler's sample buffer. Some tests create their own SampleBlockBuffer
+ // and handle block processing themselves.
+ if ((cpu_block != nullptr || allocation_block != nullptr) &&
+ Profiler::sample_block_buffer() != nullptr) {
+ Profiler::sample_block_buffer()->ProcessCompletedBlocks();
+ }
+#endif // !defined(PRODUCT)
+
// Now it's safe to delete the isolate.
delete isolate;
@@ -2600,7 +2618,7 @@
Dart::thread_pool()->Run<ShutdownGroupTask>(isolate_group);
}
} else {
- if (IsolateGroup::AreIsolateGroupsEnabled()) {
+ if (FLAG_enable_isolate_groups) {
// TODO(dartbug.com/36097): An isolate just died. A significant amount of
// memory might have become unreachable. We should evaluate how to best
// inform the GC about this situation.
@@ -2773,7 +2791,7 @@
auto thread = Thread::Current();
StoppedMutatorsScope stopped_mutators_scope(thread);
- if (thread->IsMutatorThread() && !IsolateGroup::AreIsolateGroupsEnabled()) {
+ if (thread->IsMutatorThread() && !FLAG_enable_isolate_groups) {
single_current_mutator->Call();
return;
}
@@ -3272,9 +3290,9 @@
msg.SetAt(1, element);
element = Smi::New(Isolate::kBeforeNextEventAction);
msg.SetAt(2, element);
- MessageWriter writer(false);
- std::unique_ptr<Message> message =
- writer.WriteMessage(msg, main_port(), Message::kOOBPriority);
+ std::unique_ptr<Message> message = WriteMessage(
+ /* can_send_any_object */ false, msg, main_port(),
+ Message::kOOBPriority);
bool posted = PortMap::PostMessage(std::move(message));
ASSERT(posted);
}
@@ -3518,9 +3536,9 @@
list_values[3] = &imm;
{
- ApiMessageWriter writer;
- std::unique_ptr<Message> message =
- writer.WriteCMessage(&kill_msg, main_port(), Message::kOOBPriority);
+ AllocOnlyStackZone zone;
+ std::unique_ptr<Message> message = WriteApiMessage(
+ zone.GetZone(), &kill_msg, main_port(), Message::kOOBPriority);
ASSERT(message != nullptr);
// Post the message at the given port.
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index c17a81d..d7c8e5d 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -74,6 +74,8 @@
class SafepointRwLock;
class SafepointHandler;
class SampleBuffer;
+class SampleBlock;
+class SampleBlockBuffer;
class SendPort;
class SerializedObjectBuffer;
class ServiceIdZone;
@@ -134,16 +136,6 @@
DISALLOW_COPY_AND_ASSIGN(LambdaCallable);
};
-// Disallow OOB message handling within this scope.
-class NoOOBMessageScope : public ThreadStackResource {
- public:
- explicit NoOOBMessageScope(Thread* thread);
- ~NoOOBMessageScope();
-
- private:
- DISALLOW_COPY_AND_ASSIGN(NoOOBMessageScope);
-};
-
// Fixed cache for exception handler lookup.
typedef FixedCache<intptr_t, ExceptionHandlerInfo, 16> HandlerInfoCache;
// Fixed cache for catch entry state lookup.
@@ -182,21 +174,8 @@
V(PRODUCT, null_safety, NullSafety, null_safety, false)
// Represents the information used for spawning the first isolate within an
-// isolate group.
-//
-// Any subsequent isolates created via `Isolate.spawn()` will be created using
-// the same [IsolateGroupSource] (the object itself is shared among all isolates
-// within the same group).
-//
-// Issue(http://dartbug.com/36097): It is still possible to run into issues if
-// an isolate has spawned another one and then loads more code into the first
-// one, which the latter will not get. Though it makes the status quo better
-// than what we had before (where the embedder needed to maintain the
-// same-source guarantee).
-//
-// => This is only the first step towards having multiple isolates share the
-// same heap (and therefore the same program structure).
-//
+// isolate group. All isolates within a group will refer to this
+// [IsolateGroupSource].
class IsolateGroupSource {
public:
IsolateGroupSource(const char* script_uri,
@@ -239,11 +218,6 @@
const uint8_t* script_kernel_buffer;
intptr_t script_kernel_size;
- // During AppJit training we perform a permutation of the class ids before
- // invoking the "main" script.
- // Any newly spawned isolates need to use this permutation map.
- std::unique_ptr<intptr_t[]> cid_permutation_map;
-
// List of weak pointers to external typed data for loaded blobs.
ArrayPtr loaded_blobs_;
intptr_t num_blob_loads_;
@@ -534,7 +508,7 @@
StoreBuffer* store_buffer() const { return store_buffer_.get(); }
ClassTable* class_table() const { return class_table_.get(); }
ObjectStore* object_store() const { return object_store_.get(); }
- SafepointRwLock* symbols_lock() { return symbols_lock_.get(); }
+ Mutex* symbols_mutex() { return &symbols_mutex_; }
Mutex* type_canonicalization_mutex() { return &type_canonicalization_mutex_; }
Mutex* type_arguments_canonicalization_mutex() {
return &type_arguments_canonicalization_mutex_;
@@ -789,20 +763,6 @@
void RegisterStaticField(const Field& field, const Object& initial_value);
void FreeStaticField(const Field& field);
- static bool AreIsolateGroupsEnabled() {
-#if defined(DART_PRECOMPILED_RUNTIME)
- return FLAG_enable_isolate_groups;
-#else
- return FLAG_enable_isolate_groups &&
- FLAG_experimental_enable_isolate_groups_jit;
-#endif
- }
-
- static void ForceEnableIsolateGroupsForTesting() {
- FLAG_enable_isolate_groups = true;
- FLAG_experimental_enable_isolate_groups_jit = true;
- }
-
private:
friend class Dart; // For `object_store_ = ` in Dart::Init
friend class Heap;
@@ -908,7 +868,7 @@
NOT_IN_PRECOMPILED(std::unique_ptr<BackgroundCompiler> background_compiler_);
- std::unique_ptr<SafepointRwLock> symbols_lock_;
+ Mutex symbols_mutex_;
Mutex type_canonicalization_mutex_;
Mutex type_arguments_canonicalization_mutex_;
Mutex subtype_test_cache_mutex_;
@@ -1126,6 +1086,27 @@
#if !defined(PRODUCT)
Debugger* debugger() const { return debugger_; }
+ // NOTE: this lock should only be acquired within the profiler signal handler.
+ Mutex* current_sample_block_lock() const {
+ return const_cast<Mutex*>(¤t_sample_block_lock_);
+ }
+
+ // Returns the current SampleBlock used to track CPU profiling samples.
+ //
+ // NOTE: current_sample_block_lock() should be held when accessing this
+ // block.
+ SampleBlock* current_sample_block() const { return current_sample_block_; }
+ void set_current_sample_block(SampleBlock* current);
+
+ // Returns the current SampleBlock used to track Dart allocation samples.
+ //
+ // Allocations should only occur on the mutator thread for an isolate, so we
+ // don't need to worry about grabbing a lock while accessing this block.
+ SampleBlock* current_allocation_sample_block() const {
+ return current_allocation_sample_block_;
+ }
+ void set_current_allocation_sample_block(SampleBlock* current);
+
void set_single_step(bool value) { single_step_ = value; }
bool single_step() const { return single_step_; }
static intptr_t single_step_offset() {
@@ -1570,6 +1551,21 @@
// the top.
#if !defined(PRODUCT)
Debugger* debugger_ = nullptr;
+
+ // SampleBlock containing CPU profiling samples.
+ //
+ // Can be accessed by multiple threads, so current_sample_block_lock_ should
+ // be acquired before accessing.
+ SampleBlock* current_sample_block_ = nullptr;
+ Mutex current_sample_block_lock_;
+
+ // SampleBlock containing Dart allocation profiling samples.
+ //
+ // Allocations should only occur on the mutator thread for an isolate, so we
+ // shouldn't need to worry about grabbing a lock for the allocation sample
+ // block.
+ SampleBlock* current_allocation_sample_block_ = nullptr;
+
int64_t last_resume_timestamp_;
VMTagCounters vm_tag_counters_;
diff --git a/runtime/vm/isolate_reload.cc b/runtime/vm/isolate_reload.cc
index 5be85a1..182c090 100644
--- a/runtime/vm/isolate_reload.cc
+++ b/runtime/vm/isolate_reload.cc
@@ -95,12 +95,6 @@
return heap->old_space()->tasks() == 0;
}
-// TODO(dartbug.com/36097): Once classes are split up into a read-only
-// descriptor which can be shared across isolates, we can make this function
-// take descriptors instead of the isolate-specific [Class] objects.
-//
-// (The information we access from [from]/[to] *must* be the same across
-// isolates.)
InstanceMorpher* InstanceMorpher::CreateFromClassDescriptors(
Zone* zone,
SharedClassTable* shared_class_table,
@@ -1867,9 +1861,13 @@
saved_class_table_.load(std::memory_order_relaxed);
ClassPtr* local_saved_tlc_class_table =
saved_tlc_class_table_.load(std::memory_order_relaxed);
- IG->class_table()->ResetAfterHotReload(
- local_saved_class_table, local_saved_tlc_class_table, saved_num_cids_,
- saved_num_tlc_cids_, is_rollback);
+ {
+ auto thread = Thread::Current();
+ SafepointWriteRwLocker sl(thread, thread->isolate_group()->program_lock());
+ IG->class_table()->ResetAfterHotReload(
+ local_saved_class_table, local_saved_tlc_class_table, saved_num_cids_,
+ saved_num_tlc_cids_, is_rollback);
+ }
saved_class_table_.store(nullptr, std::memory_order_release);
saved_tlc_class_table_.store(nullptr, std::memory_order_release);
}
@@ -2115,6 +2113,7 @@
type_(AbstractType::Handle(zone)),
cache_(SubtypeTestCache::Handle(zone)),
entries_(Array::Handle(zone)),
+ closure_function_(Function::Handle(zone)),
instantiator_type_arguments_(TypeArguments::Handle(zone)),
function_type_arguments_(TypeArguments::Handle(zone)),
instance_cid_or_signature_(Object::Handle(zone)),
@@ -2143,7 +2142,8 @@
// At that point it doesn't have the field table setup yet.
if (field_table->IsReadyToUse()) {
value_ = field_table->At(field_id);
- if (value_.ptr() != Object::sentinel().ptr()) {
+ if ((value_.ptr() != Object::sentinel().ptr()) &&
+ (value_.ptr() != Object::transition_sentinel().ptr())) {
CheckValueType(null_safety, value_, field);
}
}
@@ -2217,13 +2217,12 @@
cls_ = value.clazz();
const intptr_t cid = cls_.id();
if (cid == kClosureCid) {
- instance_cid_or_signature_ = Closure::Cast(value).signature();
- instance_type_arguments_ =
- Closure::Cast(value).instantiator_type_arguments();
- parent_function_type_arguments_ =
- Closure::Cast(value).function_type_arguments();
- delayed_function_type_arguments_ =
- Closure::Cast(value).delayed_type_arguments();
+ const auto& closure = Closure::Cast(value);
+ closure_function_ = closure.function();
+ instance_cid_or_signature_ = closure_function_.signature();
+ instance_type_arguments_ = closure.instantiator_type_arguments();
+ parent_function_type_arguments_ = closure.function_type_arguments();
+ delayed_function_type_arguments_ = closure.delayed_type_arguments();
} else {
instance_cid_or_signature_ = Smi::New(cid);
if (cls_.NumTypeArguments() > 0) {
@@ -2295,6 +2294,7 @@
AbstractType& type_;
SubtypeTestCache& cache_;
Array& entries_;
+ Function& closure_function_;
TypeArguments& instantiator_type_arguments_;
TypeArguments& function_type_arguments_;
Object& instance_cid_or_signature_;
diff --git a/runtime/vm/isolate_test.cc b/runtime/vm/isolate_test.cc
index 9402106..2003591 100644
--- a/runtime/vm/isolate_test.cc
+++ b/runtime/vm/isolate_test.cc
@@ -145,106 +145,4 @@
barrier.Exit();
}
-class IsolateTestHelper {
- public:
- static uword GetStackLimit(Thread* thread) { return thread->stack_limit_; }
- static uword GetSavedStackLimit(Thread* thread) {
- return thread->saved_stack_limit_;
- }
- static uword GetDeferredInterruptsMask(Thread* thread) {
- return thread->deferred_interrupts_mask_;
- }
- static uword GetDeferredInterrupts(Thread* thread) {
- return thread->deferred_interrupts_;
- }
-};
-
-TEST_CASE(NoOOBMessageScope) {
- // Finish any GC in progress so that no kVMInterrupt is added for GC reasons.
- {
- TransitionNativeToVM transition(thread);
- GCTestHelper::CollectAllGarbage();
- const Error& error = Error::Handle(thread->HandleInterrupts());
- RELEASE_ASSERT(error.IsNull());
- }
-
- // EXPECT_EQ is picky about type agreement for its arguments.
- const uword kZero = 0;
- const uword kMessageInterrupt = Thread::kMessageInterrupt;
- const uword kVMInterrupt = Thread::kVMInterrupt;
- uword stack_limit;
- uword interrupt_bits;
-
- // Initially no interrupts are scheduled or deferred.
- EXPECT_EQ(IsolateTestHelper::GetStackLimit(thread),
- IsolateTestHelper::GetSavedStackLimit(thread));
- EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterruptsMask(thread));
- EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterrupts(thread));
-
- {
- // Defer message interrupts.
- NoOOBMessageScope no_msg_scope(thread);
- EXPECT_EQ(IsolateTestHelper::GetStackLimit(thread),
- IsolateTestHelper::GetSavedStackLimit(thread));
- EXPECT_EQ(kMessageInterrupt,
- IsolateTestHelper::GetDeferredInterruptsMask(thread));
- EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterrupts(thread));
-
- // Schedule a message, it is deferred.
- thread->ScheduleInterrupts(Thread::kMessageInterrupt);
- EXPECT_EQ(IsolateTestHelper::GetStackLimit(thread),
- IsolateTestHelper::GetSavedStackLimit(thread));
- EXPECT_EQ(kMessageInterrupt,
- IsolateTestHelper::GetDeferredInterruptsMask(thread));
- EXPECT_EQ(kMessageInterrupt,
- IsolateTestHelper::GetDeferredInterrupts(thread));
-
- // Schedule a vm interrupt, it is not deferred.
- thread->ScheduleInterrupts(Thread::kVMInterrupt);
- stack_limit = IsolateTestHelper::GetStackLimit(thread);
- EXPECT_NE(stack_limit, IsolateTestHelper::GetSavedStackLimit(thread));
- EXPECT((stack_limit & Thread::kVMInterrupt) != 0);
- EXPECT_EQ(kMessageInterrupt,
- IsolateTestHelper::GetDeferredInterruptsMask(thread));
- EXPECT_EQ(kMessageInterrupt,
- IsolateTestHelper::GetDeferredInterrupts(thread));
-
- // Clear the vm interrupt. Message is still deferred.
- interrupt_bits = thread->GetAndClearInterrupts();
- EXPECT_EQ(kVMInterrupt, interrupt_bits);
- EXPECT_EQ(IsolateTestHelper::GetStackLimit(thread),
- IsolateTestHelper::GetSavedStackLimit(thread));
- EXPECT_EQ(kMessageInterrupt,
- IsolateTestHelper::GetDeferredInterruptsMask(thread));
- EXPECT_EQ(kMessageInterrupt,
- IsolateTestHelper::GetDeferredInterrupts(thread));
- }
-
- // Restore message interrupts. Message is now pending.
- stack_limit = IsolateTestHelper::GetStackLimit(thread);
- EXPECT_NE(stack_limit, IsolateTestHelper::GetSavedStackLimit(thread));
- EXPECT((stack_limit & Thread::kMessageInterrupt) != 0);
- EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterruptsMask(thread));
- EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterrupts(thread));
-
- {
- // Defer message interrupts, again. The pending interrupt is deferred.
- NoOOBMessageScope no_msg_scope(thread);
- EXPECT_EQ(IsolateTestHelper::GetStackLimit(thread),
- IsolateTestHelper::GetSavedStackLimit(thread));
- EXPECT_EQ(kMessageInterrupt,
- IsolateTestHelper::GetDeferredInterruptsMask(thread));
- EXPECT_EQ(kMessageInterrupt,
- IsolateTestHelper::GetDeferredInterrupts(thread));
- }
-
- // Restore, then clear interrupts. The world is as it was.
- interrupt_bits = thread->GetAndClearInterrupts();
- EXPECT_EQ(kMessageInterrupt, interrupt_bits);
- EXPECT_EQ(IsolateTestHelper::GetStackLimit(thread),
- IsolateTestHelper::GetSavedStackLimit(thread));
- EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterruptsMask(thread));
- EXPECT_EQ(kZero, IsolateTestHelper::GetDeferredInterrupts(thread));
-}
-
} // namespace dart
diff --git a/runtime/vm/kernel_binary.h b/runtime/vm/kernel_binary.h
index 57b229a..fb8c532 100644
--- a/runtime/vm/kernel_binary.h
+++ b/runtime/vm/kernel_binary.h
@@ -20,8 +20,8 @@
static const uint32_t kMagicProgramFile = 0x90ABCDEFu;
// Both version numbers are inclusive.
-static const uint32_t kMinSupportedKernelFormatVersion = 67;
-static const uint32_t kMaxSupportedKernelFormatVersion = 67;
+static const uint32_t kMinSupportedKernelFormatVersion = 69;
+static const uint32_t kMaxSupportedKernelFormatVersion = 69;
// Keep in sync with package:kernel/lib/binary/tag.dart
#define KERNEL_TAG_LIST(V) \
@@ -33,7 +33,7 @@
V(Field, 4) \
V(Constructor, 5) \
V(Procedure, 6) \
- V(RedirectingFactoryConstructor, 108) \
+ V(RedirectingFactory, 108) \
V(InvalidInitializer, 7) \
V(FieldInitializer, 8) \
V(SuperInitializer, 9) \
@@ -49,13 +49,10 @@
V(InvalidExpression, 19) \
V(VariableGet, 20) \
V(VariableSet, 21) \
- V(PropertyGet, 22) \
- V(PropertySet, 23) \
V(SuperPropertyGet, 24) \
V(SuperPropertySet, 25) \
V(StaticGet, 26) \
V(StaticSet, 27) \
- V(MethodInvocation, 28) \
V(SuperMethodInvocation, 29) \
V(StaticInvocation, 30) \
V(ConstructorInvocation, 31) \
@@ -98,6 +95,7 @@
V(ConstMapLiteral, 59) \
V(ConstructorTearOff, 60) \
V(TypedefTearOff, 83) \
+ V(RedirectingFactoryTearOff, 84) \
V(ExpressionStatement, 61) \
V(Block, 62) \
V(EmptyStatement, 63) \
@@ -175,6 +173,7 @@
kUnevaluatedConstant = 12,
kTypedefTearOffConstant = 14,
kConstructorTearOffConstant = 15,
+ kRedirectingFactoryTearOffConstant = 16,
};
// Keep in sync with package:kernel/lib/ast.dart
@@ -208,9 +207,9 @@
};
// Keep in sync with package:kernel/lib/ast.dart
-enum MethodInvocationFlags {
- kMethodInvocationFlagInvariant = 1 << 0,
- kMethodInvocationFlagBoundsSafe = 1 << 1,
+enum InstanceInvocationFlags {
+ kInstanceInvocationFlagInvariant = 1 << 0,
+ kInstanceInvocationFlagBoundsSafe = 1 << 1,
};
// Keep in sync with package:kernel/lib/ast.dart
diff --git a/runtime/vm/kernel_isolate.cc b/runtime/vm/kernel_isolate.cc
index 1ba9c22..066c7d4 100644
--- a/runtime/vm/kernel_isolate.cc
+++ b/runtime/vm/kernel_isolate.cc
@@ -88,6 +88,7 @@
Dart_IsolateFlags api_flags;
Isolate::FlagsInitialize(&api_flags);
api_flags.enable_asserts = false;
+ api_flags.null_safety = true;
api_flags.is_system_isolate = true;
#if !defined(DART_PRECOMPILER)
api_flags.use_field_guards = true;
diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc
index d6cbc64..a45e80c 100644
--- a/runtime/vm/kernel_loader.cc
+++ b/runtime/vm/kernel_loader.cc
@@ -1946,7 +1946,7 @@
// additional functions can cause strain on the VM. They are therefore skipped
// in jit mode and their associated origin function is used instead as
// interface call target.
- if (procedure_helper.IsRedirectingFactoryConstructor() ||
+ if (procedure_helper.IsRedirectingFactory() ||
(!FLAG_precompiled_mode && procedure_helper.IsMemberSignature())) {
helper_.SetOffset(procedure_end);
return;
diff --git a/runtime/vm/malloc_hooks_test.cc b/runtime/vm/malloc_hooks_test.cc
index 8edd992..d04ab64 100644
--- a/runtime/vm/malloc_hooks_test.cc
+++ b/runtime/vm/malloc_hooks_test.cc
@@ -176,7 +176,7 @@
EnableMallocHooksAndStacksScope scope;
ClearProfileVisitor cpv(Isolate::Current());
- Profiler::sample_buffer()->VisitSamples(&cpv);
+ Profiler::sample_block_buffer()->VisitSamples(&cpv);
char* var = static_cast<char*>(malloc(16 * sizeof(char)));
JSONStream js;
diff --git a/runtime/vm/message_snapshot.cc b/runtime/vm/message_snapshot.cc
new file mode 100644
index 0000000..37bb767
--- /dev/null
+++ b/runtime/vm/message_snapshot.cc
@@ -0,0 +1,3615 @@
+// 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.
+
+#include "vm/message_snapshot.h"
+
+#include <memory>
+
+#include "platform/assert.h"
+#include "platform/unicode.h"
+#include "vm/class_finalizer.h"
+#include "vm/class_id.h"
+#include "vm/dart_api_message.h"
+#include "vm/dart_api_state.h"
+#include "vm/dart_entry.h"
+#include "vm/flags.h"
+#include "vm/growable_array.h"
+#include "vm/heap/heap.h"
+#include "vm/heap/weak_table.h"
+#include "vm/longjump.h"
+#include "vm/object.h"
+#include "vm/object_store.h"
+#include "vm/symbols.h"
+#include "vm/type_testing_stubs.h"
+
+namespace dart {
+
+static Dart_CObject cobj_null = {.type = Dart_CObject_kNull,
+ .value = {.as_int64 = 0}};
+static Dart_CObject cobj_sentinel = {.type = Dart_CObject_kUnsupported};
+static Dart_CObject cobj_transition_sentinel = {.type =
+ Dart_CObject_kUnsupported};
+static Dart_CObject cobj_empty_array = {
+ .type = Dart_CObject_kArray,
+ .value = {.as_array = {.length = 0, .values = nullptr}}};
+static Dart_CObject cobj_zero_array_element = {.type = Dart_CObject_kInt32,
+ .value = {.as_int32 = 0}};
+static Dart_CObject* cobj_zero_array_values[1] = {&cobj_zero_array_element};
+static Dart_CObject cobj_zero_array = {
+ .type = Dart_CObject_kArray,
+ .value = {.as_array = {.length = 1, .values = &cobj_zero_array_values[0]}}};
+static Dart_CObject cobj_dynamic_type = {.type = Dart_CObject_kUnsupported};
+static Dart_CObject cobj_void_type = {.type = Dart_CObject_kUnsupported};
+static Dart_CObject cobj_empty_type_arguments = {.type =
+ Dart_CObject_kUnsupported};
+static Dart_CObject cobj_true = {.type = Dart_CObject_kBool,
+ .value = {.as_bool = true}};
+static Dart_CObject cobj_false = {.type = Dart_CObject_kBool,
+ .value = {.as_bool = false}};
+
+enum class MessagePhase {
+ kBeforeTypes = 0,
+ kTypes = 1,
+ kCanonicalInstances = 2,
+ kNonCanonicalInstances = 3,
+
+ kNumPhases = 4,
+};
+
+class MessageSerializer;
+class MessageDeserializer;
+class ApiMessageSerializer;
+class ApiMessageDeserializer;
+class WeakPropertyMessageSerializationCluster;
+
+class MessageSerializationCluster : public ZoneAllocated {
+ public:
+ explicit MessageSerializationCluster(const char* name,
+ MessagePhase phase,
+ intptr_t cid,
+ bool is_canonical = false)
+ : name_(name), phase_(phase), cid_(cid), is_canonical_(is_canonical) {}
+ virtual ~MessageSerializationCluster() {}
+
+ virtual void Trace(MessageSerializer* s, Object* object) = 0;
+ virtual void WriteNodes(MessageSerializer* s) = 0;
+ virtual void WriteEdges(MessageSerializer* s) {}
+
+ virtual void TraceApi(ApiMessageSerializer* s, Dart_CObject* object) {}
+ virtual void WriteNodesApi(ApiMessageSerializer* s) {}
+ virtual void WriteEdgesApi(ApiMessageSerializer* s) {}
+
+ const char* name() const { return name_; }
+ MessagePhase phase() const { return phase_; }
+ intptr_t cid() const { return cid_; }
+ bool is_canonical() const { return is_canonical_; }
+
+ protected:
+ const char* const name_;
+ const MessagePhase phase_;
+ const intptr_t cid_;
+ const bool is_canonical_;
+
+ DISALLOW_COPY_AND_ASSIGN(MessageSerializationCluster);
+};
+
+class MessageDeserializationCluster : public ZoneAllocated {
+ public:
+ explicit MessageDeserializationCluster(const char* name,
+ bool is_canonical = false)
+ : name_(name),
+ is_canonical_(is_canonical),
+ start_index_(0),
+ stop_index_(0) {}
+ virtual ~MessageDeserializationCluster() {}
+
+ virtual void ReadNodes(MessageDeserializer* d) = 0;
+ virtual void ReadEdges(MessageDeserializer* d) {}
+ virtual ObjectPtr PostLoad(MessageDeserializer* d) { return nullptr; }
+ virtual void ReadNodesApi(ApiMessageDeserializer* d) {}
+ virtual void ReadEdgesApi(ApiMessageDeserializer* d) {}
+ virtual void PostLoadApi(ApiMessageDeserializer* d) {}
+
+ void ReadNodesWrapped(MessageDeserializer* d);
+ void ReadNodesWrappedApi(ApiMessageDeserializer* d);
+
+ const char* name() const { return name_; }
+ bool is_canonical() const { return is_canonical_; }
+
+ protected:
+ ObjectPtr PostLoadAbstractType(MessageDeserializer* d);
+ ObjectPtr PostLoadLinkedHash(MessageDeserializer* d);
+
+ const char* const name_;
+ const bool is_canonical_;
+ // The range of the ref array that belongs to this cluster.
+ intptr_t start_index_;
+ intptr_t stop_index_;
+
+ DISALLOW_COPY_AND_ASSIGN(MessageDeserializationCluster);
+};
+
+class BaseSerializer : public StackResource {
+ public:
+ BaseSerializer(Thread* thread, Zone* zone);
+ ~BaseSerializer();
+
+ // Writes raw data to the stream (basic type).
+ // sizeof(T) must be in {1,2,4,8}.
+ template <typename T>
+ void Write(T value) {
+ BaseWriteStream::Raw<sizeof(T), T>::Write(&stream_, value);
+ }
+ void WriteUnsigned(intptr_t value) { stream_.WriteUnsigned(value); }
+ void WriteWordWith32BitWrites(uword value) {
+ stream_.WriteWordWith32BitWrites(value);
+ }
+ void WriteBytes(const uint8_t* addr, intptr_t len) {
+ stream_.WriteBytes(addr, len);
+ }
+ void WriteAscii(const String& str) {
+ intptr_t len = str.Length();
+ WriteUnsigned(len);
+ for (intptr_t i = 0; i < len; i++) {
+ int64_t c = str.CharAt(i);
+ ASSERT(c < 128);
+ Write<uint8_t>(c);
+ }
+ Write<uint8_t>(0);
+ }
+
+ MessageSerializationCluster* NewClusterForClass(intptr_t cid,
+ bool is_canonical);
+ void WriteCluster(MessageSerializationCluster* cluster);
+
+ std::unique_ptr<Message> Finish(Dart_Port dest_port,
+ Message::Priority priority) {
+ MessageFinalizableData* finalizable_data = finalizable_data_;
+ finalizable_data_ = nullptr;
+ finalizable_data->SerializationSucceeded();
+ intptr_t size;
+ uint8_t* buffer = stream_.Steal(&size);
+ return Message::New(dest_port, buffer, size, finalizable_data, priority);
+ }
+
+ Zone* zone() const { return zone_; }
+ MessageFinalizableData* finalizable_data() const { return finalizable_data_; }
+ intptr_t next_ref_index() const { return next_ref_index_; }
+
+ protected:
+ Zone* const zone_;
+ MallocWriteStream stream_;
+ MessageFinalizableData* finalizable_data_;
+ GrowableArray<MessageSerializationCluster*> clusters_;
+ WeakPropertyMessageSerializationCluster* ephemeron_cluster_;
+ intptr_t num_base_objects_;
+ intptr_t num_written_objects_;
+ intptr_t next_ref_index_;
+};
+
+class MessageSerializer : public BaseSerializer {
+ public:
+ MessageSerializer(Thread* thread, bool can_send_any_object);
+ ~MessageSerializer();
+
+ bool MarkObjectId(ObjectPtr object, intptr_t id) {
+ ASSERT(id != WeakTable::kNoValue);
+ WeakTable* table;
+ if (!object->IsSmiOrOldObject()) {
+ table = isolate()->forward_table_new();
+ } else {
+ table = isolate()->forward_table_old();
+ }
+ return table->MarkValueExclusive(object, id);
+ }
+
+ void SetObjectId(ObjectPtr object, intptr_t id) {
+ ASSERT(id != WeakTable::kNoValue);
+ WeakTable* table;
+ if (!object->IsSmiOrOldObject()) {
+ table = isolate()->forward_table_new();
+ } else {
+ table = isolate()->forward_table_old();
+ }
+ table->SetValueExclusive(object, id);
+ }
+
+ intptr_t GetObjectId(ObjectPtr object) const {
+ const WeakTable* table;
+ if (!object->IsSmiOrOldObject()) {
+ table = isolate()->forward_table_new();
+ } else {
+ table = isolate()->forward_table_old();
+ }
+ return table->GetValueExclusive(object);
+ }
+
+ DART_NOINLINE void AddBaseObject(ObjectPtr base_object) {
+ AssignRef(base_object);
+ num_base_objects_++;
+ }
+ DART_NOINLINE void AssignRef(ObjectPtr object) {
+ SetObjectId(object, next_ref_index_);
+ next_ref_index_++;
+ }
+ void AssignRef(Object* object) { AssignRef(object->ptr()); }
+
+ void Push(ObjectPtr object);
+
+ void Trace(Object* object);
+
+ void IllegalObject(const Object& object, const char* message);
+
+ void AddBaseObjects();
+ void Serialize(const Object& root);
+
+ DART_NOINLINE void WriteRef(ObjectPtr object) {
+ intptr_t index = GetObjectId(object);
+ ASSERT(index != WeakTable::kNoValue);
+ WriteUnsigned(index);
+ }
+
+ bool can_send_any_object() const { return can_send_any_object_; }
+ const char* exception_message() const { return exception_message_; }
+ Thread* thread() const {
+ return static_cast<Thread*>(StackResource::thread());
+ }
+ Isolate* isolate() const { return thread()->isolate(); }
+ IsolateGroup* isolate_group() const { return thread()->isolate_group(); }
+
+ bool HasRef(ObjectPtr object) const {
+ return GetObjectId(object) != WeakTable::kNoValue;
+ }
+
+ private:
+ WeakTable* forward_table_new_;
+ WeakTable* forward_table_old_;
+ GrowableArray<Object*> stack_;
+ bool const can_send_any_object_;
+ const char* exception_message_;
+};
+
+class ApiMessageSerializer : public BaseSerializer {
+ public:
+ explicit ApiMessageSerializer(Zone* zone);
+ ~ApiMessageSerializer();
+
+ bool MarkObjectId(Dart_CObject* object, intptr_t id) {
+ ASSERT(id != WeakTable::kNoValue);
+ return forward_table_.MarkValueExclusive(
+ static_cast<ObjectPtr>(reinterpret_cast<uword>(object)), id);
+ }
+
+ void SetObjectId(Dart_CObject* object, intptr_t id) {
+ ASSERT(id != WeakTable::kNoValue);
+ forward_table_.SetValueExclusive(
+ static_cast<ObjectPtr>(reinterpret_cast<uword>(object)), id);
+ }
+
+ intptr_t GetObjectId(Dart_CObject* object) const {
+ return forward_table_.GetValueExclusive(
+ static_cast<ObjectPtr>(reinterpret_cast<uword>(object)));
+ }
+
+ DART_NOINLINE void AddBaseObject(Dart_CObject* base_object) {
+ AssignRef(base_object);
+ num_base_objects_++;
+ }
+ DART_NOINLINE intptr_t AssignRef(Dart_CObject* object) {
+ SetObjectId(object, next_ref_index_);
+ return next_ref_index_++;
+ }
+ void ForwardRef(Dart_CObject* old, Dart_CObject* nue) {
+ intptr_t id = GetObjectId(nue);
+ ASSERT(id != WeakTable::kNoValue);
+ SetObjectId(old, id);
+ num_written_objects_--;
+ }
+
+ void Push(Dart_CObject* object);
+
+ bool Trace(Dart_CObject* object);
+
+ void AddBaseObjects();
+ bool Serialize(Dart_CObject* root);
+
+ void WriteRef(Dart_CObject* object) {
+ intptr_t index = GetObjectId(object);
+ ASSERT(index != WeakTable::kNoValue);
+ WriteUnsigned(index);
+ }
+
+ bool Fail(const char* message) {
+ exception_message_ = message;
+ return false;
+ }
+
+ private:
+ WeakTable forward_table_;
+ GrowableArray<Dart_CObject*> stack_;
+ const char* exception_message_;
+};
+
+class BaseDeserializer : public ValueObject {
+ public:
+ BaseDeserializer(Zone* zone, Message* message);
+ ~BaseDeserializer();
+
+ // Reads raw data (for basic types).
+ // sizeof(T) must be in {1,2,4,8}.
+ template <typename T>
+ T Read() {
+ return ReadStream::Raw<sizeof(T), T>::Read(&stream_);
+ }
+ intptr_t ReadUnsigned() { return stream_.ReadUnsigned(); }
+ uword ReadWordWith32BitReads() { return stream_.ReadWordWith32BitReads(); }
+ void ReadBytes(uint8_t* addr, intptr_t len) { stream_.ReadBytes(addr, len); }
+ const char* ReadAscii() {
+ intptr_t len = ReadUnsigned();
+ const char* result = reinterpret_cast<const char*>(CurrentBufferAddress());
+ Advance(len + 1);
+ return result;
+ }
+
+ const uint8_t* CurrentBufferAddress() const {
+ return stream_.AddressOfCurrentPosition();
+ }
+
+ void Advance(intptr_t value) { stream_.Advance(value); }
+
+ MessageDeserializationCluster* ReadCluster();
+
+ Zone* zone() const { return zone_; }
+ intptr_t next_index() const { return next_ref_index_; }
+ MessageFinalizableData* finalizable_data() const { return finalizable_data_; }
+
+ protected:
+ Zone* zone_;
+ ReadStream stream_;
+ MessageFinalizableData* finalizable_data_;
+ intptr_t next_ref_index_;
+};
+
+class MessageDeserializer : public BaseDeserializer {
+ public:
+ MessageDeserializer(Thread* thread, Message* message)
+ : BaseDeserializer(thread->zone(), message),
+ thread_(thread),
+ refs_(Array::Handle(thread->zone())) {}
+ ~MessageDeserializer() {}
+
+ DART_NOINLINE void AddBaseObject(ObjectPtr base_object) {
+ AssignRef(base_object);
+ }
+ void AssignRef(ObjectPtr object) {
+ refs_.untag()->set_element(next_ref_index_, object);
+ next_ref_index_++;
+ }
+
+ ObjectPtr Ref(intptr_t index) const {
+ ASSERT(index > 0);
+ ASSERT(index <= next_ref_index_);
+ return refs_.At(index);
+ }
+ void UpdateRef(intptr_t index, const Object& new_object) {
+ ASSERT(index > 0);
+ ASSERT(index <= next_ref_index_);
+ refs_.SetAt(index, new_object);
+ }
+
+ ObjectPtr ReadRef() { return Ref(ReadUnsigned()); }
+
+ void AddBaseObjects();
+ ObjectPtr Deserialize();
+
+ Thread* thread() const { return thread_; }
+ IsolateGroup* isolate_group() const { return thread_->isolate_group(); }
+ ArrayPtr refs() const { return refs_.ptr(); }
+
+ private:
+ Thread* const thread_;
+ Array& refs_;
+};
+
+class ApiMessageDeserializer : public BaseDeserializer {
+ public:
+ ApiMessageDeserializer(Zone* zone, Message* message)
+ : BaseDeserializer(zone, message), refs_(nullptr) {}
+ ~ApiMessageDeserializer() {}
+
+ void AddBaseObject(Dart_CObject* base_object) { AssignRef(base_object); }
+ void AssignRef(Dart_CObject* object) {
+ refs_[next_ref_index_] = object;
+ next_ref_index_++;
+ }
+
+ Dart_CObject* Allocate(Dart_CObject_Type type) {
+ Dart_CObject* result = zone()->Alloc<Dart_CObject>(1);
+ result->type = type;
+ return result;
+ }
+
+ Dart_CObject* Ref(intptr_t index) const {
+ ASSERT(index > 0);
+ ASSERT(index <= next_ref_index_);
+ return refs_[index];
+ }
+
+ Dart_CObject* ReadRef() { return Ref(ReadUnsigned()); }
+
+ void AddBaseObjects();
+ Dart_CObject* Deserialize();
+
+ private:
+ Dart_CObject** refs_;
+};
+
+void MessageDeserializationCluster::ReadNodesWrapped(MessageDeserializer* d) {
+ start_index_ = d->next_index();
+ this->ReadNodes(d);
+ stop_index_ = d->next_index();
+}
+
+void MessageDeserializationCluster::ReadNodesWrappedApi(
+ ApiMessageDeserializer* d) {
+ start_index_ = d->next_index();
+ this->ReadNodesApi(d);
+ stop_index_ = d->next_index();
+}
+
+ObjectPtr MessageDeserializationCluster::PostLoadAbstractType(
+ MessageDeserializer* d) {
+ ClassFinalizer::FinalizationKind finalization =
+ is_canonical() ? ClassFinalizer::kCanonicalize
+ : ClassFinalizer::kFinalize;
+ AbstractType& type = AbstractType::Handle(d->zone());
+ Code& code = Code::Handle(d->zone());
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ type ^= d->Ref(id);
+
+ code = TypeTestingStubGenerator::DefaultCodeForType(type);
+ type.InitializeTypeTestingStubNonAtomic(code);
+
+ type ^= ClassFinalizer::FinalizeType(type, finalization);
+ d->UpdateRef(id, type);
+ }
+ return nullptr;
+}
+
+ObjectPtr MessageDeserializationCluster::PostLoadLinkedHash(
+ MessageDeserializer* d) {
+ ASSERT(!is_canonical());
+ Array& maps = Array::Handle(d->zone(), d->refs());
+ maps = maps.Slice(start_index_, stop_index_ - start_index_,
+ /*with_type_argument=*/false);
+ return DartLibraryCalls::RehashObjects(d->thread(), maps);
+}
+
+class ClassMessageSerializationCluster : public MessageSerializationCluster {
+ public:
+ ClassMessageSerializationCluster()
+ : MessageSerializationCluster("Class",
+ MessagePhase::kBeforeTypes,
+ kClassCid),
+ objects_() {}
+ ~ClassMessageSerializationCluster() {}
+
+ void Trace(MessageSerializer* s, Object* object) {
+ Class* cls = static_cast<Class*>(object);
+ objects_.Add(cls);
+ }
+
+ void WriteNodes(MessageSerializer* s) {
+ intptr_t count = objects_.length();
+ s->WriteUnsigned(count);
+ Library& lib = Library::Handle(s->zone());
+ String& str = String::Handle(s->zone());
+ for (intptr_t i = 0; i < count; i++) {
+ Class* cls = objects_[i];
+ s->AssignRef(cls);
+ intptr_t cid = cls->id();
+ if (cid < kNumPredefinedCids) {
+ ASSERT(cid != 0);
+ s->WriteUnsigned(cid);
+ } else {
+ s->WriteUnsigned(0);
+ lib = cls->library();
+ str = lib.url();
+ s->WriteAscii(str);
+ str = cls->Name();
+ s->WriteAscii(str);
+ }
+ }
+ }
+
+ private:
+ GrowableArray<Class*> objects_;
+};
+
+class ClassMessageDeserializationCluster
+ : public MessageDeserializationCluster {
+ public:
+ ClassMessageDeserializationCluster()
+ : MessageDeserializationCluster("Class") {}
+ ~ClassMessageDeserializationCluster() {}
+
+ void ReadNodes(MessageDeserializer* d) {
+ auto* class_table = d->isolate_group()->class_table();
+ String& str = String::Handle(d->zone());
+ Library& lib = Library::Handle(d->zone());
+ Class& cls = Class::Handle(d->zone());
+ intptr_t count = d->ReadUnsigned();
+ for (intptr_t i = 0; i < count; i++) {
+ intptr_t cid = d->ReadUnsigned();
+ if (cid != 0) {
+ cls = class_table->At(cid);
+ } else {
+ str = String::New(d->ReadAscii()); // Library URI.
+ lib = Library::LookupLibrary(d->thread(), str);
+ RELEASE_ASSERT(!lib.IsNull());
+ str = String::New(d->ReadAscii()); // Class name.
+ if (str.Equals(Symbols::TopLevel())) {
+ cls = lib.toplevel_class();
+ } else {
+ cls = lib.LookupClass(str);
+ }
+ RELEASE_ASSERT(!cls.IsNull());
+ cls.EnsureIsFinalized(d->thread());
+ }
+ d->AssignRef(cls.ptr());
+ }
+ }
+
+ void ReadNodesApi(ApiMessageDeserializer* d) {
+ intptr_t count = d->ReadUnsigned();
+ for (intptr_t i = 0; i < count; i++) {
+ intptr_t cid = d->ReadUnsigned();
+ if (cid == 0) {
+ d->ReadAscii(); // Library URI.
+ d->ReadAscii(); // Class name.
+ }
+ d->AssignRef(nullptr);
+ }
+ }
+};
+
+class TypeArgumentsMessageSerializationCluster
+ : public MessageSerializationCluster {
+ public:
+ explicit TypeArgumentsMessageSerializationCluster(bool is_canonical)
+ : MessageSerializationCluster("TypeArguments",
+ MessagePhase::kTypes,
+ kTypeArgumentsCid,
+ is_canonical) {}
+ ~TypeArgumentsMessageSerializationCluster() {}
+
+ void Trace(MessageSerializer* s, Object* object) {
+ TypeArguments* type_args = static_cast<TypeArguments*>(object);
+ objects_.Add(type_args);
+
+ s->Push(type_args->untag()->instantiations());
+ intptr_t length = Smi::Value(type_args->untag()->length());
+ for (intptr_t i = 0; i < length; i++) {
+ s->Push(type_args->untag()->element(i));
+ }
+ }
+
+ void WriteNodes(MessageSerializer* s) {
+ intptr_t count = objects_.length();
+ s->WriteUnsigned(count);
+ for (intptr_t i = 0; i < count; i++) {
+ TypeArguments* type_args = objects_[i];
+ s->AssignRef(type_args);
+ intptr_t length = Smi::Value(type_args->untag()->length());
+ s->WriteUnsigned(length);
+ }
+ }
+
+ void WriteEdges(MessageSerializer* s) {
+ intptr_t count = objects_.length();
+ for (intptr_t i = 0; i < count; i++) {
+ TypeArguments* type_args = objects_[i];
+ intptr_t hash = Smi::Value(type_args->untag()->hash());
+ s->Write<int32_t>(hash);
+ const intptr_t nullability =
+ Smi::Value(type_args->untag()->nullability());
+ s->WriteUnsigned(nullability);
+
+ intptr_t length = Smi::Value(type_args->untag()->length());
+ s->WriteUnsigned(length);
+ for (intptr_t j = 0; j < length; j++) {
+ s->WriteRef(type_args->untag()->element(j));
+ }
+ }
+ }
+
+ private:
+ GrowableArray<TypeArguments*> objects_;
+};
+
+class TypeArgumentsMessageDeserializationCluster
+ : public MessageDeserializationCluster {
+ public:
+ explicit TypeArgumentsMessageDeserializationCluster(bool is_canonical)
+ : MessageDeserializationCluster("TypeArguments", is_canonical) {}
+ ~TypeArgumentsMessageDeserializationCluster() {}
+
+ void ReadNodes(MessageDeserializer* d) {
+ intptr_t count = d->ReadUnsigned();
+ for (intptr_t i = 0; i < count; i++) {
+ intptr_t length = d->ReadUnsigned();
+ d->AssignRef(TypeArguments::New(length));
+ }
+ }
+
+ void ReadEdges(MessageDeserializer* d) {
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ TypeArgumentsPtr type_args = static_cast<TypeArgumentsPtr>(d->Ref(id));
+
+ type_args->untag()->hash_ = Smi::New(d->Read<int32_t>());
+ type_args->untag()->nullability_ = Smi::New(d->ReadUnsigned());
+
+ intptr_t length = d->ReadUnsigned();
+ for (intptr_t j = 0; j < length; j++) {
+ type_args->untag()->types()[j] =
+ static_cast<AbstractTypePtr>(d->ReadRef());
+ }
+ }
+ }
+
+ ObjectPtr PostLoad(MessageDeserializer* d) {
+ if (is_canonical()) {
+ TypeArguments& type_args = TypeArguments::Handle(d->zone());
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ type_args ^= d->Ref(id);
+ type_args ^= type_args.Canonicalize(d->thread());
+ d->UpdateRef(id, type_args);
+ }
+ }
+ return nullptr;
+ }
+
+ void ReadNodesApi(ApiMessageDeserializer* d) {
+ intptr_t count = d->ReadUnsigned();
+ for (intptr_t i = 0; i < count; i++) {
+ d->ReadUnsigned(); // Length.
+ d->AssignRef(nullptr);
+ }
+ }
+
+ void ReadEdgesApi(ApiMessageDeserializer* d) {
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ d->Read<int32_t>(); // Hash.
+ d->ReadUnsigned(); // Nullability.
+ intptr_t length = d->ReadUnsigned();
+ for (intptr_t j = 0; j < length; j++) {
+ d->ReadRef(); // Element.
+ }
+ }
+ }
+};
+
+class FunctionMessageSerializationCluster : public MessageSerializationCluster {
+ public:
+ FunctionMessageSerializationCluster()
+ : MessageSerializationCluster("Function",
+ MessagePhase::kBeforeTypes,
+ kFunctionCid) {}
+ ~FunctionMessageSerializationCluster() {}
+
+ void Trace(MessageSerializer* s, Object* object) {
+ Function* func = static_cast<Function*>(object);
+ objects_.Add(func);
+ }
+
+ void WriteNodes(MessageSerializer* s) {
+ intptr_t count = objects_.length();
+ s->WriteUnsigned(count);
+ Library& lib = Library::Handle(s->zone());
+ Class& cls = Class::Handle(s->zone());
+ String& str = String::Handle(s->zone());
+ for (intptr_t i = 0; i < count; i++) {
+ Function* func = objects_[i];
+ s->AssignRef(func);
+ cls ^= func->Owner();
+ lib = cls.library();
+ str = lib.url();
+ s->WriteAscii(str);
+ str = cls.Name();
+ s->WriteAscii(str);
+ str = func->name();
+ s->WriteAscii(str);
+ }
+ }
+
+ private:
+ GrowableArray<Function*> objects_;
+};
+
+class FunctionMessageDeserializationCluster
+ : public MessageDeserializationCluster {
+ public:
+ FunctionMessageDeserializationCluster()
+ : MessageDeserializationCluster("Function") {}
+ ~FunctionMessageDeserializationCluster() {}
+
+ void ReadNodes(MessageDeserializer* d) {
+ intptr_t count = d->ReadUnsigned();
+ String& str = String::Handle(d->zone());
+ Library& lib = Library::Handle(d->zone());
+ Class& cls = Class::Handle(d->zone());
+ Function& func = Function::Handle(d->zone());
+ for (intptr_t i = 0; i < count; i++) {
+ str = String::New(d->ReadAscii()); // Library URI.
+ lib = Library::LookupLibrary(d->thread(), str);
+ RELEASE_ASSERT(!lib.IsNull());
+ str = String::New(d->ReadAscii()); // Class name.
+ if (str.Equals(Symbols::TopLevel())) {
+ cls = lib.toplevel_class();
+ } else {
+ cls = lib.LookupClass(str);
+ }
+ RELEASE_ASSERT(!cls.IsNull());
+ cls.EnsureIsFinalized(d->thread());
+ str = String::New(d->ReadAscii()); // Function name.
+ func = cls.LookupStaticFunction(str);
+ RELEASE_ASSERT(!func.IsNull());
+ d->AssignRef(func.ptr());
+ }
+ }
+};
+
+class InstanceMessageSerializationCluster : public MessageSerializationCluster {
+ public:
+ InstanceMessageSerializationCluster(bool is_canonical, intptr_t cid)
+ : MessageSerializationCluster("Instance",
+ is_canonical
+ ? MessagePhase::kCanonicalInstances
+ : MessagePhase::kNonCanonicalInstances,
+ cid,
+ is_canonical),
+ cls_(Class::Handle()) {
+ cls_ = IsolateGroup::Current()->class_table()->At(cid);
+ next_field_offset_ = cls_.host_next_field_offset();
+ }
+ ~InstanceMessageSerializationCluster() {}
+
+ void Trace(MessageSerializer* s, Object* object) {
+ Instance* instance = static_cast<Instance*>(object);
+ objects_.Add(instance);
+
+ const intptr_t next_field_offset = next_field_offset_;
+ const auto unboxed_fields_bitmap =
+ s->isolate_group()->shared_class_table()->GetUnboxedFieldsMapAt(cid_);
+ for (intptr_t offset = Instance::NextFieldOffset();
+ offset < next_field_offset; offset += kCompressedWordSize) {
+ if (unboxed_fields_bitmap.Get(offset / kCompressedWordSize)) {
+ continue;
+ }
+ s->Push(reinterpret_cast<CompressedObjectPtr*>(
+ reinterpret_cast<uword>(instance->untag()) + offset)
+ ->Decompress(instance->untag()->heap_base()));
+ }
+ }
+
+ void WriteNodes(MessageSerializer* s) {
+ s->WriteRef(cls_.ptr());
+
+ intptr_t count = objects_.length();
+ s->WriteUnsigned(count);
+ for (intptr_t i = 0; i < count; i++) {
+ Instance* instance = objects_[i];
+ s->AssignRef(instance);
+ }
+ }
+
+ void WriteEdges(MessageSerializer* s) {
+ intptr_t count = objects_.length();
+ for (intptr_t i = 0; i < count; i++) {
+ Instance* instance = objects_[i];
+
+ const intptr_t next_field_offset = next_field_offset_;
+ const auto unboxed_fields_bitmap =
+ s->isolate_group()->shared_class_table()->GetUnboxedFieldsMapAt(cid_);
+ for (intptr_t offset = Instance::NextFieldOffset();
+ offset < next_field_offset; offset += kCompressedWordSize) {
+ if (unboxed_fields_bitmap.Get(offset / kCompressedWordSize)) {
+ // Writes 32 bits of the unboxed value at a time
+ const uword value = *reinterpret_cast<compressed_uword*>(
+ reinterpret_cast<uword>(instance->untag()) + offset);
+ s->WriteWordWith32BitWrites(value);
+ } else {
+ s->WriteRef(reinterpret_cast<CompressedObjectPtr*>(
+ reinterpret_cast<uword>(instance->untag()) + offset)
+ ->Decompress(instance->untag()->heap_base()));
+ }
+ }
+ }
+ }
+
+ private:
+ Class& cls_;
+ intptr_t next_field_offset_;
+ GrowableArray<Instance*> objects_;
+};
+
+class InstanceMessageDeserializationCluster
+ : public MessageDeserializationCluster {
+ public:
+ explicit InstanceMessageDeserializationCluster(bool is_canonical)
+ : MessageDeserializationCluster("Instance", is_canonical),
+ cls_(Class::Handle()) {}
+ ~InstanceMessageDeserializationCluster() {}
+
+ void ReadNodes(MessageDeserializer* d) {
+ cls_ ^= d->ReadRef();
+
+ intptr_t count = d->ReadUnsigned();
+ for (intptr_t i = 0; i < count; i++) {
+ d->AssignRef(Instance::New(cls_));
+ }
+ }
+
+ void ReadEdges(MessageDeserializer* d) {
+ const intptr_t next_field_offset = cls_.host_next_field_offset();
+ const intptr_t type_argument_field_offset =
+ cls_.host_type_arguments_field_offset();
+ const auto unboxed_fields_bitmap =
+ d->isolate_group()->shared_class_table()->GetUnboxedFieldsMapAt(
+ cls_.id());
+ const bool use_field_guards = d->isolate_group()->use_field_guards();
+ const Array& field_map = Array::Handle(d->zone(), cls_.OffsetToFieldMap());
+ Instance& instance = Instance::Handle(d->zone());
+ Object& value = Object::Handle(d->zone());
+ Field& field = Field::Handle(d->zone());
+
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ instance ^= d->Ref(id);
+ for (intptr_t offset = Instance::NextFieldOffset();
+ offset < next_field_offset; offset += kCompressedWordSize) {
+ if (unboxed_fields_bitmap.Get(offset / kCompressedWordSize)) {
+ compressed_uword* p = reinterpret_cast<compressed_uword*>(
+ reinterpret_cast<uword>(instance.untag()) + offset);
+ // Reads 32 bits of the unboxed value at a time
+ *p = d->ReadWordWith32BitReads();
+ } else {
+ value = d->ReadRef();
+ instance.SetFieldAtOffset(offset, value);
+ if (use_field_guards && (offset != type_argument_field_offset) &&
+ (value.ptr() != Object::sentinel().ptr())) {
+ field ^= field_map.At(offset >> kCompressedWordSizeLog2);
+ ASSERT(!field.IsNull());
+ ASSERT(field.HostOffset() == offset);
+ field.RecordStore(value);
+ }
+ }
+ }
+ }
+ }
+
+ ObjectPtr PostLoad(MessageDeserializer* d) {
+ if (is_canonical()) {
+ SafepointMutexLocker ml(
+ d->isolate_group()->constant_canonicalization_mutex());
+ Instance& instance = Instance::Handle(d->zone());
+ for (intptr_t i = start_index_; i < stop_index_; i++) {
+ instance ^= d->Ref(i);
+ instance = instance.CanonicalizeLocked(d->thread());
+ d->UpdateRef(i, instance);
+ }
+ }
+
+ if (cls_.ptr() == d->isolate_group()->object_store()->expando_class()) {
+ Instance& instance = Instance::Handle(d->zone());
+ const String& selector = Library::PrivateCoreLibName(Symbols::_rehash());
+ Array& args = Array::Handle(d->zone(), Array::New(1));
+ for (intptr_t i = start_index_; i < stop_index_; i++) {
+ instance ^= d->Ref(i);
+ args.SetAt(0, instance);
+ ObjectPtr error = instance.Invoke(selector, args, Object::empty_array(),
+ false, false);
+ if (error != Object::null()) {
+ return error;
+ }
+ }
+ }
+ return nullptr;
+ }
+
+ private:
+ Class& cls_;
+};
+
+class TypeMessageSerializationCluster : public MessageSerializationCluster {
+ public:
+ explicit TypeMessageSerializationCluster(bool is_canonical)
+ : MessageSerializationCluster("Type",
+ MessagePhase::kTypes,
+ kTypeCid,
+ is_canonical) {}
+ ~TypeMessageSerializationCluster() {}
+
+ void Trace(MessageSerializer* s, Object* object) {
+ Type* type = static_cast<Type*>(object);
+ objects_.Add(type);
+
+ s->Push(type->type_class());
+ s->Push(type->arguments());
+ }
+
+ void WriteNodes(MessageSerializer* s) {
+ intptr_t count = objects_.length();
+ s->WriteUnsigned(count);
+ for (intptr_t i = 0; i < count; i++) {
+ Type* type = objects_[i];
+ s->AssignRef(type);
+ }
+ }
+
+ void WriteEdges(MessageSerializer* s) {
+ intptr_t count = objects_.length();
+ for (intptr_t i = 0; i < count; i++) {
+ Type* type = objects_[i];
+ s->WriteRef(type->type_class());
+ s->WriteRef(type->arguments());
+ s->Write<uint8_t>(static_cast<uint8_t>(type->nullability()));
+ }
+ }
+
+ private:
+ GrowableArray<Type*> objects_;
+};
+
+class TypeMessageDeserializationCluster : public MessageDeserializationCluster {
+ public:
+ explicit TypeMessageDeserializationCluster(bool is_canonical)
+ : MessageDeserializationCluster("Type", is_canonical) {}
+ ~TypeMessageDeserializationCluster() {}
+
+ void ReadNodes(MessageDeserializer* d) {
+ intptr_t count = d->ReadUnsigned();
+ for (intptr_t i = 0; i < count; i++) {
+ d->AssignRef(Type::New());
+ }
+ }
+
+ void ReadEdges(MessageDeserializer* d) {
+ Class& cls = Class::Handle(d->zone());
+ Type& type = Type::Handle(d->zone());
+ TypeArguments& type_args = TypeArguments::Handle(d->zone());
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ type ^= d->Ref(id);
+ cls ^= d->ReadRef();
+ type.set_type_class(cls);
+ type_args ^= d->ReadRef();
+ type.set_arguments(type_args);
+ type.untag()->set_hash(Smi::New(0));
+ type.set_nullability(static_cast<Nullability>(d->Read<uint8_t>()));
+ type.SetIsFinalized();
+ }
+ }
+
+ ObjectPtr PostLoad(MessageDeserializer* d) { return PostLoadAbstractType(d); }
+
+ void ReadNodesApi(ApiMessageDeserializer* d) {
+ intptr_t count = d->ReadUnsigned();
+ for (intptr_t i = 0; i < count; i++) {
+ d->AssignRef(nullptr);
+ }
+ }
+
+ void ReadEdgesApi(ApiMessageDeserializer* d) {
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ d->ReadRef(); // Class.
+ d->ReadRef(); // Type arguments.
+ d->Read<uint8_t>(); // Nullability.
+ }
+ }
+};
+
+class TypeRefMessageSerializationCluster : public MessageSerializationCluster {
+ public:
+ explicit TypeRefMessageSerializationCluster(bool is_canonical)
+ : MessageSerializationCluster("TypeRef",
+ MessagePhase::kTypes,
+ kTypeRefCid,
+ is_canonical) {}
+ ~TypeRefMessageSerializationCluster() {}
+
+ void Trace(MessageSerializer* s, Object* object) {
+ TypeRef* type = static_cast<TypeRef*>(object);
+ objects_.Add(type);
+
+ s->Push(type->type());
+ }
+
+ void WriteNodes(MessageSerializer* s) {
+ intptr_t count = objects_.length();
+ s->WriteUnsigned(count);
+ for (intptr_t i = 0; i < count; i++) {
+ TypeRef* type = objects_[i];
+ s->AssignRef(type);
+ }
+ }
+
+ void WriteEdges(MessageSerializer* s) {
+ intptr_t count = objects_.length();
+ for (intptr_t i = 0; i < count; i++) {
+ TypeRef* type = objects_[i];
+ s->WriteRef(type->type());
+ }
+ }
+
+ private:
+ GrowableArray<TypeRef*> objects_;
+};
+
+class TypeRefMessageDeserializationCluster
+ : public MessageDeserializationCluster {
+ public:
+ explicit TypeRefMessageDeserializationCluster(bool is_canonical)
+ : MessageDeserializationCluster("TypeRef", is_canonical) {}
+ ~TypeRefMessageDeserializationCluster() {}
+
+ void ReadNodes(MessageDeserializer* d) {
+ intptr_t count = d->ReadUnsigned();
+ for (intptr_t i = 0; i < count; i++) {
+ d->AssignRef(TypeRef::New());
+ }
+ }
+
+ void ReadEdges(MessageDeserializer* d) {
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ TypeRefPtr type = static_cast<TypeRefPtr>(d->Ref(id));
+ type->untag()->set_type(static_cast<AbstractTypePtr>(d->ReadRef()));
+ }
+ }
+
+ ObjectPtr PostLoad(MessageDeserializer* d) {
+ ClassFinalizer::FinalizationKind finalization =
+ is_canonical() ? ClassFinalizer::kCanonicalize
+ : ClassFinalizer::kFinalize;
+ Code& code = Code::Handle(d->zone());
+ TypeRef& type = TypeRef::Handle(d->zone());
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ type ^= d->Ref(id);
+ type ^= ClassFinalizer::FinalizeType(type, finalization);
+ d->UpdateRef(id, type);
+
+ code = TypeTestingStubGenerator::DefaultCodeForType(type);
+ type.InitializeTypeTestingStubNonAtomic(code);
+ }
+ return nullptr;
+ }
+
+ void ReadNodesApi(ApiMessageDeserializer* d) {
+ intptr_t count = d->ReadUnsigned();
+ for (intptr_t i = 0; i < count; i++) {
+ d->AssignRef(nullptr);
+ }
+ }
+
+ void ReadEdgesApi(ApiMessageDeserializer* d) {
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ d->ReadRef(); // Type.
+ }
+ }
+};
+
+class ClosureMessageSerializationCluster : public MessageSerializationCluster {
+ public:
+ explicit ClosureMessageSerializationCluster(bool is_canonical)
+ : MessageSerializationCluster("Closure",
+ MessagePhase::kCanonicalInstances,
+ kClosureCid,
+ is_canonical) {}
+ ~ClosureMessageSerializationCluster() {}
+
+ void Trace(MessageSerializer* s, Object* object) {
+ Closure* closure = static_cast<Closure*>(object);
+
+ if (!s->can_send_any_object() ||
+ !Function::IsImplicitStaticClosureFunction(closure->function())) {
+ const char* message = OS::SCreate(
+ s->zone(),
+ "Illegal argument in isolate message : (object is a closure - %s)",
+ Function::Handle(closure->function()).ToCString());
+ s->IllegalObject(*object, message);
+ }
+
+ objects_.Add(closure);
+
+ s->Push(closure->function());
+ s->Push(closure->delayed_type_arguments());
+ }
+
+ void WriteNodes(MessageSerializer* s) {
+ intptr_t count = objects_.length();
+ s->WriteUnsigned(count);
+ for (intptr_t i = 0; i < count; i++) {
+ Closure* closure = objects_[i];
+ s->AssignRef(closure);
+ s->WriteRef(closure->function());
+ s->WriteRef(closure->delayed_type_arguments());
+ }
+ }
+
+ private:
+ GrowableArray<Closure*> objects_;
+};
+
+class ClosureMessageDeserializationCluster
+ : public MessageDeserializationCluster {
+ public:
+ explicit ClosureMessageDeserializationCluster(bool is_canonical)
+ : MessageDeserializationCluster("Closure", is_canonical) {}
+ ~ClosureMessageDeserializationCluster() {}
+
+ void ReadNodes(MessageDeserializer* d) {
+ const Context& null_context = Context::Handle(d->zone());
+ TypeArguments& delayed_type_arguments = TypeArguments::Handle(d->zone());
+ Function& func = Function::Handle(d->zone());
+ intptr_t count = d->ReadUnsigned();
+ for (intptr_t i = 0; i < count; i++) {
+ func ^= d->ReadRef();
+ ASSERT(func.is_static());
+ func = func.ImplicitClosureFunction();
+ delayed_type_arguments ^= d->ReadRef();
+ if (delayed_type_arguments.IsNull()) {
+ d->AssignRef(func.ImplicitStaticClosure());
+ } else {
+ // If delayed type arguments were provided, create and return new
+ // closure with those, otherwise return associated implicit static
+ // closure. Note that static closures can't have instantiator or
+ // function types since statics can't refer to class type arguments,
+ // don't have outer functions.
+ d->AssignRef(Closure::New(
+ /*instantiator_type_arguments=*/Object::null_type_arguments(),
+ /*function_type_arguments=*/Object::null_type_arguments(),
+ delayed_type_arguments, func, null_context, Heap::kOld));
+ }
+ }
+ }
+};
+
+class SmiMessageSerializationCluster : public MessageSerializationCluster {
+ public:
+ explicit SmiMessageSerializationCluster(Zone* zone)
+ : MessageSerializationCluster("Smi",
+ MessagePhase::kBeforeTypes,
+ kSmiCid,
+ true),
+ objects_(zone, 0) {}
+ ~SmiMessageSerializationCluster() {}
+
+ void Trace(MessageSerializer* s, Object* object) {
+ Smi* smi = static_cast<Smi*>(object);
+ objects_.Add(smi);
+ }
+
+ void WriteNodes(MessageSerializer* s) {
+ intptr_t count = objects_.length();
+ s->WriteUnsigned(count);
+ for (intptr_t i = 0; i < count; i++) {
+ Smi* smi = static_cast<Smi*>(objects_[i]);
+ s->AssignRef(smi);
+ s->Write<intptr_t>(smi->Value());
+ }
+ }
+
+ void TraceApi(ApiMessageSerializer* s, Dart_CObject* object) {
+ objects_.Add(reinterpret_cast<Smi*>(object));
+ }
+
+ void WriteNodesApi(ApiMessageSerializer* s) {
+ intptr_t count = objects_.length();
+ s->WriteUnsigned(count);
+ for (intptr_t i = 0; i < count; i++) {
+ Dart_CObject* smi = reinterpret_cast<Dart_CObject*>(objects_[i]);
+ s->AssignRef(smi);
+ intptr_t value = smi->type == Dart_CObject_kInt32 ? smi->value.as_int32
+ : smi->value.as_int64;
+ s->Write<intptr_t>(value);
+ }
+ }
+
+ private:
+ GrowableArray<Smi*> objects_;
+};
+
+class SmiMessageDeserializationCluster : public MessageDeserializationCluster {
+ public:
+ SmiMessageDeserializationCluster()
+ : MessageDeserializationCluster("Smi", true) {}
+ ~SmiMessageDeserializationCluster() {}
+
+ void ReadNodes(MessageDeserializer* d) {
+ intptr_t count = d->ReadUnsigned();
+ for (intptr_t i = 0; i < count; i++) {
+ d->AssignRef(Smi::New(d->Read<intptr_t>()));
+ }
+ }
+
+ void ReadNodesApi(ApiMessageDeserializer* d) {
+ intptr_t count = d->ReadUnsigned();
+ for (intptr_t i = 0; i < count; i++) {
+ intptr_t value = d->Read<intptr_t>();
+ Dart_CObject* smi;
+ if ((kMinInt32 <= value) && (value <= kMaxInt32)) {
+ smi = d->Allocate(Dart_CObject_kInt32);
+ smi->value.as_int32 = value;
+ } else {
+ smi = d->Allocate(Dart_CObject_kInt64);
+ smi->value.as_int64 = value;
+ }
+ d->AssignRef(smi);
+ }
+ }
+};
+
+class MintMessageSerializationCluster : public MessageSerializationCluster {
+ public:
+ explicit MintMessageSerializationCluster(Zone* zone, bool is_canonical)
+ : MessageSerializationCluster("Mint",
+ MessagePhase::kBeforeTypes,
+ kMintCid,
+ is_canonical),
+ objects_(zone, 0) {}
+ ~MintMessageSerializationCluster() {}
+
+ void Trace(MessageSerializer* s, Object* object) {
+ Mint* mint = static_cast<Mint*>(object);
+ objects_.Add(mint);
+ }
+
+ void WriteNodes(MessageSerializer* s) {
+ intptr_t count = objects_.length();
+ s->WriteUnsigned(count);
+ for (intptr_t i = 0; i < count; i++) {
+ Mint* mint = static_cast<Mint*>(objects_[i]);
+ s->AssignRef(mint);
+ s->Write<int64_t>(mint->value());
+ }
+ }
+
+ void TraceApi(ApiMessageSerializer* s, Dart_CObject* object) {
+ objects_.Add(reinterpret_cast<Mint*>(object));
+ }
+
+ void WriteNodesApi(ApiMessageSerializer* s) {
+ intptr_t count = objects_.length();
+ s->WriteUnsigned(count);
+ for (intptr_t i = 0; i < count; i++) {
+ Dart_CObject* mint = reinterpret_cast<Dart_CObject*>(objects_[i]);
+ s->AssignRef(mint);
+ int64_t value = mint->type == Dart_CObject_kInt32 ? mint->value.as_int32
+ : mint->value.as_int64;
+ s->Write<int64_t>(value);
+ }
+ }
+
+ private:
+ GrowableArray<Mint*> objects_;
+};
+
+class MintMessageDeserializationCluster : public MessageDeserializationCluster {
+ public:
+ explicit MintMessageDeserializationCluster(bool is_canonical)
+ : MessageDeserializationCluster("int", is_canonical) {}
+ ~MintMessageDeserializationCluster() {}
+
+ void ReadNodes(MessageDeserializer* d) {
+ intptr_t count = d->ReadUnsigned();
+ for (intptr_t i = 0; i < count; i++) {
+ int64_t value = d->Read<int64_t>();
+ d->AssignRef(is_canonical() ? Mint::NewCanonical(value)
+ : Mint::New(value));
+ }
+ }
+
+ void ReadNodesApi(ApiMessageDeserializer* d) {
+ intptr_t count = d->ReadUnsigned();
+ for (intptr_t i = 0; i < count; i++) {
+ int64_t value = d->Read<int64_t>();
+ Dart_CObject* mint;
+ if ((kMinInt32 <= value) && (value <= kMaxInt32)) {
+ mint = d->Allocate(Dart_CObject_kInt32);
+ mint->value.as_int32 = value;
+ } else {
+ mint = d->Allocate(Dart_CObject_kInt64);
+ mint->value.as_int64 = value;
+ }
+ d->AssignRef(mint);
+ }
+ }
+};
+
+class DoubleMessageSerializationCluster : public MessageSerializationCluster {
+ public:
+ explicit DoubleMessageSerializationCluster(Zone* zone, bool is_canonical)
+ : MessageSerializationCluster("double",
+ MessagePhase::kBeforeTypes,
+ kDoubleCid,
+ is_canonical),
+ objects_(zone, 0) {}
+
+ ~DoubleMessageSerializationCluster() {}
+
+ void Trace(MessageSerializer* s, Object* object) {
+ Double* dbl = static_cast<Double*>(object);
+ objects_.Add(dbl);
+ }
+
+ void WriteNodes(MessageSerializer* s) {
+ intptr_t count = objects_.length();
+ s->WriteUnsigned(count);
+ for (intptr_t i = 0; i < count; i++) {
+ Double* dbl = objects_[i];
+ s->AssignRef(dbl);
+ s->Write<double>(dbl->untag()->value_);
+ }
+ }
+
+ void TraceApi(ApiMessageSerializer* s, Dart_CObject* object) {
+ objects_.Add(reinterpret_cast<Double*>(object));
+ }
+
+ void WriteNodesApi(ApiMessageSerializer* s) {
+ intptr_t count = objects_.length();
+ s->WriteUnsigned(count);
+ for (intptr_t i = 0; i < count; i++) {
+ Dart_CObject* dbl = reinterpret_cast<Dart_CObject*>(objects_[i]);
+ s->AssignRef(dbl);
+ s->Write<double>(dbl->value.as_double);
+ }
+ }
+
+ private:
+ GrowableArray<Double*> objects_;
+};
+
+class DoubleMessageDeserializationCluster
+ : public MessageDeserializationCluster {
+ public:
+ explicit DoubleMessageDeserializationCluster(bool is_canonical)
+ : MessageDeserializationCluster("double", is_canonical) {}
+ ~DoubleMessageDeserializationCluster() {}
+
+ void ReadNodes(MessageDeserializer* d) {
+ intptr_t count = d->ReadUnsigned();
+ for (intptr_t i = 0; i < count; i++) {
+ double value = d->Read<double>();
+ d->AssignRef(is_canonical() ? Double::NewCanonical(value)
+ : Double::New(value));
+ }
+ }
+
+ void ReadNodesApi(ApiMessageDeserializer* d) {
+ intptr_t count = d->ReadUnsigned();
+ for (intptr_t i = 0; i < count; i++) {
+ Dart_CObject* dbl = d->Allocate(Dart_CObject_kDouble);
+ dbl->value.as_double = d->Read<double>();
+ d->AssignRef(dbl);
+ }
+ }
+};
+
+class GrowableObjectArrayMessageSerializationCluster
+ : public MessageSerializationCluster {
+ public:
+ GrowableObjectArrayMessageSerializationCluster()
+ : MessageSerializationCluster("GrowableObjectArray",
+ MessagePhase::kNonCanonicalInstances,
+ kGrowableObjectArrayCid) {}
+ ~GrowableObjectArrayMessageSerializationCluster() {}
+
+ void Trace(MessageSerializer* s, Object* object) {
+ GrowableObjectArray* array = static_cast<GrowableObjectArray*>(object);
+ objects_.Add(array);
+
+ s->Push(array->GetTypeArguments());
+ for (intptr_t i = 0, n = array->Length(); i < n; i++) {
+ s->Push(array->At(i));
+ }
+ }
+
+ void WriteNodes(MessageSerializer* s) {
+ intptr_t count = objects_.length();
+ s->WriteUnsigned(count);
+ for (intptr_t i = 0; i < count; i++) {
+ GrowableObjectArray* array = objects_[i];
+ s->WriteUnsigned(array->Length());
+ s->AssignRef(array);
+ }
+ }
+
+ void WriteEdges(MessageSerializer* s) {
+ intptr_t count = objects_.length();
+ for (intptr_t i = 0; i < count; i++) {
+ GrowableObjectArray* array = objects_[i];
+ s->WriteRef(array->GetTypeArguments());
+ for (intptr_t i = 0, n = array->Length(); i < n; i++) {
+ s->WriteRef(array->At(i));
+ }
+ }
+ }
+
+ private:
+ GrowableArray<GrowableObjectArray*> objects_;
+};
+
+class GrowableObjectArrayMessageDeserializationCluster
+ : public MessageDeserializationCluster {
+ public:
+ GrowableObjectArrayMessageDeserializationCluster()
+ : MessageDeserializationCluster("GrowableObjectArray") {}
+ ~GrowableObjectArrayMessageDeserializationCluster() {}
+
+ void ReadNodes(MessageDeserializer* d) {
+ intptr_t count = d->ReadUnsigned();
+ GrowableObjectArray& array = GrowableObjectArray::Handle(d->zone());
+ for (intptr_t i = 0; i < count; i++) {
+ intptr_t length = d->ReadUnsigned();
+ array = GrowableObjectArray::New(length); // Here length is capacity.
+ array.SetLength(length);
+ d->AssignRef(array.ptr());
+ }
+ }
+
+ void ReadEdges(MessageDeserializer* d) {
+ GrowableObjectArray& array = GrowableObjectArray::Handle(d->zone());
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ array ^= d->Ref(id);
+ array.untag()->set_type_arguments(
+ static_cast<TypeArgumentsPtr>(d->ReadRef()));
+ for (intptr_t i = 0, n = array.Length(); i < n; i++) {
+ array.untag()->data()->untag()->set_element(i, d->ReadRef());
+ }
+ }
+ }
+
+ ObjectPtr PostLoad(MessageDeserializer* d) {
+ ASSERT(!is_canonical());
+ return nullptr;
+ }
+
+ void ReadNodesApi(ApiMessageDeserializer* d) {
+ intptr_t count = d->ReadUnsigned();
+ for (intptr_t i = 0; i < count; i++) {
+ Dart_CObject* array = d->Allocate(Dart_CObject_kArray);
+ intptr_t length = d->ReadUnsigned();
+ array->value.as_array.length = length;
+ if (length > 0) {
+ array->value.as_array.values = d->zone()->Alloc<Dart_CObject*>(length);
+ } else {
+ ASSERT(length == 0);
+ array->value.as_array.values = NULL;
+ }
+ d->AssignRef(array);
+ }
+ }
+
+ void ReadEdgesApi(ApiMessageDeserializer* d) {
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ Dart_CObject* array = d->Ref(id);
+ intptr_t length = array->value.as_array.length;
+ d->ReadRef(); // type_arguments
+ for (intptr_t i = 0; i < length; i++) {
+ array->value.as_array.values[i] = d->ReadRef();
+ }
+ }
+ }
+};
+
+class TypedDataMessageSerializationCluster
+ : public MessageSerializationCluster {
+ public:
+ explicit TypedDataMessageSerializationCluster(Zone* zone, intptr_t cid)
+ : MessageSerializationCluster("TypedData",
+ MessagePhase::kNonCanonicalInstances,
+ cid),
+ objects_(zone, 0) {}
+ ~TypedDataMessageSerializationCluster() {}
+
+ void Trace(MessageSerializer* s, Object* object) {
+ TypedData* data = static_cast<TypedData*>(object);
+ objects_.Add(data);
+ }
+
+ void WriteNodes(MessageSerializer* s) {
+ intptr_t element_size = TypedData::ElementSizeInBytes(cid_);
+ intptr_t count = objects_.length();
+ s->WriteUnsigned(count);
+ for (intptr_t i = 0; i < count; i++) {
+ TypedData* data = objects_[i];
+ s->AssignRef(data);
+ intptr_t length = data->Length();
+ s->WriteUnsigned(length);
+ NoSafepointScope no_safepoint;
+ uint8_t* cdata = reinterpret_cast<uint8_t*>(data->untag()->data());
+ s->WriteBytes(cdata, length * element_size);
+ }
+ }
+
+ void TraceApi(ApiMessageSerializer* s, Dart_CObject* object) {
+ objects_.Add(reinterpret_cast<TypedData*>(object));
+ }
+
+ void WriteNodesApi(ApiMessageSerializer* s) {
+ intptr_t element_size = TypedData::ElementSizeInBytes(cid_);
+ intptr_t count = objects_.length();
+ s->WriteUnsigned(count);
+ for (intptr_t i = 0; i < count; i++) {
+ Dart_CObject* data = reinterpret_cast<Dart_CObject*>(objects_[i]);
+ s->AssignRef(data);
+ intptr_t length = data->value.as_external_typed_data.length;
+ s->WriteUnsigned(length);
+ uint8_t* cdata =
+ reinterpret_cast<uint8_t*>(data->value.as_typed_data.values);
+ s->WriteBytes(cdata, length * element_size);
+ }
+ }
+
+ private:
+ GrowableArray<TypedData*> objects_;
+};
+
+class TypedDataMessageDeserializationCluster
+ : public MessageDeserializationCluster {
+ public:
+ explicit TypedDataMessageDeserializationCluster(intptr_t cid)
+ : MessageDeserializationCluster("TypedData"), cid_(cid) {}
+ ~TypedDataMessageDeserializationCluster() {}
+
+ void ReadNodes(MessageDeserializer* d) {
+ intptr_t element_size = TypedData::ElementSizeInBytes(cid_);
+ intptr_t count = d->ReadUnsigned();
+ TypedData& data = TypedData::Handle(d->zone());
+ for (intptr_t i = 0; i < count; i++) {
+ intptr_t length = d->ReadUnsigned();
+ data = TypedData::New(cid_, length);
+ d->AssignRef(data.ptr());
+ const intptr_t length_in_bytes = length * element_size;
+ NoSafepointScope no_safepoint;
+ uint8_t* cdata = reinterpret_cast<uint8_t*>(data.untag()->data());
+ d->ReadBytes(cdata, length_in_bytes);
+ }
+ }
+
+ void ReadNodesApi(ApiMessageDeserializer* d) {
+ Dart_TypedData_Type type;
+ switch (cid_) {
+ case kTypedDataInt8ArrayCid:
+ type = Dart_TypedData_kInt8;
+ break;
+ case kTypedDataUint8ArrayCid:
+ type = Dart_TypedData_kUint8;
+ break;
+ case kTypedDataUint8ClampedArrayCid:
+ type = Dart_TypedData_kUint8Clamped;
+ break;
+ case kTypedDataInt16ArrayCid:
+ type = Dart_TypedData_kInt16;
+ break;
+ case kTypedDataUint16ArrayCid:
+ type = Dart_TypedData_kUint16;
+ break;
+ case kTypedDataInt32ArrayCid:
+ type = Dart_TypedData_kInt32;
+ break;
+ case kTypedDataUint32ArrayCid:
+ type = Dart_TypedData_kUint32;
+ break;
+ case kTypedDataInt64ArrayCid:
+ type = Dart_TypedData_kInt64;
+ break;
+ case kTypedDataUint64ArrayCid:
+ type = Dart_TypedData_kUint64;
+ break;
+ case kTypedDataFloat32ArrayCid:
+ type = Dart_TypedData_kFloat32;
+ break;
+ case kTypedDataFloat64ArrayCid:
+ type = Dart_TypedData_kFloat64;
+ break;
+ case kTypedDataInt32x4ArrayCid:
+ type = Dart_TypedData_kInt32x4;
+ break;
+ case kTypedDataFloat32x4ArrayCid:
+ type = Dart_TypedData_kFloat32x4;
+ break;
+ case kTypedDataFloat64x2ArrayCid:
+ type = Dart_TypedData_kFloat64x2;
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ intptr_t element_size = TypedData::ElementSizeInBytes(cid_);
+ intptr_t count = d->ReadUnsigned();
+ for (intptr_t i = 0; i < count; i++) {
+ Dart_CObject* data = d->Allocate(Dart_CObject_kTypedData);
+ intptr_t length = d->ReadUnsigned();
+ data->value.as_typed_data.type = type;
+ data->value.as_typed_data.length = length * element_size;
+ if (length == 0) {
+ data->value.as_typed_data.values = NULL;
+ } else {
+ data->value.as_typed_data.values =
+ const_cast<uint8_t*>(d->CurrentBufferAddress());
+ d->Advance(length * element_size);
+ }
+ d->AssignRef(data);
+ }
+ }
+
+ private:
+ const intptr_t cid_;
+};
+
+// This function's name can appear in Observatory.
+static void IsolateMessageTypedDataFinalizer(void* isolate_callback_data,
+ void* buffer) {
+ free(buffer);
+}
+
+class ExternalTypedDataMessageSerializationCluster
+ : public MessageSerializationCluster {
+ public:
+ explicit ExternalTypedDataMessageSerializationCluster(Zone* zone,
+ intptr_t cid)
+ : MessageSerializationCluster("ExternalTypedData",
+ MessagePhase::kNonCanonicalInstances,
+ cid),
+ objects_(zone, 0) {}
+ ~ExternalTypedDataMessageSerializationCluster() {}
+
+ void Trace(MessageSerializer* s, Object* object) {
+ ExternalTypedData* data = static_cast<ExternalTypedData*>(object);
+ objects_.Add(data);
+ }
+
+ void WriteNodes(MessageSerializer* s) {
+ intptr_t element_size = ExternalTypedData::ElementSizeInBytes(cid_);
+
+ intptr_t count = objects_.length();
+ s->WriteUnsigned(count);
+ for (intptr_t i = 0; i < count; i++) {
+ ExternalTypedData* data = objects_[i];
+ s->AssignRef(data);
+ intptr_t length = Smi::Value(data->untag()->length_);
+ s->WriteUnsigned(length);
+
+ intptr_t length_in_bytes = length * element_size;
+ void* passed_data = malloc(length_in_bytes);
+ memmove(passed_data, data->untag()->data_, length_in_bytes);
+ s->finalizable_data()->Put(length_in_bytes,
+ passed_data, // data
+ passed_data, // peer,
+ IsolateMessageTypedDataFinalizer);
+ }
+ }
+
+ void TraceApi(ApiMessageSerializer* s, Dart_CObject* object) {
+ objects_.Add(reinterpret_cast<ExternalTypedData*>(object));
+ }
+
+ void WriteNodesApi(ApiMessageSerializer* s) {
+ intptr_t element_size = ExternalTypedData::ElementSizeInBytes(cid_);
+
+ intptr_t count = objects_.length();
+ s->WriteUnsigned(count);
+ for (intptr_t i = 0; i < count; i++) {
+ Dart_CObject* data = reinterpret_cast<Dart_CObject*>(objects_[i]);
+ s->AssignRef(data);
+
+ intptr_t length = data->value.as_external_typed_data.length;
+ s->WriteUnsigned(length);
+
+ s->finalizable_data()->Put(length * element_size,
+ data->value.as_external_typed_data.data,
+ data->value.as_external_typed_data.peer,
+ data->value.as_external_typed_data.callback);
+ }
+ }
+
+ private:
+ GrowableArray<ExternalTypedData*> objects_;
+};
+
+class ExternalTypedDataMessageDeserializationCluster
+ : public MessageDeserializationCluster {
+ public:
+ explicit ExternalTypedDataMessageDeserializationCluster(intptr_t cid)
+ : MessageDeserializationCluster("ExternalTypedData"), cid_(cid) {}
+ ~ExternalTypedDataMessageDeserializationCluster() {}
+
+ void ReadNodes(MessageDeserializer* d) {
+ intptr_t element_size = ExternalTypedData::ElementSizeInBytes(cid_);
+ intptr_t count = d->ReadUnsigned();
+ ExternalTypedData& data = ExternalTypedData::Handle(d->zone());
+ for (intptr_t i = 0; i < count; i++) {
+ intptr_t length = d->ReadUnsigned();
+ FinalizableData finalizable_data = d->finalizable_data()->Take();
+ data = ExternalTypedData::New(
+ cid_, reinterpret_cast<uint8_t*>(finalizable_data.data), length);
+ intptr_t external_size = length * element_size;
+ data.AddFinalizer(finalizable_data.peer, finalizable_data.callback,
+ external_size);
+ d->AssignRef(data.ptr());
+ }
+ }
+
+ void ReadNodesApi(ApiMessageDeserializer* d) {
+ intptr_t element_size = ExternalTypedData::ElementSizeInBytes(cid_);
+ Dart_TypedData_Type type;
+ switch (cid_) {
+ case kExternalTypedDataInt8ArrayCid:
+ type = Dart_TypedData_kInt8;
+ break;
+ case kExternalTypedDataUint8ArrayCid:
+ type = Dart_TypedData_kUint8;
+ break;
+ case kExternalTypedDataUint8ClampedArrayCid:
+ type = Dart_TypedData_kUint8Clamped;
+ break;
+ case kExternalTypedDataInt16ArrayCid:
+ type = Dart_TypedData_kInt16;
+ break;
+ case kExternalTypedDataUint16ArrayCid:
+ type = Dart_TypedData_kUint16;
+ break;
+ case kExternalTypedDataInt32ArrayCid:
+ type = Dart_TypedData_kInt32;
+ break;
+ case kExternalTypedDataUint32ArrayCid:
+ type = Dart_TypedData_kUint32;
+ break;
+ case kExternalTypedDataInt64ArrayCid:
+ type = Dart_TypedData_kInt64;
+ break;
+ case kExternalTypedDataUint64ArrayCid:
+ type = Dart_TypedData_kUint64;
+ break;
+ case kExternalTypedDataFloat32ArrayCid:
+ type = Dart_TypedData_kFloat32;
+ break;
+ case kExternalTypedDataFloat64ArrayCid:
+ type = Dart_TypedData_kFloat64;
+ break;
+ case kExternalTypedDataInt32x4ArrayCid:
+ type = Dart_TypedData_kInt32x4;
+ break;
+ case kExternalTypedDataFloat32x4ArrayCid:
+ type = Dart_TypedData_kFloat32x4;
+ break;
+ case kExternalTypedDataFloat64x2ArrayCid:
+ type = Dart_TypedData_kFloat64x2;
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ intptr_t count = d->ReadUnsigned();
+ for (intptr_t i = 0; i < count; i++) {
+ Dart_CObject* data = d->Allocate(Dart_CObject_kTypedData);
+ intptr_t length = d->ReadUnsigned();
+ FinalizableData finalizable_data = d->finalizable_data()->Get();
+ data->value.as_typed_data.type = type;
+ data->value.as_typed_data.length = length * element_size;
+ data->value.as_typed_data.values =
+ reinterpret_cast<uint8_t*>(finalizable_data.data);
+ d->AssignRef(data);
+ }
+ }
+
+ private:
+ const intptr_t cid_;
+};
+
+class TypedDataViewMessageSerializationCluster
+ : public MessageSerializationCluster {
+ public:
+ explicit TypedDataViewMessageSerializationCluster(Zone* zone, intptr_t cid)
+ : MessageSerializationCluster("TypedDataView",
+ MessagePhase::kNonCanonicalInstances,
+ cid),
+ objects_(zone, 0) {}
+ ~TypedDataViewMessageSerializationCluster() {}
+
+ void Trace(MessageSerializer* s, Object* object) {
+ TypedDataView* view = static_cast<TypedDataView*>(object);
+ objects_.Add(view);
+
+ s->Push(view->untag()->length());
+ s->Push(view->untag()->typed_data());
+ s->Push(view->untag()->offset_in_bytes());
+ }
+
+ void WriteNodes(MessageSerializer* s) {
+ intptr_t count = objects_.length();
+ s->WriteUnsigned(count);
+ for (intptr_t i = 0; i < count; i++) {
+ TypedDataView* view = objects_[i];
+ s->AssignRef(view);
+ }
+ }
+
+ void WriteEdges(MessageSerializer* s) {
+ intptr_t count = objects_.length();
+ for (intptr_t i = 0; i < count; i++) {
+ TypedDataView* view = objects_[i];
+ s->WriteRef(view->untag()->length());
+ s->WriteRef(view->untag()->typed_data());
+ s->WriteRef(view->untag()->offset_in_bytes());
+ }
+ }
+
+ private:
+ GrowableArray<TypedDataView*> objects_;
+};
+
+class TypedDataViewMessageDeserializationCluster
+ : public MessageDeserializationCluster {
+ public:
+ explicit TypedDataViewMessageDeserializationCluster(intptr_t cid)
+ : MessageDeserializationCluster("TypedDataView"), cid_(cid) {}
+ ~TypedDataViewMessageDeserializationCluster() {}
+
+ void ReadNodes(MessageDeserializer* d) {
+ intptr_t count = d->ReadUnsigned();
+ for (intptr_t i = 0; i < count; i++) {
+ d->AssignRef(TypedDataView::New(cid_));
+ }
+ }
+
+ void ReadEdges(MessageDeserializer* d) {
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ TypedDataViewPtr view = static_cast<TypedDataViewPtr>(d->Ref(id));
+ view->untag()->set_length(static_cast<SmiPtr>(d->ReadRef()));
+ view->untag()->set_typed_data(
+ static_cast<TypedDataBasePtr>(d->ReadRef()));
+ view->untag()->set_offset_in_bytes(static_cast<SmiPtr>(d->ReadRef()));
+ }
+ }
+
+ ObjectPtr PostLoad(MessageDeserializer* d) {
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ TypedDataViewPtr view = static_cast<TypedDataViewPtr>(d->Ref(id));
+ view->untag()->RecomputeDataField();
+ }
+ return nullptr;
+ }
+
+ struct Dart_CTypedDataView : public Dart_CObject {
+ Dart_CObject* length;
+ Dart_CObject* typed_data;
+ Dart_CObject* offset_in_bytes;
+ };
+
+ void ReadNodesApi(ApiMessageDeserializer* d) {
+ intptr_t count = d->ReadUnsigned();
+ for (intptr_t i = 0; i < count; i++) {
+ Dart_CTypedDataView* view = d->zone()->Alloc<Dart_CTypedDataView>(1);
+ d->AssignRef(view);
+ }
+ }
+
+ void ReadEdgesApi(ApiMessageDeserializer* d) {
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ Dart_CTypedDataView* view = static_cast<Dart_CTypedDataView*>(d->Ref(id));
+ view->length = d->ReadRef();
+ view->typed_data = d->ReadRef();
+ view->offset_in_bytes = d->ReadRef();
+ }
+ }
+
+ void PostLoadApi(ApiMessageDeserializer* d) {
+ intptr_t element_size = TypedDataView::ElementSizeInBytes(cid_);
+ Dart_TypedData_Type type;
+ switch (cid_) {
+ case kTypedDataInt8ArrayViewCid:
+ type = Dart_TypedData_kInt8;
+ break;
+ case kTypedDataUint8ArrayViewCid:
+ type = Dart_TypedData_kUint8;
+ break;
+ case kTypedDataUint8ClampedArrayViewCid:
+ type = Dart_TypedData_kUint8Clamped;
+ break;
+ case kTypedDataInt16ArrayViewCid:
+ type = Dart_TypedData_kInt16;
+ break;
+ case kTypedDataUint16ArrayViewCid:
+ type = Dart_TypedData_kUint16;
+ break;
+ case kTypedDataInt32ArrayViewCid:
+ type = Dart_TypedData_kInt32;
+ break;
+ case kTypedDataUint32ArrayViewCid:
+ type = Dart_TypedData_kUint32;
+ break;
+ case kTypedDataInt64ArrayViewCid:
+ type = Dart_TypedData_kInt64;
+ break;
+ case kTypedDataUint64ArrayViewCid:
+ type = Dart_TypedData_kUint64;
+ break;
+ case kTypedDataFloat32ArrayViewCid:
+ type = Dart_TypedData_kFloat32;
+ break;
+ case kTypedDataFloat64ArrayViewCid:
+ type = Dart_TypedData_kFloat64;
+ break;
+ case kTypedDataInt32x4ArrayViewCid:
+ type = Dart_TypedData_kInt32x4;
+ break;
+ case kTypedDataFloat32x4ArrayViewCid:
+ type = Dart_TypedData_kFloat32x4;
+ break;
+ case kTypedDataFloat64x2ArrayViewCid:
+ type = Dart_TypedData_kFloat64x2;
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ Dart_CTypedDataView* view = static_cast<Dart_CTypedDataView*>(d->Ref(id));
+ if (view->typed_data->type == Dart_CObject_kTypedData) {
+ view->type = Dart_CObject_kTypedData;
+ view->value.as_typed_data.type = type;
+ // view->typed_data->value.as_typed_data.type;
+ view->value.as_typed_data.length =
+ view->length->value.as_int32 * element_size;
+ view->value.as_typed_data.values =
+ view->typed_data->value.as_typed_data.values +
+ view->offset_in_bytes->value.as_int32;
+ } else if (view->typed_data->type == Dart_CObject_kExternalTypedData) {
+ UNREACHABLE(); ///???
+ view->type = Dart_CObject_kTypedData;
+ view->value.as_typed_data.type = type;
+ // view->typed_data->value.as_external_typed_data.type;
+ view->value.as_typed_data.length =
+ view->length->value.as_int32 * element_size;
+ view->value.as_typed_data.values =
+ view->typed_data->value.as_external_typed_data.data +
+ view->offset_in_bytes->value.as_int32;
+ } else {
+ UNREACHABLE();
+ }
+ }
+ }
+
+ private:
+ const intptr_t cid_;
+};
+
+class TransferableTypedDataMessageSerializationCluster
+ : public MessageSerializationCluster {
+ public:
+ TransferableTypedDataMessageSerializationCluster()
+ : MessageSerializationCluster("TransferableTypedData",
+ MessagePhase::kNonCanonicalInstances,
+ kTransferableTypedDataCid) {}
+ ~TransferableTypedDataMessageSerializationCluster() {}
+
+ void Trace(MessageSerializer* s, Object* object) {
+ TransferableTypedData* transferable =
+ static_cast<TransferableTypedData*>(object);
+ objects_.Add(transferable);
+
+ void* peer = s->thread()->heap()->GetPeer(transferable->ptr());
+ // Assume that object's Peer is only used to track transferrability state.
+ ASSERT(peer != nullptr);
+ TransferableTypedDataPeer* tpeer =
+ reinterpret_cast<TransferableTypedDataPeer*>(peer);
+ if (tpeer->data() == nullptr) {
+ s->IllegalObject(
+ *object,
+ "Illegal argument in isolate message"
+ " : (TransferableTypedData has been transferred already)");
+ }
+ }
+
+ void WriteNodes(MessageSerializer* s) {
+ intptr_t count = objects_.length();
+ s->WriteUnsigned(count);
+ for (intptr_t i = 0; i < count; i++) {
+ TransferableTypedData* transferable = objects_[i];
+ s->AssignRef(transferable);
+
+ void* peer = s->thread()->heap()->GetPeer(transferable->ptr());
+ // Assume that object's Peer is only used to track transferrability state.
+ ASSERT(peer != nullptr);
+ TransferableTypedDataPeer* tpeer =
+ reinterpret_cast<TransferableTypedDataPeer*>(peer);
+ intptr_t length = tpeer->length(); // In bytes.
+ void* data = tpeer->data();
+ ASSERT(data != nullptr);
+ s->WriteUnsigned(length);
+ s->finalizable_data()->Put(
+ length, data, tpeer,
+ // Finalizer does nothing - in case of failure to serialize,
+ // [data] remains wrapped in sender's [TransferableTypedData].
+ [](void* data, void* peer) {},
+ // This is invoked on successful serialization of the message
+ [](void* data, void* peer) {
+ TransferableTypedDataPeer* ttpeer =
+ reinterpret_cast<TransferableTypedDataPeer*>(peer);
+ ttpeer->handle()->EnsureFreedExternal(IsolateGroup::Current());
+ ttpeer->ClearData();
+ });
+ }
+ }
+
+ private:
+ GrowableArray<TransferableTypedData*> objects_;
+};
+
+class TransferableTypedDataMessageDeserializationCluster
+ : public MessageDeserializationCluster {
+ public:
+ TransferableTypedDataMessageDeserializationCluster()
+ : MessageDeserializationCluster("TransferableTypedData") {}
+ ~TransferableTypedDataMessageDeserializationCluster() {}
+
+ void ReadNodes(MessageDeserializer* d) {
+ intptr_t count = d->ReadUnsigned();
+ for (intptr_t i = 0; i < count; i++) {
+ intptr_t length = d->ReadUnsigned();
+ const FinalizableData finalizable_data = d->finalizable_data()->Take();
+ d->AssignRef(TransferableTypedData::New(
+ reinterpret_cast<uint8_t*>(finalizable_data.data), length));
+ }
+ }
+};
+
+class RegExpMessageSerializationCluster : public MessageSerializationCluster {
+ public:
+ RegExpMessageSerializationCluster()
+ : MessageSerializationCluster("RegExp",
+ MessagePhase::kNonCanonicalInstances,
+ kRegExpCid) {}
+ ~RegExpMessageSerializationCluster() {}
+
+ void Trace(MessageSerializer* s, Object* object) {
+ RegExp* regexp = static_cast<RegExp*>(object);
+ objects_.Add(regexp);
+
+ s->Push(regexp->capture_name_map());
+ s->Push(regexp->pattern());
+ }
+
+ void WriteNodes(MessageSerializer* s) {
+ intptr_t count = objects_.length();
+ s->WriteUnsigned(count);
+ for (intptr_t i = 0; i < count; i++) {
+ RegExp* regexp = objects_[i];
+ s->AssignRef(regexp);
+ s->WriteRef(regexp->capture_name_map());
+ s->WriteRef(regexp->pattern());
+ s->Write<int32_t>(regexp->num_bracket_expressions());
+ s->Write<int32_t>(regexp->num_registers(true));
+ s->Write<int32_t>(regexp->num_registers(false));
+ s->Write<int>(regexp->flags().value());
+ }
+ }
+
+ private:
+ GrowableArray<RegExp*> objects_;
+};
+
+class RegExpMessageDeserializationCluster
+ : public MessageDeserializationCluster {
+ public:
+ RegExpMessageDeserializationCluster()
+ : MessageDeserializationCluster("RegExp") {}
+ ~RegExpMessageDeserializationCluster() {}
+
+ void ReadNodes(MessageDeserializer* d) {
+ RegExp& regexp = RegExp::Handle(d->zone());
+ intptr_t count = d->ReadUnsigned();
+ for (intptr_t i = 0; i < count; i++) {
+ regexp = RegExp::New(d->zone());
+ d->AssignRef(regexp.ptr());
+ regexp.untag()->set_capture_name_map(static_cast<ArrayPtr>(d->ReadRef()));
+ regexp.untag()->set_pattern(static_cast<StringPtr>(d->ReadRef()));
+ regexp.set_num_bracket_expressions(d->Read<int32_t>());
+ regexp.set_num_registers(true, d->Read<int32_t>());
+ regexp.set_num_registers(false, d->Read<int32_t>());
+ regexp.set_flags(RegExpFlags(d->Read<int>()));
+ }
+ }
+};
+
+class SendPortMessageSerializationCluster : public MessageSerializationCluster {
+ public:
+ explicit SendPortMessageSerializationCluster(Zone* zone)
+ : MessageSerializationCluster("SendPort",
+ MessagePhase::kNonCanonicalInstances,
+ kSendPortCid),
+ objects_(zone, 0) {}
+ ~SendPortMessageSerializationCluster() {}
+
+ void Trace(MessageSerializer* s, Object* object) {
+ SendPort* port = static_cast<SendPort*>(object);
+ objects_.Add(port);
+ }
+
+ void WriteNodes(MessageSerializer* s) {
+ intptr_t count = objects_.length();
+ s->WriteUnsigned(count);
+ for (intptr_t i = 0; i < count; i++) {
+ SendPort* port = objects_[i];
+ s->AssignRef(port);
+ s->Write<Dart_Port>(port->untag()->id_);
+ s->Write<Dart_Port>(port->untag()->origin_id_);
+ }
+ }
+
+ void TraceApi(ApiMessageSerializer* s, Dart_CObject* object) {
+ objects_.Add(reinterpret_cast<SendPort*>(object));
+ }
+
+ void WriteNodesApi(ApiMessageSerializer* s) {
+ intptr_t count = objects_.length();
+ s->WriteUnsigned(count);
+ for (intptr_t i = 0; i < count; i++) {
+ Dart_CObject* port = reinterpret_cast<Dart_CObject*>(objects_[i]);
+ s->AssignRef(port);
+ s->Write<Dart_Port>(port->value.as_send_port.id);
+ s->Write<Dart_Port>(port->value.as_send_port.origin_id);
+ }
+ }
+
+ private:
+ GrowableArray<SendPort*> objects_;
+};
+
+class SendPortMessageDeserializationCluster
+ : public MessageDeserializationCluster {
+ public:
+ SendPortMessageDeserializationCluster()
+ : MessageDeserializationCluster("SendPort") {}
+ ~SendPortMessageDeserializationCluster() {}
+
+ void ReadNodes(MessageDeserializer* d) {
+ intptr_t count = d->ReadUnsigned();
+ for (intptr_t i = 0; i < count; i++) {
+ Dart_Port id = d->Read<Dart_Port>();
+ Dart_Port origin_id = d->Read<Dart_Port>();
+ d->AssignRef(SendPort::New(id, origin_id));
+ }
+ }
+
+ void ReadNodesApi(ApiMessageDeserializer* d) {
+ intptr_t count = d->ReadUnsigned();
+ for (intptr_t i = 0; i < count; i++) {
+ Dart_CObject* port = d->Allocate(Dart_CObject_kSendPort);
+ port->value.as_send_port.id = d->Read<Dart_Port>();
+ port->value.as_send_port.origin_id = d->Read<Dart_Port>();
+ d->AssignRef(port);
+ }
+ }
+};
+
+class CapabilityMessageSerializationCluster
+ : public MessageSerializationCluster {
+ public:
+ explicit CapabilityMessageSerializationCluster(Zone* zone)
+ : MessageSerializationCluster("Capability",
+ MessagePhase::kNonCanonicalInstances,
+ kCapabilityCid),
+ objects_(zone, 0) {}
+ ~CapabilityMessageSerializationCluster() {}
+
+ void Trace(MessageSerializer* s, Object* object) {
+ Capability* cap = static_cast<Capability*>(object);
+ objects_.Add(cap);
+ }
+
+ void WriteNodes(MessageSerializer* s) {
+ intptr_t count = objects_.length();
+ s->WriteUnsigned(count);
+ for (intptr_t i = 0; i < count; i++) {
+ Capability* cap = objects_[i];
+ s->AssignRef(cap);
+ s->Write<uint64_t>(cap->untag()->id_);
+ }
+ }
+
+ void TraceApi(ApiMessageSerializer* s, Dart_CObject* object) {
+ objects_.Add(reinterpret_cast<Capability*>(object));
+ }
+
+ void WriteNodesApi(ApiMessageSerializer* s) {
+ intptr_t count = objects_.length();
+ s->WriteUnsigned(count);
+ for (intptr_t i = 0; i < count; i++) {
+ Dart_CObject* cap = reinterpret_cast<Dart_CObject*>(objects_[i]);
+ s->AssignRef(cap);
+ s->Write<Dart_Port>(cap->value.as_capability.id);
+ }
+ }
+
+ private:
+ GrowableArray<Capability*> objects_;
+};
+
+class CapabilityMessageDeserializationCluster
+ : public MessageDeserializationCluster {
+ public:
+ CapabilityMessageDeserializationCluster()
+ : MessageDeserializationCluster("Capability") {}
+ ~CapabilityMessageDeserializationCluster() {}
+
+ void ReadNodes(MessageDeserializer* d) {
+ intptr_t count = d->ReadUnsigned();
+ for (intptr_t i = 0; i < count; i++) {
+ uint64_t id = d->Read<uint64_t>();
+ d->AssignRef(Capability::New(id));
+ }
+ }
+
+ void ReadNodesApi(ApiMessageDeserializer* d) {
+ intptr_t count = d->ReadUnsigned();
+ for (intptr_t i = 0; i < count; i++) {
+ Dart_CObject* cap = d->Allocate(Dart_CObject_kCapability);
+ cap->value.as_capability.id = d->Read<uint64_t>();
+ d->AssignRef(cap);
+ }
+ }
+};
+
+class WeakPropertyMessageSerializationCluster
+ : public MessageSerializationCluster {
+ public:
+ WeakPropertyMessageSerializationCluster()
+ : MessageSerializationCluster("WeakProperty",
+ MessagePhase::kNonCanonicalInstances,
+ kWeakPropertyCid) {}
+ ~WeakPropertyMessageSerializationCluster() {}
+
+ void Trace(MessageSerializer* s, Object* object) {
+ WeakProperty* property = static_cast<WeakProperty*>(object);
+ objects_.Add(property);
+ }
+
+ void RetraceEphemerons(MessageSerializer* s) {
+ for (intptr_t i = 0; i < objects_.length(); i++) {
+ WeakProperty* property = objects_[i];
+ if (s->HasRef(property->untag()->key())) {
+ s->Push(property->untag()->value());
+ }
+ }
+ }
+
+ void WriteNodes(MessageSerializer* s) {
+ intptr_t count = objects_.length();
+ s->WriteUnsigned(count);
+ for (intptr_t i = 0; i < count; i++) {
+ WeakProperty* property = objects_[i];
+ s->AssignRef(property);
+ }
+ }
+
+ void WriteEdges(MessageSerializer* s) {
+ intptr_t count = objects_.length();
+ for (intptr_t i = 0; i < count; i++) {
+ WeakProperty* property = objects_[i];
+ if (s->HasRef(property->untag()->key())) {
+ s->WriteRef(property->untag()->key());
+ s->WriteRef(property->untag()->value());
+ } else {
+ s->WriteRef(Object::null());
+ s->WriteRef(Object::null());
+ }
+ }
+ }
+
+ private:
+ GrowableArray<WeakProperty*> objects_;
+};
+
+class WeakPropertyMessageDeserializationCluster
+ : public MessageDeserializationCluster {
+ public:
+ WeakPropertyMessageDeserializationCluster()
+ : MessageDeserializationCluster("WeakProperty") {}
+ ~WeakPropertyMessageDeserializationCluster() {}
+
+ void ReadNodes(MessageDeserializer* d) {
+ intptr_t count = d->ReadUnsigned();
+ for (intptr_t i = 0; i < count; i++) {
+ d->AssignRef(WeakProperty::New());
+ }
+ }
+
+ void ReadEdges(MessageDeserializer* d) {
+ ASSERT(!is_canonical()); // Never canonical.
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ WeakPropertyPtr property = static_cast<WeakPropertyPtr>(d->Ref(id));
+ property->untag()->set_key(d->ReadRef());
+ property->untag()->set_value(d->ReadRef());
+ }
+ }
+};
+
+class LinkedHashMapMessageSerializationCluster
+ : public MessageSerializationCluster {
+ public:
+ LinkedHashMapMessageSerializationCluster()
+ : MessageSerializationCluster("LinkedHashMap",
+ MessagePhase::kNonCanonicalInstances,
+ kLinkedHashMapCid) {}
+ ~LinkedHashMapMessageSerializationCluster() {}
+
+ void Trace(MessageSerializer* s, Object* object) {
+ LinkedHashMap* map = static_cast<LinkedHashMap*>(object);
+ objects_.Add(map);
+
+ s->Push(map->untag()->type_arguments());
+ s->Push(map->untag()->data());
+ s->Push(map->untag()->used_data());
+ }
+
+ void WriteNodes(MessageSerializer* s) {
+ intptr_t count = objects_.length();
+ s->WriteUnsigned(count);
+ for (intptr_t i = 0; i < count; i++) {
+ LinkedHashMap* map = objects_[i];
+ s->AssignRef(map);
+ }
+ }
+
+ void WriteEdges(MessageSerializer* s) {
+ intptr_t count = objects_.length();
+ for (intptr_t i = 0; i < count; i++) {
+ LinkedHashMap* map = objects_[i];
+ s->WriteRef(map->untag()->type_arguments());
+ s->WriteRef(map->untag()->data());
+ s->WriteRef(map->untag()->used_data());
+ }
+ }
+
+ private:
+ GrowableArray<LinkedHashMap*> objects_;
+};
+
+class LinkedHashMapMessageDeserializationCluster
+ : public MessageDeserializationCluster {
+ public:
+ explicit LinkedHashMapMessageDeserializationCluster(bool is_canonical)
+ : MessageDeserializationCluster("LinkedHashMap", is_canonical) {}
+ ~LinkedHashMapMessageDeserializationCluster() {}
+
+ void ReadNodes(MessageDeserializer* d) {
+ intptr_t count = d->ReadUnsigned();
+ for (intptr_t i = 0; i < count; i++) {
+ d->AssignRef(LinkedHashMap::NewUninitialized());
+ }
+ }
+
+ void ReadEdges(MessageDeserializer* d) {
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ LinkedHashMapPtr map = static_cast<LinkedHashMapPtr>(d->Ref(id));
+ map->untag()->set_hash_mask(Smi::New(0));
+ map->untag()->set_type_arguments(
+ static_cast<TypeArgumentsPtr>(d->ReadRef()));
+ map->untag()->set_data(static_cast<ArrayPtr>(d->ReadRef()));
+ map->untag()->set_used_data(static_cast<SmiPtr>(d->ReadRef()));
+ map->untag()->set_deleted_keys(Smi::New(0));
+ }
+ }
+
+ ObjectPtr PostLoad(MessageDeserializer* d) { return PostLoadLinkedHash(d); }
+};
+
+class LinkedHashSetMessageSerializationCluster
+ : public MessageSerializationCluster {
+ public:
+ LinkedHashSetMessageSerializationCluster()
+ : MessageSerializationCluster("LinkedHashSet",
+ MessagePhase::kNonCanonicalInstances,
+ kLinkedHashSetCid) {}
+ ~LinkedHashSetMessageSerializationCluster() {}
+
+ void Trace(MessageSerializer* s, Object* object) {
+ LinkedHashSet* map = static_cast<LinkedHashSet*>(object);
+ objects_.Add(map);
+
+ s->Push(map->untag()->type_arguments());
+ s->Push(map->untag()->data());
+ s->Push(map->untag()->used_data());
+ }
+
+ void WriteNodes(MessageSerializer* s) {
+ intptr_t count = objects_.length();
+ s->WriteUnsigned(count);
+ for (intptr_t i = 0; i < count; i++) {
+ LinkedHashSet* map = objects_[i];
+ s->AssignRef(map);
+ }
+ }
+
+ void WriteEdges(MessageSerializer* s) {
+ intptr_t count = objects_.length();
+ for (intptr_t i = 0; i < count; i++) {
+ LinkedHashSet* map = objects_[i];
+ s->WriteRef(map->untag()->type_arguments());
+ s->WriteRef(map->untag()->data());
+ s->WriteRef(map->untag()->used_data());
+ }
+ }
+
+ private:
+ GrowableArray<LinkedHashSet*> objects_;
+};
+
+class LinkedHashSetMessageDeserializationCluster
+ : public MessageDeserializationCluster {
+ public:
+ explicit LinkedHashSetMessageDeserializationCluster(bool is_canonical)
+ : MessageDeserializationCluster("LinkedHashSet", is_canonical) {}
+ ~LinkedHashSetMessageDeserializationCluster() {}
+
+ void ReadNodes(MessageDeserializer* d) {
+ intptr_t count = d->ReadUnsigned();
+ for (intptr_t i = 0; i < count; i++) {
+ d->AssignRef(LinkedHashSet::NewUninitialized());
+ }
+ }
+
+ void ReadEdges(MessageDeserializer* d) {
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ LinkedHashSetPtr map = static_cast<LinkedHashSetPtr>(d->Ref(id));
+ map->untag()->set_hash_mask(Smi::New(0));
+ map->untag()->set_type_arguments(
+ static_cast<TypeArgumentsPtr>(d->ReadRef()));
+ map->untag()->set_data(static_cast<ArrayPtr>(d->ReadRef()));
+ map->untag()->set_used_data(static_cast<SmiPtr>(d->ReadRef()));
+ map->untag()->set_deleted_keys(Smi::New(0));
+ }
+ }
+
+ ObjectPtr PostLoad(MessageDeserializer* d) { return PostLoadLinkedHash(d); }
+};
+
+class ArrayMessageSerializationCluster : public MessageSerializationCluster {
+ public:
+ ArrayMessageSerializationCluster(Zone* zone, bool is_canonical, intptr_t cid)
+ : MessageSerializationCluster("Array",
+ is_canonical
+ ? MessagePhase::kCanonicalInstances
+ : MessagePhase::kNonCanonicalInstances,
+ cid,
+ is_canonical),
+ objects_(zone, 0) {}
+ ~ArrayMessageSerializationCluster() {}
+
+ void Trace(MessageSerializer* s, Object* object) {
+ Array* array = static_cast<Array*>(object);
+ objects_.Add(array);
+
+ s->Push(array->untag()->type_arguments());
+ intptr_t length = Smi::Value(array->untag()->length());
+ for (intptr_t i = 0; i < length; i++) {
+ s->Push(array->untag()->element(i));
+ }
+ }
+
+ void WriteNodes(MessageSerializer* s) {
+ intptr_t count = objects_.length();
+ s->WriteUnsigned(count);
+ for (intptr_t i = 0; i < count; i++) {
+ Array* array = objects_[i];
+ s->AssignRef(array);
+ intptr_t length = Smi::Value(array->untag()->length());
+ s->WriteUnsigned(length);
+ }
+ }
+
+ void WriteEdges(MessageSerializer* s) {
+ intptr_t count = objects_.length();
+ for (intptr_t i = 0; i < count; i++) {
+ Array* array = objects_[i];
+ intptr_t length = array->Length();
+ s->WriteRef(array->untag()->type_arguments());
+ for (intptr_t j = 0; j < length; j++) {
+ s->WriteRef(array->untag()->element(j));
+ }
+ }
+ }
+
+ void TraceApi(ApiMessageSerializer* s, Dart_CObject* object) {
+ objects_.Add(reinterpret_cast<Array*>(object));
+
+ for (intptr_t i = 0, n = object->value.as_array.length; i < n; i++) {
+ s->Push(object->value.as_array.values[i]);
+ }
+ }
+
+ void WriteNodesApi(ApiMessageSerializer* s) {
+ intptr_t count = objects_.length();
+ s->WriteUnsigned(count);
+ for (intptr_t i = 0; i < count; i++) {
+ Dart_CObject* array = reinterpret_cast<Dart_CObject*>(objects_[i]);
+ s->AssignRef(array);
+ s->WriteUnsigned(array->value.as_array.length);
+ }
+ }
+
+ void WriteEdgesApi(ApiMessageSerializer* s) {
+ intptr_t count = objects_.length();
+ for (intptr_t i = 0; i < count; i++) {
+ Dart_CObject* array = reinterpret_cast<Dart_CObject*>(objects_[i]);
+ intptr_t length = array->value.as_array.length;
+ s->WriteRef(&cobj_null); // TypeArguments
+ for (intptr_t j = 0; j < length; j++) {
+ s->WriteRef(array->value.as_array.values[j]);
+ }
+ }
+ }
+
+ private:
+ GrowableArray<Array*> objects_;
+};
+
+class ArrayMessageDeserializationCluster
+ : public MessageDeserializationCluster {
+ public:
+ explicit ArrayMessageDeserializationCluster(bool is_canonical, intptr_t cid)
+ : MessageDeserializationCluster("Array", is_canonical), cid_(cid) {}
+ ~ArrayMessageDeserializationCluster() {}
+
+ void ReadNodes(MessageDeserializer* d) {
+ intptr_t count = d->ReadUnsigned();
+ for (intptr_t i = 0; i < count; i++) {
+ intptr_t length = d->ReadUnsigned();
+ d->AssignRef(Array::New(cid_, length));
+ }
+ }
+
+ void ReadEdges(MessageDeserializer* d) {
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ ArrayPtr array = static_cast<ArrayPtr>(d->Ref(id));
+ intptr_t length = Smi::Value(array->untag()->length());
+ array->untag()->set_type_arguments(
+ static_cast<TypeArgumentsPtr>(d->ReadRef()));
+ for (intptr_t j = 0; j < length; j++) {
+ array->untag()->set_element(j, d->ReadRef());
+ }
+ }
+ }
+
+ ObjectPtr PostLoad(MessageDeserializer* d) {
+ if (is_canonical()) {
+ SafepointMutexLocker ml(
+ d->isolate_group()->constant_canonicalization_mutex());
+ Instance& instance = Instance::Handle(d->zone());
+ for (intptr_t i = start_index_; i < stop_index_; i++) {
+ instance ^= d->Ref(i);
+ instance = instance.CanonicalizeLocked(d->thread());
+ d->UpdateRef(i, instance);
+ }
+ }
+ return nullptr;
+ }
+
+ void ReadNodesApi(ApiMessageDeserializer* d) {
+ intptr_t count = d->ReadUnsigned();
+ for (intptr_t i = 0; i < count; i++) {
+ Dart_CObject* array = d->Allocate(Dart_CObject_kArray);
+ intptr_t length = d->ReadUnsigned();
+ array->value.as_array.length = length;
+ if (length == 0) {
+ array->value.as_array.values = NULL;
+ } else {
+ array->value.as_array.values = d->zone()->Alloc<Dart_CObject*>(length);
+ }
+ d->AssignRef(array);
+ }
+ }
+
+ void ReadEdgesApi(ApiMessageDeserializer* d) {
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ Dart_CObject* array = d->Ref(id);
+ intptr_t length = array->value.as_array.length;
+ d->ReadRef(); // type_arguments
+ for (intptr_t i = 0; i < length; i++) {
+ array->value.as_array.values[i] = d->ReadRef();
+ }
+ }
+ }
+
+ private:
+ const intptr_t cid_;
+};
+
+class OneByteStringMessageSerializationCluster
+ : public MessageSerializationCluster {
+ public:
+ explicit OneByteStringMessageSerializationCluster(Zone* zone,
+ bool is_canonical)
+ : MessageSerializationCluster("OneByteString",
+ MessagePhase::kBeforeTypes,
+ kOneByteStringCid,
+ is_canonical),
+ objects_(zone, 0) {}
+ ~OneByteStringMessageSerializationCluster() {}
+
+ void Trace(MessageSerializer* s, Object* object) {
+ String* str = static_cast<String*>(object);
+ objects_.Add(str);
+ }
+
+ void WriteNodes(MessageSerializer* s) {
+ intptr_t count = objects_.length();
+ s->WriteUnsigned(count);
+ for (intptr_t i = 0; i < count; i++) {
+ String* str = objects_[i];
+ s->AssignRef(str);
+ intptr_t length = str->Length();
+ s->WriteUnsigned(length);
+ NoSafepointScope no_safepoint;
+ s->WriteBytes(OneByteString::DataStart(*str), length * sizeof(uint8_t));
+ }
+ }
+
+ void TraceApi(ApiMessageSerializer* s, Dart_CObject* object) {
+ objects_.Add(reinterpret_cast<String*>(object));
+ }
+
+ void WriteNodesApi(ApiMessageSerializer* s) {
+ intptr_t count = objects_.length();
+ s->WriteUnsigned(count);
+ for (intptr_t i = 0; i < count; i++) {
+ Dart_CObject* str = reinterpret_cast<Dart_CObject*>(objects_[i]);
+ s->AssignRef(str);
+
+ const uint8_t* utf8_str =
+ reinterpret_cast<const uint8_t*>(str->value.as_string);
+ intptr_t utf8_len = strlen(str->value.as_string);
+ Utf8::Type type = Utf8::kLatin1;
+ intptr_t latin1_len = Utf8::CodeUnitCount(utf8_str, utf8_len, &type);
+
+ uint8_t* latin1_str = reinterpret_cast<uint8_t*>(
+ dart::malloc(latin1_len * sizeof(uint8_t)));
+ bool success =
+ Utf8::DecodeToLatin1(utf8_str, utf8_len, latin1_str, latin1_len);
+ ASSERT(success);
+ s->WriteUnsigned(latin1_len);
+ s->WriteBytes(latin1_str, latin1_len);
+ ::free(latin1_str);
+ }
+ }
+
+ private:
+ GrowableArray<String*> objects_;
+};
+
+class OneByteStringMessageDeserializationCluster
+ : public MessageDeserializationCluster {
+ public:
+ explicit OneByteStringMessageDeserializationCluster(bool is_canonical)
+ : MessageDeserializationCluster("OneByteString", is_canonical) {}
+ ~OneByteStringMessageDeserializationCluster() {}
+
+ void ReadNodes(MessageDeserializer* d) {
+ intptr_t count = d->ReadUnsigned();
+ for (intptr_t i = 0; i < count; i++) {
+ intptr_t length = d->ReadUnsigned();
+ const uint8_t* data = d->CurrentBufferAddress();
+ d->Advance(length * sizeof(uint8_t));
+ d->AssignRef(is_canonical()
+ ? Symbols::FromLatin1(d->thread(), data, length)
+ : String::FromLatin1(data, length));
+ }
+ }
+
+ void ReadNodesApi(ApiMessageDeserializer* d) {
+ intptr_t count = d->ReadUnsigned();
+ for (intptr_t i = 0; i < count; i++) {
+ Dart_CObject* str = d->Allocate(Dart_CObject_kString);
+ intptr_t latin1_length = d->ReadUnsigned();
+ const uint8_t* data = d->CurrentBufferAddress();
+
+ d->Advance(latin1_length * sizeof(uint8_t));
+
+ intptr_t utf8_len = 0;
+ for (intptr_t i = 0; i < latin1_length; i++) {
+ utf8_len += Utf8::Length(data[i]);
+ }
+ char* utf8_data = d->zone()->Alloc<char>(utf8_len + 1);
+ str->value.as_string = utf8_data;
+ for (intptr_t i = 0; i < latin1_length; i++) {
+ utf8_data += Utf8::Encode(data[i], utf8_data);
+ }
+ *utf8_data = '\0';
+
+ d->AssignRef(str);
+ }
+ }
+};
+
+class TwoByteStringMessageSerializationCluster
+ : public MessageSerializationCluster {
+ public:
+ explicit TwoByteStringMessageSerializationCluster(Zone* zone,
+ bool is_canonical)
+ : MessageSerializationCluster("TwoByteString",
+ MessagePhase::kBeforeTypes,
+ kTwoByteStringCid,
+ is_canonical),
+ objects_(zone, 0) {}
+ ~TwoByteStringMessageSerializationCluster() {}
+
+ void Trace(MessageSerializer* s, Object* object) {
+ String* str = static_cast<String*>(object);
+ objects_.Add(str);
+ }
+
+ void WriteNodes(MessageSerializer* s) {
+ intptr_t count = objects_.length();
+ s->WriteUnsigned(count);
+ for (intptr_t i = 0; i < count; i++) {
+ String* str = objects_[i];
+ s->AssignRef(str);
+ intptr_t length = str->Length();
+ s->WriteUnsigned(length);
+ NoSafepointScope no_safepoint;
+ uint16_t* utf16 = TwoByteString::DataStart(*str);
+ s->WriteBytes(reinterpret_cast<const uint8_t*>(utf16),
+ length * sizeof(uint16_t));
+ }
+ }
+
+ void TraceApi(ApiMessageSerializer* s, Dart_CObject* object) {
+ objects_.Add(reinterpret_cast<String*>(object));
+ }
+
+ void WriteNodesApi(ApiMessageSerializer* s) {
+ intptr_t count = objects_.length();
+ s->WriteUnsigned(count);
+ for (intptr_t i = 0; i < count; i++) {
+ Dart_CObject* str = reinterpret_cast<Dart_CObject*>(objects_[i]);
+ s->AssignRef(str);
+
+ const uint8_t* utf8_str =
+ reinterpret_cast<const uint8_t*>(str->value.as_string);
+ intptr_t utf8_len = strlen(str->value.as_string);
+ Utf8::Type type = Utf8::kLatin1;
+ intptr_t utf16_len = Utf8::CodeUnitCount(utf8_str, utf8_len, &type);
+
+ uint16_t* utf16_str = reinterpret_cast<uint16_t*>(
+ dart::malloc(utf16_len * sizeof(uint16_t)));
+ bool success =
+ Utf8::DecodeToUTF16(utf8_str, utf8_len, utf16_str, utf16_len);
+ ASSERT(success);
+ s->WriteUnsigned(utf16_len);
+ s->WriteBytes(reinterpret_cast<const uint8_t*>(utf16_str),
+ utf16_len * sizeof(uint16_t));
+ ::free(utf16_str);
+ }
+ }
+
+ private:
+ GrowableArray<String*> objects_;
+};
+
+class TwoByteStringMessageDeserializationCluster
+ : public MessageDeserializationCluster {
+ public:
+ explicit TwoByteStringMessageDeserializationCluster(bool is_canonical)
+ : MessageDeserializationCluster("TwoByteString", is_canonical) {}
+ ~TwoByteStringMessageDeserializationCluster() {}
+
+ void ReadNodes(MessageDeserializer* d) {
+ intptr_t count = d->ReadUnsigned();
+ for (intptr_t i = 0; i < count; i++) {
+ intptr_t length = d->ReadUnsigned();
+ const uint16_t* data =
+ reinterpret_cast<const uint16_t*>(d->CurrentBufferAddress());
+ d->Advance(length * sizeof(uint16_t));
+ d->AssignRef(is_canonical()
+ ? Symbols::FromUTF16(d->thread(), data, length)
+ : String::FromUTF16(data, length));
+ }
+ }
+
+ void ReadNodesApi(ApiMessageDeserializer* d) {
+ intptr_t count = d->ReadUnsigned();
+ for (intptr_t j = 0; j < count; j++) {
+ // Read all the UTF-16 code units.
+ intptr_t utf16_length = d->ReadUnsigned();
+ const uint16_t* utf16 =
+ reinterpret_cast<const uint16_t*>(d->CurrentBufferAddress());
+ d->Advance(utf16_length * sizeof(uint16_t));
+
+ // Calculate the UTF-8 length and check if the string can be
+ // UTF-8 encoded.
+ intptr_t utf8_len = 0;
+ bool valid = true;
+ intptr_t i = 0;
+ while (i < utf16_length && valid) {
+ int32_t ch = Utf16::Next(utf16, &i, utf16_length);
+ utf8_len += Utf8::Length(ch);
+ valid = !Utf16::IsSurrogate(ch);
+ }
+ if (!valid) {
+ d->AssignRef(d->Allocate(Dart_CObject_kUnsupported));
+ } else {
+ Dart_CObject* str = d->Allocate(Dart_CObject_kString);
+ char* utf8 = d->zone()->Alloc<char>(utf8_len + 1);
+ str->value.as_string = utf8;
+ i = 0;
+ while (i < utf16_length) {
+ utf8 += Utf8::Encode(Utf16::Next(utf16, &i, utf16_length), utf8);
+ }
+ *utf8 = '\0';
+ d->AssignRef(str);
+ }
+ }
+ }
+};
+
+static const intptr_t kFirstReference = 1;
+static const intptr_t kUnallocatedReference = -1;
+
+BaseSerializer::BaseSerializer(Thread* thread, Zone* zone)
+ : StackResource(thread),
+ zone_(zone),
+ stream_(100),
+ finalizable_data_(new MessageFinalizableData()),
+ clusters_(zone, 0),
+ ephemeron_cluster_(nullptr),
+ num_base_objects_(0),
+ num_written_objects_(0),
+ next_ref_index_(kFirstReference) {}
+
+BaseSerializer::~BaseSerializer() {
+ delete finalizable_data_;
+}
+
+MessageSerializer::MessageSerializer(Thread* thread, bool can_send_any_object)
+ : BaseSerializer(thread, thread->zone()),
+ forward_table_new_(),
+ forward_table_old_(),
+ stack_(thread->zone(), 0),
+ can_send_any_object_(can_send_any_object),
+ exception_message_(nullptr) {
+ isolate()->set_forward_table_new(new WeakTable());
+ isolate()->set_forward_table_old(new WeakTable());
+}
+
+MessageSerializer::~MessageSerializer() {
+ isolate()->set_forward_table_new(nullptr);
+ isolate()->set_forward_table_old(nullptr);
+}
+
+ApiMessageSerializer::ApiMessageSerializer(Zone* zone)
+ : BaseSerializer(nullptr, zone), forward_table_(), stack_(zone, 0) {}
+
+ApiMessageSerializer::~ApiMessageSerializer() {}
+
+void MessageSerializer::Push(ObjectPtr object) {
+ if (MarkObjectId(object, kUnallocatedReference)) {
+ stack_.Add(&Object::ZoneHandle(zone_, object));
+ num_written_objects_++;
+ }
+}
+
+void ApiMessageSerializer::Push(Dart_CObject* object) {
+ if (MarkObjectId(object, kUnallocatedReference)) {
+ stack_.Add(object);
+ num_written_objects_++;
+ }
+}
+
+void MessageSerializer::Trace(Object* object) {
+ intptr_t cid;
+ bool is_canonical;
+ if (!object->ptr()->IsHeapObject()) {
+ cid = kSmiCid;
+ is_canonical = true;
+ } else {
+ cid = object->GetClassId();
+ is_canonical = object->ptr()->untag()->IsCanonical();
+ }
+
+ MessageSerializationCluster* cluster = nullptr;
+ for (MessageSerializationCluster* c : clusters_) {
+ if ((c->cid() == cid) && (c->is_canonical() == is_canonical)) {
+ cluster = c;
+ break;
+ }
+ }
+ if (cluster == nullptr) {
+ if (cid >= kNumPredefinedCids || cid == kInstanceCid) {
+ const Class& clazz =
+ Class::Handle(zone(), isolate_group()->class_table()->At(cid));
+ if (!can_send_any_object()) {
+ ObjectStore* object_store = isolate_group()->object_store();
+ if ((clazz.library() != object_store->core_library()) &&
+ (clazz.library() != object_store->collection_library()) &&
+ (clazz.library() != object_store->typed_data_library())) {
+ IllegalObject(*object,
+ "Illegal argument in isolate message"
+ " : (object is a regular Dart Instance)");
+ }
+ }
+ if (clazz.num_native_fields() != 0) {
+ char* chars = OS::SCreate(thread()->zone(),
+ "Illegal argument in isolate message"
+ " : (object extends NativeWrapper - %s)",
+ clazz.ToCString());
+ IllegalObject(*object, chars);
+ }
+ }
+#define ILLEGAL(type) \
+ if (cid == k##type##Cid) { \
+ IllegalObject(*object, \
+ "Illegal argument in isolate message" \
+ " : (object is a " #type ")"); \
+ }
+
+ ILLEGAL(FunctionType)
+ ILLEGAL(DynamicLibrary)
+ ILLEGAL(MirrorReference)
+ ILLEGAL(Pointer)
+ ILLEGAL(ReceivePort)
+ ILLEGAL(StackTrace)
+ ILLEGAL(UserTag)
+#undef ILLEGAL
+
+ switch (cid) {
+#define ILLEGAL(type) case kFfi##type##Cid:
+ CLASS_LIST_FFI(ILLEGAL)
+#undef ILLEGAL
+ IllegalObject(*object,
+ "Native objects (from dart:ffi) such as Pointers and "
+ "Structs cannot be passed between isolates.");
+ }
+
+ if (cid >= kNumPredefinedCids || cid == kInstanceCid ||
+ cid == kByteBufferCid) {
+ Push(isolate_group()->class_table()->At(cid));
+ }
+ cluster = NewClusterForClass(cid, is_canonical);
+ clusters_.Add(cluster);
+ }
+
+ cluster->Trace(this, object);
+}
+
+bool ApiMessageSerializer::Trace(Dart_CObject* object) {
+ const bool is_canonical = false;
+ intptr_t cid;
+ switch (object->type) {
+ case Dart_CObject_kNull:
+ ForwardRef(object, &cobj_null);
+ return true;
+ case Dart_CObject_kBool:
+ ForwardRef(object, object->value.as_bool ? &cobj_true : &cobj_false);
+ return true;
+ case Dart_CObject_kInt32:
+ cid = Smi::IsValid(object->value.as_int32) ? kSmiCid : kMintCid;
+ break;
+ case Dart_CObject_kInt64:
+ cid = Smi::IsValid(object->value.as_int64) ? kSmiCid : kMintCid;
+ break;
+ case Dart_CObject_kDouble:
+ cid = kDoubleCid;
+ break;
+ case Dart_CObject_kString: {
+ const uint8_t* utf8_str =
+ reinterpret_cast<const uint8_t*>(object->value.as_string);
+ intptr_t utf8_len = strlen(object->value.as_string);
+ if (!Utf8::IsValid(utf8_str, utf8_len)) {
+ return Fail("invalid utf8");
+ }
+ Utf8::Type type = Utf8::kLatin1;
+ intptr_t len = Utf8::CodeUnitCount(utf8_str, utf8_len, &type);
+ if (len > String::kMaxElements) {
+ return Fail("invalid string length");
+ }
+ cid = type == Utf8::kLatin1 ? kOneByteStringCid : kTwoByteStringCid;
+ break;
+ }
+ case Dart_CObject_kArray:
+ cid = kArrayCid;
+ if (!Array::IsValidLength(object->value.as_array.length)) {
+ return Fail("invalid array length");
+ }
+ break;
+ case Dart_CObject_kTypedData:
+ switch (object->value.as_typed_data.type) {
+ case Dart_TypedData_kInt8:
+ cid = kTypedDataInt8ArrayCid;
+ break;
+ case Dart_TypedData_kUint8:
+ cid = kTypedDataUint8ArrayCid;
+ break;
+ case Dart_TypedData_kUint8Clamped:
+ cid = kTypedDataUint8ClampedArrayCid;
+ break;
+ case Dart_TypedData_kInt16:
+ cid = kTypedDataInt16ArrayCid;
+ break;
+ case Dart_TypedData_kUint16:
+ cid = kTypedDataUint16ArrayCid;
+ break;
+ case Dart_TypedData_kInt32:
+ cid = kTypedDataInt32ArrayCid;
+ break;
+ case Dart_TypedData_kUint32:
+ cid = kTypedDataUint32ArrayCid;
+ break;
+ case Dart_TypedData_kInt64:
+ cid = kTypedDataInt64ArrayCid;
+ break;
+ case Dart_TypedData_kUint64:
+ cid = kTypedDataUint64ArrayCid;
+ break;
+ case Dart_TypedData_kFloat32:
+ cid = kTypedDataFloat32ArrayCid;
+ break;
+ case Dart_TypedData_kFloat64:
+ cid = kTypedDataFloat64ArrayCid;
+ break;
+ case Dart_TypedData_kInt32x4:
+ cid = kTypedDataInt32x4ArrayCid;
+ break;
+ case Dart_TypedData_kFloat32x4:
+ cid = kTypedDataFloat32x4ArrayCid;
+ break;
+ case Dart_TypedData_kFloat64x2:
+ cid = kTypedDataFloat64x2ArrayCid;
+ break;
+ default:
+ return Fail("invalid TypedData type");
+ }
+ {
+ intptr_t len = object->value.as_typed_data.length;
+ if (len < 0 || len > TypedData::MaxElements(cid)) {
+ return Fail("invalid typeddata length");
+ }
+ }
+ break;
+ case Dart_CObject_kExternalTypedData:
+ switch (object->value.as_external_typed_data.type) {
+ case Dart_TypedData_kInt8:
+ cid = kExternalTypedDataInt8ArrayCid;
+ break;
+ case Dart_TypedData_kUint8:
+ cid = kExternalTypedDataUint8ArrayCid;
+ break;
+ case Dart_TypedData_kUint8Clamped:
+ cid = kExternalTypedDataUint8ClampedArrayCid;
+ break;
+ case Dart_TypedData_kInt16:
+ cid = kExternalTypedDataInt16ArrayCid;
+ break;
+ case Dart_TypedData_kUint16:
+ cid = kExternalTypedDataUint16ArrayCid;
+ break;
+ case Dart_TypedData_kInt32:
+ cid = kExternalTypedDataInt32ArrayCid;
+ break;
+ case Dart_TypedData_kUint32:
+ cid = kExternalTypedDataUint32ArrayCid;
+ break;
+ case Dart_TypedData_kInt64:
+ cid = kExternalTypedDataInt64ArrayCid;
+ break;
+ case Dart_TypedData_kUint64:
+ cid = kExternalTypedDataUint64ArrayCid;
+ break;
+ case Dart_TypedData_kFloat32:
+ cid = kExternalTypedDataFloat32ArrayCid;
+ break;
+ case Dart_TypedData_kFloat64:
+ cid = kExternalTypedDataFloat64ArrayCid;
+ break;
+ case Dart_TypedData_kInt32x4:
+ cid = kExternalTypedDataInt32x4ArrayCid;
+ break;
+ case Dart_TypedData_kFloat32x4:
+ cid = kExternalTypedDataFloat32x4ArrayCid;
+ break;
+ case Dart_TypedData_kFloat64x2:
+ cid = kExternalTypedDataFloat64x2ArrayCid;
+ break;
+ default:
+ return Fail("invalid TypedData type");
+ }
+ {
+ intptr_t len = object->value.as_typed_data.length;
+ if (len < 0 || len > ExternalTypedData::MaxElements(cid)) {
+ return Fail("invalid typeddata length");
+ }
+ }
+ break;
+ case Dart_CObject_kSendPort:
+ cid = kSendPortCid;
+ break;
+ case Dart_CObject_kCapability:
+ cid = kCapabilityCid;
+ break;
+ default:
+ return Fail("invalid Dart_CObject type");
+ }
+
+ MessageSerializationCluster* cluster = nullptr;
+ for (MessageSerializationCluster* c : clusters_) {
+ if (c->cid() == cid) {
+ cluster = c;
+ break;
+ }
+ }
+ if (cluster == nullptr) {
+ cluster = NewClusterForClass(cid, is_canonical);
+ clusters_.Add(cluster);
+ }
+
+ cluster->TraceApi(this, object);
+ return true;
+}
+
+void MessageSerializer::IllegalObject(const Object& object,
+ const char* message) {
+ exception_message_ = message;
+ thread()->long_jump_base()->Jump(1, Object::snapshot_writer_error());
+}
+
+BaseDeserializer::BaseDeserializer(Zone* zone, Message* message)
+ : zone_(zone),
+ stream_(message->snapshot(), message->snapshot_length()),
+ finalizable_data_(message->finalizable_data()),
+ next_ref_index_(kFirstReference) {}
+
+BaseDeserializer::~BaseDeserializer() {}
+
+MessageSerializationCluster* BaseSerializer::NewClusterForClass(
+ intptr_t cid,
+ bool is_canonical) {
+ Zone* Z = zone_;
+ if ((cid >= kNumPredefinedCids) || (cid == kInstanceCid) ||
+ (cid == kByteBufferCid)) {
+ return new (Z) InstanceMessageSerializationCluster(is_canonical, cid);
+ }
+ if (IsTypedDataViewClassId(cid) || cid == kByteDataViewCid) {
+ return new (Z) TypedDataViewMessageSerializationCluster(Z, cid);
+ }
+ if (IsExternalTypedDataClassId(cid)) {
+ return new (Z) ExternalTypedDataMessageSerializationCluster(Z, cid);
+ }
+ if (IsTypedDataClassId(cid)) {
+ return new (Z) TypedDataMessageSerializationCluster(Z, cid);
+ }
+
+ switch (cid) {
+ case kClassCid:
+ return new (Z) ClassMessageSerializationCluster();
+ case kTypeArgumentsCid:
+ return new (Z) TypeArgumentsMessageSerializationCluster(is_canonical);
+ case kFunctionCid:
+ return new (Z) FunctionMessageSerializationCluster();
+ case kTypeCid:
+ return new (Z) TypeMessageSerializationCluster(is_canonical);
+ case kTypeRefCid:
+ return new (Z) TypeRefMessageSerializationCluster(is_canonical);
+ case kClosureCid:
+ return new (Z) ClosureMessageSerializationCluster(is_canonical);
+ case kSmiCid:
+ return new (Z) SmiMessageSerializationCluster(Z);
+ case kMintCid:
+ return new (Z) MintMessageSerializationCluster(Z, is_canonical);
+ case kDoubleCid:
+ return new (Z) DoubleMessageSerializationCluster(Z, is_canonical);
+ case kGrowableObjectArrayCid:
+ return new (Z) GrowableObjectArrayMessageSerializationCluster();
+ case kRegExpCid:
+ return new (Z) RegExpMessageSerializationCluster();
+ case kSendPortCid:
+ return new (Z) SendPortMessageSerializationCluster(Z);
+ case kCapabilityCid:
+ return new (Z) CapabilityMessageSerializationCluster(Z);
+ case kTransferableTypedDataCid:
+ return new (Z) TransferableTypedDataMessageSerializationCluster();
+ case kWeakPropertyCid:
+ ephemeron_cluster_ = new (Z) WeakPropertyMessageSerializationCluster();
+ return ephemeron_cluster_;
+ case kLinkedHashMapCid:
+ return new (Z) LinkedHashMapMessageSerializationCluster();
+ case kLinkedHashSetCid:
+ return new (Z) LinkedHashSetMessageSerializationCluster();
+ case kArrayCid:
+ case kImmutableArrayCid:
+ return new (Z) ArrayMessageSerializationCluster(Z, is_canonical, cid);
+ case kOneByteStringCid:
+ return new (Z) OneByteStringMessageSerializationCluster(Z, is_canonical);
+ case kTwoByteStringCid:
+ return new (Z) TwoByteStringMessageSerializationCluster(Z, is_canonical);
+ default:
+ break;
+ }
+
+ FATAL("No cluster defined for cid %" Pd, cid);
+ return nullptr;
+}
+
+void BaseSerializer::WriteCluster(MessageSerializationCluster* cluster) {
+ uint64_t cid_and_canonical = (static_cast<uint64_t>(cluster->cid()) << 1) |
+ (cluster->is_canonical() ? 0x1 : 0x0);
+ WriteUnsigned(cid_and_canonical);
+}
+
+MessageDeserializationCluster* BaseDeserializer::ReadCluster() {
+ const uint64_t cid_and_canonical = ReadUnsigned();
+ const intptr_t cid = (cid_and_canonical >> 1) & kMaxUint32;
+ const bool is_canonical = (cid_and_canonical & 0x1) == 0x1;
+
+ Zone* Z = zone_;
+ if ((cid >= kNumPredefinedCids) || (cid == kInstanceCid) ||
+ (cid == kByteBufferCid)) {
+ return new (Z) InstanceMessageDeserializationCluster(is_canonical);
+ }
+ if (IsTypedDataViewClassId(cid) || cid == kByteDataViewCid) {
+ ASSERT(!is_canonical);
+ return new (Z) TypedDataViewMessageDeserializationCluster(cid);
+ }
+ if (IsExternalTypedDataClassId(cid)) {
+ ASSERT(!is_canonical);
+ return new (Z) ExternalTypedDataMessageDeserializationCluster(cid);
+ }
+ if (IsTypedDataClassId(cid)) {
+ ASSERT(!is_canonical);
+ return new (Z) TypedDataMessageDeserializationCluster(cid);
+ }
+
+ switch (cid) {
+ case kClassCid:
+ ASSERT(!is_canonical);
+ return new (Z) ClassMessageDeserializationCluster();
+ case kTypeArgumentsCid:
+ return new (Z) TypeArgumentsMessageDeserializationCluster(is_canonical);
+ case kFunctionCid:
+ ASSERT(!is_canonical);
+ return new (Z) FunctionMessageDeserializationCluster();
+ case kTypeCid:
+ return new (Z) TypeMessageDeserializationCluster(is_canonical);
+ case kTypeRefCid:
+ return new (Z) TypeRefMessageDeserializationCluster(is_canonical);
+ case kClosureCid:
+ return new (Z) ClosureMessageDeserializationCluster(is_canonical);
+ case kSmiCid:
+ ASSERT(is_canonical);
+ return new (Z) SmiMessageDeserializationCluster();
+ case kMintCid:
+ return new (Z) MintMessageDeserializationCluster(is_canonical);
+ case kDoubleCid:
+ return new (Z) DoubleMessageDeserializationCluster(is_canonical);
+ case kGrowableObjectArrayCid:
+ ASSERT(!is_canonical);
+ return new (Z) GrowableObjectArrayMessageDeserializationCluster();
+ case kRegExpCid:
+ ASSERT(!is_canonical);
+ return new (Z) RegExpMessageDeserializationCluster();
+ case kSendPortCid:
+ ASSERT(!is_canonical);
+ return new (Z) SendPortMessageDeserializationCluster();
+ case kCapabilityCid:
+ ASSERT(!is_canonical);
+ return new (Z) CapabilityMessageDeserializationCluster();
+ case kTransferableTypedDataCid:
+ ASSERT(!is_canonical);
+ return new (Z) TransferableTypedDataMessageDeserializationCluster();
+ case kWeakPropertyCid:
+ ASSERT(!is_canonical);
+ return new (Z) WeakPropertyMessageDeserializationCluster();
+ case kLinkedHashMapCid:
+ return new (Z) LinkedHashMapMessageDeserializationCluster(is_canonical);
+ case kLinkedHashSetCid:
+ return new (Z) LinkedHashSetMessageDeserializationCluster(is_canonical);
+ case kArrayCid:
+ case kImmutableArrayCid:
+ return new (Z) ArrayMessageDeserializationCluster(is_canonical, cid);
+ case kOneByteStringCid:
+ return new (Z) OneByteStringMessageDeserializationCluster(is_canonical);
+ case kTwoByteStringCid:
+ return new (Z) TwoByteStringMessageDeserializationCluster(is_canonical);
+ default:
+ break;
+ }
+
+ FATAL("No cluster defined for cid %" Pd, cid);
+ return nullptr;
+}
+
+void MessageSerializer::AddBaseObjects() {
+ AddBaseObject(Object::null());
+ AddBaseObject(Object::sentinel().ptr());
+ AddBaseObject(Object::transition_sentinel().ptr());
+ AddBaseObject(Object::empty_array().ptr());
+ AddBaseObject(Object::zero_array().ptr());
+ AddBaseObject(Object::dynamic_type().ptr());
+ AddBaseObject(Object::void_type().ptr());
+ AddBaseObject(Object::empty_type_arguments().ptr());
+ AddBaseObject(Bool::True().ptr());
+ AddBaseObject(Bool::False().ptr());
+}
+
+void MessageDeserializer::AddBaseObjects() {
+ AddBaseObject(Object::null());
+ AddBaseObject(Object::sentinel().ptr());
+ AddBaseObject(Object::transition_sentinel().ptr());
+ AddBaseObject(Object::empty_array().ptr());
+ AddBaseObject(Object::zero_array().ptr());
+ AddBaseObject(Object::dynamic_type().ptr());
+ AddBaseObject(Object::void_type().ptr());
+ AddBaseObject(Object::empty_type_arguments().ptr());
+ AddBaseObject(Bool::True().ptr());
+ AddBaseObject(Bool::False().ptr());
+}
+
+void ApiMessageSerializer::AddBaseObjects() {
+ AddBaseObject(&cobj_null);
+ AddBaseObject(&cobj_sentinel);
+ AddBaseObject(&cobj_transition_sentinel);
+ AddBaseObject(&cobj_empty_array);
+ AddBaseObject(&cobj_zero_array);
+ AddBaseObject(&cobj_dynamic_type);
+ AddBaseObject(&cobj_void_type);
+ AddBaseObject(&cobj_empty_type_arguments);
+ AddBaseObject(&cobj_true);
+ AddBaseObject(&cobj_false);
+}
+
+void ApiMessageDeserializer::AddBaseObjects() {
+ AddBaseObject(&cobj_null);
+ AddBaseObject(&cobj_sentinel);
+ AddBaseObject(&cobj_transition_sentinel);
+ AddBaseObject(&cobj_empty_array);
+ AddBaseObject(&cobj_zero_array);
+ AddBaseObject(&cobj_dynamic_type);
+ AddBaseObject(&cobj_void_type);
+ AddBaseObject(&cobj_empty_type_arguments);
+ AddBaseObject(&cobj_true);
+ AddBaseObject(&cobj_false);
+}
+
+void MessageSerializer::Serialize(const Object& root) {
+ AddBaseObjects();
+
+ Push(root.ptr());
+
+ while (stack_.length() > 0) {
+ // Strong references.
+ while (stack_.length() > 0) {
+ Trace(stack_.RemoveLast());
+ }
+
+ // Ephemeron references.
+ if (ephemeron_cluster_ != nullptr) {
+ ephemeron_cluster_->RetraceEphemerons(this);
+ }
+ }
+
+ intptr_t num_objects = num_base_objects_ + num_written_objects_;
+ WriteUnsigned(num_base_objects_);
+ WriteUnsigned(num_objects);
+
+ for (intptr_t i = 0; i < static_cast<intptr_t>(MessagePhase::kNumPhases);
+ i++) {
+ intptr_t num_clusters = 0;
+ for (MessageSerializationCluster* cluster : clusters_) {
+ if (static_cast<intptr_t>(cluster->phase()) != i) continue;
+ num_clusters++;
+ }
+ WriteUnsigned(num_clusters);
+ for (MessageSerializationCluster* cluster : clusters_) {
+ if (static_cast<intptr_t>(cluster->phase()) != i) continue;
+ WriteCluster(cluster);
+ cluster->WriteNodes(this);
+ }
+ for (MessageSerializationCluster* cluster : clusters_) {
+ if (static_cast<intptr_t>(cluster->phase()) != i) continue;
+ cluster->WriteEdges(this);
+ }
+ }
+
+ // We should have assigned a ref to every object we pushed.
+ ASSERT((next_ref_index_ - 1) == num_objects);
+
+ WriteRef(root.ptr());
+}
+
+bool ApiMessageSerializer::Serialize(Dart_CObject* root) {
+ AddBaseObjects();
+
+ Push(root);
+
+ // Strong references only.
+ while (stack_.length() > 0) {
+ if (!Trace(stack_.RemoveLast())) {
+ return false;
+ }
+ }
+
+ intptr_t num_objects = num_base_objects_ + num_written_objects_;
+ WriteUnsigned(num_base_objects_);
+ WriteUnsigned(num_objects);
+
+ for (intptr_t i = 0; i < static_cast<intptr_t>(MessagePhase::kNumPhases);
+ i++) {
+ intptr_t num_clusters = 0;
+ for (MessageSerializationCluster* cluster : clusters_) {
+ if (static_cast<intptr_t>(cluster->phase()) != i) continue;
+ num_clusters++;
+ }
+ WriteUnsigned(num_clusters);
+ for (MessageSerializationCluster* cluster : clusters_) {
+ if (static_cast<intptr_t>(cluster->phase()) != i) continue;
+ WriteCluster(cluster);
+ cluster->WriteNodesApi(this);
+ }
+ for (MessageSerializationCluster* cluster : clusters_) {
+ if (static_cast<intptr_t>(cluster->phase()) != i) continue;
+ cluster->WriteEdgesApi(this);
+ }
+ }
+
+ // We should have assigned a ref to every object we pushed.
+ ASSERT((next_ref_index_ - 1) == num_objects);
+
+ WriteRef(root);
+ return true;
+}
+
+ObjectPtr MessageDeserializer::Deserialize() {
+ intptr_t num_base_objects = ReadUnsigned();
+ intptr_t num_objects = ReadUnsigned();
+
+ refs_ = Array::New(num_objects + kFirstReference);
+
+ AddBaseObjects();
+
+ // Writer and reader must agree on number of base objects.
+ ASSERT_EQUAL(num_base_objects, (next_ref_index_ - kFirstReference));
+
+ Object& error = Object::Handle(zone());
+ for (intptr_t i = 0; i < static_cast<intptr_t>(MessagePhase::kNumPhases);
+ i++) {
+ intptr_t num_clusters = ReadUnsigned();
+ MessageDeserializationCluster** clusters =
+ zone()->Alloc<MessageDeserializationCluster*>(num_clusters);
+ for (intptr_t i = 0; i < num_clusters; i++) {
+ clusters[i] = ReadCluster();
+ clusters[i]->ReadNodesWrapped(this);
+ }
+ for (intptr_t i = 0; i < num_clusters; i++) {
+ clusters[i]->ReadEdges(this);
+ }
+ for (intptr_t i = 0; i < num_clusters; i++) {
+ error = clusters[i]->PostLoad(this);
+ if (error.IsError()) {
+ return error.ptr(); // E.g., an UnwindError during rehashing.
+ }
+ }
+ }
+
+ // We should have completely filled the ref array.
+ ASSERT_EQUAL(next_ref_index_ - kFirstReference, num_objects);
+
+ return ReadRef();
+}
+
+Dart_CObject* ApiMessageDeserializer::Deserialize() {
+ intptr_t num_base_objects = ReadUnsigned();
+ intptr_t num_objects = ReadUnsigned();
+
+ refs_ = zone()->Alloc<Dart_CObject*>(num_objects + kFirstReference);
+
+ AddBaseObjects();
+
+ // Writer and reader must agree on number of base objects.
+ ASSERT_EQUAL(num_base_objects, (next_ref_index_ - kFirstReference));
+
+ for (intptr_t i = 0; i < static_cast<intptr_t>(MessagePhase::kNumPhases);
+ i++) {
+ intptr_t num_clusters = ReadUnsigned();
+ MessageDeserializationCluster** clusters =
+ zone()->Alloc<MessageDeserializationCluster*>(num_clusters);
+ for (intptr_t i = 0; i < num_clusters; i++) {
+ clusters[i] = ReadCluster();
+ clusters[i]->ReadNodesWrappedApi(this);
+ }
+ for (intptr_t i = 0; i < num_clusters; i++) {
+ clusters[i]->ReadEdgesApi(this);
+ }
+ for (intptr_t i = 0; i < num_clusters; i++) {
+ clusters[i]->PostLoadApi(this);
+ }
+ }
+
+ // We should have completely filled the ref array.
+ ASSERT_EQUAL(next_ref_index_ - kFirstReference, num_objects);
+
+ return ReadRef();
+}
+
+std::unique_ptr<Message> WriteMessage(bool can_send_any_object,
+ const Object& obj,
+ Dart_Port dest_port,
+ Message::Priority priority) {
+ if (ApiObjectConverter::CanConvert(obj.ptr())) {
+ return Message::New(dest_port, obj.ptr(), priority);
+ }
+
+ Thread* thread = Thread::Current();
+ MessageSerializer serializer(thread, can_send_any_object);
+
+ volatile bool has_exception = false;
+ {
+ LongJumpScope jump;
+ if (setjmp(*jump.Set()) == 0) {
+ serializer.Serialize(obj);
+ } else {
+ has_exception = true;
+ }
+ }
+
+ if (has_exception) {
+ {
+ NoSafepointScope no_safepoint;
+ ErrorPtr error = thread->StealStickyError();
+ ASSERT(error == Object::snapshot_writer_error().ptr());
+ }
+
+ const String& msg_obj =
+ String::Handle(String::New(serializer.exception_message()));
+ const Array& args = Array::Handle(Array::New(1));
+ args.SetAt(0, msg_obj);
+ Exceptions::ThrowByType(Exceptions::kArgument, args);
+ }
+
+ return serializer.Finish(dest_port, priority);
+}
+
+std::unique_ptr<Message> WriteApiMessage(Zone* zone,
+ Dart_CObject* obj,
+ Dart_Port dest_port,
+ Message::Priority priority) {
+ ApiMessageSerializer serializer(zone);
+ if (!serializer.Serialize(obj)) {
+ return nullptr;
+ }
+ return serializer.Finish(dest_port, priority);
+}
+
+ObjectPtr ReadMessage(Thread* thread, Message* message) {
+ if (message->IsRaw()) {
+ return message->raw_obj();
+ } else {
+ RELEASE_ASSERT(message->IsSnapshot());
+ MessageDeserializer deserializer(thread, message);
+ return deserializer.Deserialize();
+ }
+}
+
+Dart_CObject* ReadApiMessage(Zone* zone, Message* message) {
+ if (message->IsRaw()) {
+ Dart_CObject* result = zone->Alloc<Dart_CObject>(1);
+ ApiObjectConverter::Convert(message->raw_obj(), result);
+ return result;
+ } else {
+ RELEASE_ASSERT(message->IsSnapshot());
+ ApiMessageDeserializer deserializer(zone, message);
+ return deserializer.Deserialize();
+ }
+}
+
+} // namespace dart
diff --git a/runtime/vm/message_snapshot.h b/runtime/vm/message_snapshot.h
new file mode 100644
index 0000000..d06640e
--- /dev/null
+++ b/runtime/vm/message_snapshot.h
@@ -0,0 +1,32 @@
+// 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.
+
+#ifndef RUNTIME_VM_MESSAGE_SNAPSHOT_H_
+#define RUNTIME_VM_MESSAGE_SNAPSHOT_H_
+
+#include <memory>
+
+#include "include/dart_native_api.h"
+#include "vm/message.h"
+#include "vm/object.h"
+
+namespace dart {
+
+std::unique_ptr<Message> WriteMessage(bool can_send_any_object,
+ const Object& obj,
+ Dart_Port dest_port,
+ Message::Priority priority);
+
+std::unique_ptr<Message> WriteApiMessage(Zone* zone,
+ Dart_CObject* obj,
+ Dart_Port dest_port,
+ Message::Priority priority);
+
+ObjectPtr ReadMessage(Thread* thread, Message* message);
+
+Dart_CObject* ReadApiMessage(Zone* zone, Message* message);
+
+} // namespace dart
+
+#endif // RUNTIME_VM_MESSAGE_SNAPSHOT_H_
diff --git a/runtime/vm/native_api_impl.cc b/runtime/vm/native_api_impl.cc
index 20f7748..132ac95 100644
--- a/runtime/vm/native_api_impl.cc
+++ b/runtime/vm/native_api_impl.cc
@@ -12,6 +12,7 @@
#include "vm/dart_api_message.h"
#include "vm/dart_api_state.h"
#include "vm/message.h"
+#include "vm/message_snapshot.h"
#include "vm/native_message_handler.h"
#include "vm/port.h"
#include "vm/service_isolate.h"
@@ -43,9 +44,9 @@
};
static bool PostCObjectHelper(Dart_Port port_id, Dart_CObject* message) {
- ApiMessageWriter writer;
- std::unique_ptr<Message> msg =
- writer.WriteCMessage(message, port_id, Message::kNormalPriority);
+ AllocOnlyStackZone zone;
+ std::unique_ptr<Message> msg = WriteApiMessage(
+ zone.GetZone(), message, port_id, Message::kNormalPriority);
if (msg == nullptr) {
return false;
diff --git a/runtime/vm/native_message_handler.cc b/runtime/vm/native_message_handler.cc
index 65d97fd..31639e9 100644
--- a/runtime/vm/native_message_handler.cc
+++ b/runtime/vm/native_message_handler.cc
@@ -9,6 +9,7 @@
#include "vm/dart_api_message.h"
#include "vm/isolate.h"
#include "vm/message.h"
+#include "vm/message_snapshot.h"
#include "vm/snapshot.h"
namespace dart {
@@ -37,9 +38,7 @@
// All allocation of objects for decoding the message is done in the
// zone associated with this scope.
ApiNativeScope scope;
- Dart_CObject* object;
- ApiMessageReader reader(message.get());
- object = reader.ReadMessage();
+ Dart_CObject* object = ReadApiMessage(scope.zone(), message.get());
(*func())(message->dest_port(), object);
return kOK;
}
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 06dcf56..a1b8649 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -606,7 +606,23 @@
clazz fake_handle; \
builtin_vtables_[k##clazz##Cid] = fake_handle.vtable(); \
}
- CLASS_LIST_NO_OBJECT_NOR_STRING_NOR_ARRAY(INIT_VTABLE)
+ CLASS_LIST_NO_OBJECT_NOR_STRING_NOR_ARRAY_NOR_MAP(INIT_VTABLE)
+#undef INIT_VTABLE
+
+#define INIT_VTABLE(clazz) \
+ { \
+ LinkedHashMap fake_handle; \
+ builtin_vtables_[k##clazz##Cid] = fake_handle.vtable(); \
+ }
+ CLASS_LIST_MAPS(INIT_VTABLE)
+#undef INIT_VTABLE
+
+#define INIT_VTABLE(clazz) \
+ { \
+ LinkedHashSet fake_handle; \
+ builtin_vtables_[k##clazz##Cid] = fake_handle.vtable(); \
+ }
+ CLASS_LIST_SETS(INIT_VTABLE)
#undef INIT_VTABLE
#define INIT_VTABLE(clazz) \
@@ -1948,6 +1964,15 @@
RegisterPrivateClass(cls, Symbols::_LinkedHashMap(), lib);
pending_classes.Add(cls);
+ cls = Class::New<LinkedHashSet, RTN::LinkedHashSet>(isolate_group);
+ object_store->set_linked_hash_set_class(cls);
+ cls.set_type_arguments_field_offset(
+ LinkedHashSet::type_arguments_offset(),
+ RTN::LinkedHashSet::type_arguments_offset());
+ cls.set_num_type_arguments_unsafe(1);
+ RegisterPrivateClass(cls, Symbols::_LinkedHashSet(), lib);
+ pending_classes.Add(cls);
+
// Pre-register the async library so we can place the vm class
// FutureOr there rather than the core library.
lib = Library::LookupLibrary(thread, Symbols::DartAsync());
@@ -2372,8 +2397,6 @@
const bool injected = cls.InjectCIDFields();
ASSERT(injected);
- isolate_group->object_store()->InitKnownObjects();
-
// Set up recognized state of all functions (core, math and typed data).
MethodRecognizer::InitializeState();
#endif // !defined(DART_PRECOMPILED_RUNTIME)
@@ -2414,6 +2437,9 @@
cls = Class::New<LinkedHashMap, RTN::LinkedHashMap>(isolate_group);
object_store->set_linked_hash_map_class(cls);
+ cls = Class::New<LinkedHashSet, RTN::LinkedHashSet>(isolate_group);
+ object_store->set_linked_hash_set_class(cls);
+
cls = Class::New<Float32x4, RTN::Float32x4>(isolate_group);
object_store->set_float32x4_class(cls);
@@ -2995,8 +3021,11 @@
}
ArrayPtr Class::OffsetToFieldMap(bool original_classes) const {
- if (untag()->offset_in_words_to_field() == Array::null()) {
- ASSERT(is_finalized());
+ ASSERT(is_finalized());
+ if (untag()->offset_in_words_to_field<std::memory_order_acquire>() ==
+ Array::null()) {
+ // Even if multiple threads are calling this concurrently, all of them would
+ // compute the same array, so we intentionally don't acquire any locks here.
const intptr_t length = untag()->host_instance_size_in_words_;
const Array& array = Array::Handle(Array::New(length, Heap::kOld));
Class& cls = Class::Handle(this->ptr());
@@ -3012,9 +3041,10 @@
}
cls = cls.SuperClass(original_classes);
}
- untag()->set_offset_in_words_to_field(array.ptr());
+ untag()->set_offset_in_words_to_field<std::memory_order_release>(
+ array.ptr());
}
- return untag()->offset_in_words_to_field();
+ return untag()->offset_in_words_to_field<std::memory_order_acquire>();
}
bool Class::HasInstanceFields() const {
@@ -3995,8 +4025,11 @@
// fields.
const auto host_bitmap = CalculateFieldOffsets();
if (ptr() == isolate_group->class_table()->At(id())) {
- // Sets the new size in the class table.
- isolate_group->class_table()->SetAt(id(), ptr());
+ if (!ClassTable::IsTopLevelCid(id())) {
+ // Unless class is top-level, which don't get instantiated,
+ // sets the new size in the class table.
+ isolate_group->class_table()->UpdateClassSize(id(), ptr());
+ }
if (FLAG_precompiled_mode && !ClassTable::IsTopLevelCid(id())) {
isolate_group->shared_class_table()->SetUnboxedFieldsMapAt(id(),
host_bitmap);
@@ -7486,7 +7519,7 @@
}
FunctionPtr Function::implicit_closure_function() const {
- if (IsClosureFunction() || IsFactory() || IsDispatcherOrImplicitAccessor() ||
+ if (IsClosureFunction() || IsDispatcherOrImplicitAccessor() ||
IsFieldInitializer() || IsFfiTrampoline()) {
return Function::null();
}
@@ -7656,6 +7689,7 @@
// native function: Array[0] = String native name
// Array[1] = Function implicit closure function
// regular function: Function for implicit closure function
+// constructor, factory: Function for implicit closure function
// ffi trampoline function: FfiTrampolineData (Dart->C)
// dyn inv forwarder: Array[0] = Function target
// Array[1] = TypeArguments default type args
@@ -7928,19 +7962,11 @@
bool Function::HasRequiredNamedParameters() const {
#if defined(DART_PRECOMPILED_RUNTIME)
if (signature() == FunctionType::null()) {
- // Signature is not dropped in aot when any named parameter is required.
+ // Signatures for functions with required named parameters are not dropped.
return false;
}
#endif
- if (!HasOptionalNamedParameters()) {
- return false;
- }
- const FunctionType& sig = FunctionType::Handle(signature());
- const Array& parameter_names = Array::Handle(sig.named_parameter_names());
- if (parameter_names.IsNull()) {
- return false;
- }
- return parameter_names.Length() > NumOptionalNamedParameters();
+ return FunctionType::Handle(signature()).HasRequiredNamedParameters();
}
bool Function::IsRequiredAt(intptr_t index) const {
@@ -8010,6 +8036,15 @@
#endif
}
+bool FunctionType::HasRequiredNamedParameters() const {
+ const intptr_t num_named_params = NumOptionalNamedParameters();
+ if (num_named_params == 0) return false;
+ // Check for flag slots in the named parameter names array.
+ const auto& parameter_names = Array::Handle(named_parameter_names());
+ ASSERT(!parameter_names.IsNull());
+ return parameter_names.Length() > num_named_params;
+}
+
static void ReportTooManyTypeParameters(const FunctionType& sig) {
Report::MessageF(Report::kError, Script::Handle(), TokenPosition::kNoSource,
Report::AtLocation,
@@ -8037,10 +8072,41 @@
value);
}
+bool Function::IsGeneric() const {
+ return FunctionType::IsGeneric(signature());
+}
+intptr_t Function::NumTypeParameters() const {
+ return FunctionType::NumTypeParametersOf(signature());
+}
intptr_t Function::NumParentTypeArguments() const {
- // Don't allocate handle in cases where we know it is 0.
- if (!IsClosureFunction()) return 0;
- return FunctionType::Handle(signature()).NumParentTypeArguments();
+ return FunctionType::NumParentTypeArgumentsOf(signature());
+}
+intptr_t Function::NumTypeArguments() const {
+ return FunctionType::NumTypeArgumentsOf(signature());
+}
+intptr_t Function::num_fixed_parameters() const {
+ return FunctionType::NumFixedParametersOf(signature());
+}
+bool Function::HasOptionalParameters() const {
+ return FunctionType::HasOptionalParameters(signature());
+}
+bool Function::HasOptionalNamedParameters() const {
+ return FunctionType::HasOptionalNamedParameters(signature());
+}
+bool Function::HasOptionalPositionalParameters() const {
+ return FunctionType::HasOptionalPositionalParameters(signature());
+}
+intptr_t Function::NumOptionalParameters() const {
+ return FunctionType::NumOptionalParametersOf(signature());
+}
+intptr_t Function::NumOptionalPositionalParameters() const {
+ return FunctionType::NumOptionalPositionalParametersOf(signature());
+}
+intptr_t Function::NumOptionalNamedParameters() const {
+ return FunctionType::NumOptionalNamedParametersOf(signature());
+}
+intptr_t Function::NumParameters() const {
+ return FunctionType::NumParametersOf(signature());
}
TypeParameterPtr Function::TypeParameterAt(intptr_t index,
@@ -8134,10 +8200,6 @@
}
#endif // !defined(DART_PRECOMPILED_RUNTIME)
-intptr_t Function::NumParameters() const {
- return num_fixed_parameters() + NumOptionalParameters();
-}
-
intptr_t Function::NumImplicitParameters() const {
const UntaggedFunction::Kind k = kind();
if (k == UntaggedFunction::kConstructor) {
@@ -9099,6 +9161,7 @@
FunctionPtr Function::NewClosureFunctionWithKind(UntaggedFunction::Kind kind,
const String& name,
const Function& parent,
+ bool is_static,
TokenPosition token_pos,
const Object& owner) {
ASSERT((kind == UntaggedFunction::kClosureFunction) ||
@@ -9110,7 +9173,7 @@
: 0));
const Function& result = Function::Handle(
Function::New(signature, name, kind,
- /* is_static = */ parent.is_static(),
+ /* is_static = */ is_static,
/* is_const = */ false,
/* is_abstract = */ false,
/* is_external = */ false,
@@ -9125,7 +9188,8 @@
// Use the owner defining the parent function and not the class containing it.
const Object& parent_owner = Object::Handle(parent.RawOwner());
return NewClosureFunctionWithKind(UntaggedFunction::kClosureFunction, name,
- parent, token_pos, parent_owner);
+ parent, parent.is_static(), token_pos,
+ parent_owner);
}
FunctionPtr Function::NewImplicitClosureFunction(const String& name,
@@ -9133,8 +9197,9 @@
TokenPosition token_pos) {
// Use the owner defining the parent function and not the class containing it.
const Object& parent_owner = Object::Handle(parent.RawOwner());
- return NewClosureFunctionWithKind(UntaggedFunction::kImplicitClosureFunction,
- name, parent, token_pos, parent_owner);
+ return NewClosureFunctionWithKind(
+ UntaggedFunction::kImplicitClosureFunction, name, parent,
+ parent.is_static() || parent.IsConstructor(), token_pos, parent_owner);
}
bool Function::SafeToClosurize() const {
@@ -9180,7 +9245,7 @@
zone, NewImplicitClosureFunction(closure_name, *this, token_pos()));
// Set closure function's context scope.
- if (is_static()) {
+ if (is_static() || IsConstructor()) {
closure_function.set_context_scope(Object::empty_context_scope());
} else {
const ContextScope& context_scope = ContextScope::Handle(
@@ -9191,15 +9256,46 @@
FunctionType& closure_signature =
FunctionType::Handle(zone, closure_function.signature());
- // Set closure function's type parameters.
- // This function cannot be local, therefore it has no generic parent.
- // Its implicit closure function therefore has no generic parent function
- // either. That is why it is safe to simply copy the type parameters.
- closure_signature.SetTypeParameters(
- TypeParameters::Handle(zone, type_parameters()));
+ // Set closure function's type parameters and result type.
+ if (IsConstructor()) {
+ // Inherit type parameters from owner class.
+ const auto& cls = Class::Handle(zone, Owner());
+ closure_signature.SetTypeParameters(
+ TypeParameters::Handle(zone, cls.type_parameters()));
+ ASSERT(closure_signature.NumTypeParameters() == cls.NumTypeParameters());
- // Set closure function's result type to this result type.
- closure_signature.set_result_type(AbstractType::Handle(zone, result_type()));
+ Type& result_type = Type::Handle(zone);
+ const Nullability result_nullability =
+ (nnbd_mode() == NNBDMode::kOptedInLib) ? Nullability::kNonNullable
+ : Nullability::kLegacy;
+ if (cls.IsGeneric()) {
+ TypeArguments& type_args = TypeArguments::Handle(zone);
+ const intptr_t num_type_params = cls.NumTypeParameters();
+ ASSERT(num_type_params > 0);
+ type_args = TypeArguments::New(num_type_params);
+ TypeParameter& type_param = TypeParameter::Handle(zone);
+ for (intptr_t i = 0; i < num_type_params; i++) {
+ type_param = closure_signature.TypeParameterAt(i);
+ type_args.SetTypeAt(i, type_param);
+ }
+ result_type = Type::New(cls, type_args, result_nullability);
+ result_type ^= ClassFinalizer::FinalizeType(result_type);
+ } else {
+ result_type = cls.DeclarationType();
+ result_type = result_type.ToNullability(result_nullability, Heap::kOld);
+ }
+ closure_signature.set_result_type(result_type);
+ } else {
+ // This function cannot be local, therefore it has no generic parent.
+ // Its implicit closure function therefore has no generic parent function
+ // either. That is why it is safe to simply copy the type parameters.
+ closure_signature.SetTypeParameters(
+ TypeParameters::Handle(zone, type_parameters()));
+
+ // Set closure function's result type to this result type.
+ closure_signature.set_result_type(
+ AbstractType::Handle(zone, result_type()));
+ }
// Set closure function's end token to this end token.
closure_function.set_end_token_pos(end_token_pos());
@@ -9213,8 +9309,9 @@
// removing the receiver if this is an instance method and adding the closure
// object as first parameter.
const int kClosure = 1;
- const int has_receiver = is_static() ? 0 : 1;
- const int num_fixed_params = kClosure - has_receiver + num_fixed_parameters();
+ const int num_implicit_params = NumImplicitParameters();
+ const int num_fixed_params =
+ kClosure - num_implicit_params + num_fixed_parameters();
const int num_opt_params = NumOptionalParameters();
const bool has_opt_pos_params = HasOptionalPositionalParameters();
const int num_params = num_fixed_params + num_opt_params;
@@ -9233,19 +9330,19 @@
closure_signature.SetParameterTypeAt(0, param_type);
closure_function.SetParameterNameAt(0, Symbols::ClosureParameter());
for (int i = kClosure; i < num_pos_params; i++) {
- param_type = ParameterTypeAt(has_receiver - kClosure + i);
+ param_type = ParameterTypeAt(num_implicit_params - kClosure + i);
closure_signature.SetParameterTypeAt(i, param_type);
- param_name = ParameterNameAt(has_receiver - kClosure + i);
+ param_name = ParameterNameAt(num_implicit_params - kClosure + i);
// Set the name in the function for positional parameters.
closure_function.SetParameterNameAt(i, param_name);
}
for (int i = num_pos_params; i < num_params; i++) {
- param_type = ParameterTypeAt(has_receiver - kClosure + i);
+ param_type = ParameterTypeAt(num_implicit_params - kClosure + i);
closure_signature.SetParameterTypeAt(i, param_type);
- param_name = ParameterNameAt(has_receiver - kClosure + i);
+ param_name = ParameterNameAt(num_implicit_params - kClosure + i);
// Set the name in the signature for named parameters.
closure_signature.SetParameterNameAt(i, param_name);
- if (IsRequiredAt(has_receiver - kClosure + i)) {
+ if (IsRequiredAt(num_implicit_params - kClosure + i)) {
closure_signature.SetIsRequiredAt(i);
}
}
@@ -9254,7 +9351,7 @@
// Change covariant parameter types to either Object? for an opted-in implicit
// closure or to Object* for a legacy implicit closure.
- if (!is_static()) {
+ if (!is_static() && !IsConstructor()) {
BitVector is_covariant(zone, NumParameters());
BitVector is_generic_covariant_impl(zone, NumParameters());
kernel::ReadParameterCovariance(*this, &is_covariant,
@@ -9267,7 +9364,7 @@
: object_store->legacy_object_type();
ASSERT(object_type.IsCanonical());
for (intptr_t i = kClosure; i < num_params; ++i) {
- const intptr_t original_param_index = has_receiver - kClosure + i;
+ const intptr_t original_param_index = num_implicit_params - kClosure + i;
if (is_covariant.Contains(original_param_index) ||
is_generic_covariant_impl.Contains(original_param_index)) {
closure_signature.SetParameterTypeAt(i, object_type);
@@ -9279,6 +9376,7 @@
closure_function.SetSignature(closure_signature);
set_implicit_closure_function(closure_function);
ASSERT(closure_function.IsImplicitClosureFunction());
+ ASSERT(HasImplicitClosureFunction());
return closure_function.ptr();
#endif // defined(DART_PRECOMPILED_RUNTIME)
}
@@ -10206,10 +10304,6 @@
untag()->packed_type_parameter_counts_ = packed_type_parameter_counts;
}
-intptr_t FunctionType::NumParameters() const {
- return num_fixed_parameters() + NumOptionalParameters();
-}
-
void FunctionType::set_num_implicit_parameters(intptr_t value) const {
ASSERT(value >= 0);
untag()->packed_parameter_counts_.Update<PackedNumImplicitParameters>(value);
@@ -10264,6 +10358,8 @@
void FunctionType::SetNumOptionalParameters(
intptr_t value,
bool are_optional_positional) const {
+ // HasOptionalNamedParameters only checks this bit, so only set it if there
+ // are actual named parameters.
untag()->packed_parameter_counts_.Update<PackedHasNamedOptionalParameters>(
(value > 0) && !are_optional_positional);
untag()->packed_parameter_counts_.Update<PackedNumOptionalParameters>(value);
@@ -10735,7 +10831,9 @@
}
ASSERT(original.IsOriginal());
Field& clone = Field::Handle();
- clone ^= Object::Clone(*this, Heap::kOld);
+ // Using relaxed loading is fine because concurrent fields changes are all
+ // guarded, will be reconciled during optimized code installation.
+ clone ^= Object::Clone(*this, Heap::kOld, /*load_with_relaxed_atomics=*/true);
clone.SetOriginal(original);
clone.InheritKernelOffsetFrom(original);
return clone.ptr();
@@ -11097,7 +11195,8 @@
// We can safely cache the value of the static const field in the initial
// field table.
- auto& value = Object::Handle(zone, initial_field_table->At(field_id()));
+ auto& value = Object::Handle(
+ zone, initial_field_table->At(field_id(), /*concurrent_use=*/true));
if (value.ptr() == Object::sentinel().ptr()) {
ASSERT(has_initializer());
value = EvaluateInitializer();
@@ -11119,14 +11218,14 @@
ASSERT(initial_field_table->At(field_id()) == Object::sentinel().ptr() ||
initial_field_table->At(field_id()) == value.ptr() ||
!assert_initializing_store);
- initial_field_table->SetAt(field_id(), value.IsNull()
- ? Instance::null_instance().ptr()
- : Instance::Cast(value).ptr());
+ initial_field_table->SetAt(field_id(),
+ value.IsNull() ? Instance::null_instance().ptr()
+ : Instance::Cast(value).ptr(),
+ /*concurrent_use=*/true);
}
ObjectPtr Field::EvaluateInitializer() const {
- Thread* const thread = Thread::Current();
- ASSERT(thread->IsMutatorThread());
+ ASSERT(Thread::Current()->IsMutatorThread());
#if !defined(DART_PRECOMPILED_RUNTIME)
if (is_static() && is_const()) {
@@ -11134,8 +11233,6 @@
}
#endif // !defined(DART_PRECOMPILED_RUNTIME)
- NoOOBMessageScope no_msg_scope(thread);
- NoReloadScope no_reload_scope(thread);
const Function& initializer = Function::Handle(EnsureInitializerFunction());
return DartEntry::InvokeFunction(initializer, Object::empty_array());
}
@@ -11550,14 +11647,14 @@
void Field::RecordStore(const Object& value) const {
ASSERT(IsOriginal());
- if (!IsolateGroup::Current()->use_field_guards()) {
+ Thread* const thread = Thread::Current();
+ if (!thread->isolate_group()->use_field_guards()) {
return;
}
// We should never try to record a sentinel.
ASSERT(value.ptr() != Object::sentinel().ptr());
- Thread* const thread = Thread::Current();
SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
if ((guarded_cid() == kDynamicCid) ||
(is_nullable() && value.ptr() == Object::null())) {
@@ -14333,6 +14430,7 @@
all_libs.Add(&Library::ZoneHandle(Library::ConvertLibrary()));
all_libs.Add(&Library::ZoneHandle(Library::InternalLibrary()));
all_libs.Add(&Library::ZoneHandle(Library::FfiLibrary()));
+ all_libs.Add(&Library::ZoneHandle(Library::NativeWrappersLibrary()));
INTERNAL_LIB_INTRINSIC_LIST(CHECK_FINGERPRINTS_ASM_INTRINSIC);
OTHER_RECOGNIZED_LIST(CHECK_FINGERPRINTS_OTHER);
POLYMORPHIC_TARGET_LIST(CHECK_FINGERPRINTS);
@@ -15464,10 +15562,8 @@
// AOT
ASSERT(target.HasCode());
const Code& code = Code::Handle(target.CurrentCode());
- const Smi& entry_point =
- Smi::Handle(Smi::FromAlignedAddress(code.EntryPoint()));
data.SetAt(data_pos + CodeIndexFor(num_args_tested), code);
- data.SetAt(data_pos + EntryPointIndexFor(num_args_tested), entry_point);
+ data.SetAt(data_pos + EntryPointIndexFor(num_args_tested), target);
#endif
}
@@ -17852,16 +17948,7 @@
}
#if defined(DEBUG)
- if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
- if (target.IsFunction()) {
- const auto& function = Function::Cast(target);
- const auto& entry_point = Smi::Handle(
- Smi::FromAlignedAddress(Code::EntryPointOf(function.CurrentCode())));
- ASSERT(LookupLocked(class_id) == entry_point.ptr());
- }
- } else {
- ASSERT(LookupLocked(class_id) == target.ptr());
- }
+ ASSERT(LookupLocked(class_id) == target.ptr());
#endif // define(DEBUG)
}
@@ -17977,25 +18064,6 @@
name.ToCString());
}
-void MegamorphicCache::SwitchToBareInstructions() {
- NoSafepointScope no_safepoint_scope;
-
- intptr_t capacity = mask() + 1;
- for (intptr_t i = 0; i < capacity; ++i) {
- const intptr_t target_index = i * kEntryLength + kTargetFunctionIndex;
- CompressedObjectPtr* slot = &Array::DataOf(buckets())[target_index];
- ObjectPtr decompressed_slot = slot->Decompress(buckets()->heap_base());
- const intptr_t cid = decompressed_slot->GetClassIdMayBeSmi();
- if (cid == kFunctionCid) {
- CodePtr code =
- Function::CurrentCodeOf(Function::RawCast(decompressed_slot));
- *slot = Smi::FromAlignedAddress(Code::EntryPointOf(code));
- } else {
- ASSERT(cid == kSmiCid || cid == kNullCid);
- }
- }
-}
-
void SubtypeTestCache::Init() {
cached_array_ = Array::New(kTestEntryLength, Heap::kOld);
}
@@ -18213,7 +18281,6 @@
buffer->Printf("%sclass id: %" Pd "", separator,
Smi::Cast(instance_class_id_or_signature).Value());
} else {
- ASSERT(instance_class_id_or_signature.IsFunctionType());
buffer->Printf(
"%ssignature: %s", separator,
FunctionType::Cast(instance_class_id_or_signature).ToCString());
@@ -18252,12 +18319,10 @@
function_type_arguments.ToCString());
}
if (!instance_parent_function_type_arguments.IsNull()) {
- ASSERT(instance_class_id_or_signature.IsFunctionType());
buffer->Printf("%sclosure parent function type arguments: %s", separator,
instance_parent_function_type_arguments.ToCString());
}
if (!instance_delayed_type_arguments.IsNull()) {
- ASSERT(instance_class_id_or_signature.IsFunctionType());
buffer->Printf("%sclosure delayed function type arguments: %s", separator,
instance_delayed_type_arguments.ToCString());
}
@@ -18875,6 +18940,29 @@
return true;
}
+bool Symbol::IsSymbolCid(Thread* thread, classid_t class_id) {
+ auto object_store = thread->isolate_group()->object_store();
+ return Class::GetClassId(object_store->symbol_class()) == class_id;
+}
+
+// Must be kept in sync with Symbol.hashCode in symbol_patch.dart
+uint32_t Symbol::CanonicalizeHash(Thread* thread, const Instance& instance) {
+ ASSERT(IsSymbolCid(thread, instance.GetClassId()));
+
+ auto zone = thread->zone();
+ auto object_store = thread->isolate_group()->object_store();
+
+ const auto& symbol_name_field =
+ Field::Handle(zone, object_store->symbol_name_field());
+ ASSERT(!symbol_name_field.IsNull());
+
+ // Keep in sync with sdk/lib/_internal/vm/lib/symbol_patch.dart.
+ const auto& name =
+ String::Cast(Object::Handle(zone, instance.GetField(symbol_name_field)));
+ const uint32_t arbitrary_prime = 664597;
+ return 0x1fffffff & (arbitrary_prime * name.CanonicalizeHash());
+}
+
uint32_t Instance::CanonicalizeHash() const {
if (GetClassId() == kNullCid) {
return 2011; // Matches null_patch.dart.
@@ -18886,42 +18974,49 @@
}
Zone* zone = thread->zone();
const Class& cls = Class::Handle(zone, clazz());
+ const bool is_symbol = Symbol::IsSymbolCid(thread, cls.id());
+
NoSafepointScope no_safepoint(thread);
- const intptr_t instance_size = SizeFromClass();
- ASSERT(instance_size != 0);
- hash = instance_size / kCompressedWordSize;
- uword this_addr = reinterpret_cast<uword>(this->untag());
- Object& obj = Object::Handle(zone);
- Instance& instance = Instance::Handle(zone);
- const auto unboxed_fields_bitmap =
- thread->isolate_group()->shared_class_table()->GetUnboxedFieldsMapAt(
- GetClassId());
+ if (is_symbol) {
+ hash = Symbol::CanonicalizeHash(thread, *this);
+ } else {
+ const intptr_t class_id = cls.id();
+ ASSERT(class_id != 0);
+ hash = class_id;
+ uword this_addr = reinterpret_cast<uword>(this->untag());
+ Object& obj = Object::Handle(zone);
+ Instance& instance = Instance::Handle(zone);
- for (intptr_t offset = Instance::NextFieldOffset();
- offset < cls.host_next_field_offset(); offset += kCompressedWordSize) {
- if (unboxed_fields_bitmap.Get(offset / kCompressedWordSize)) {
- if (kCompressedWordSize == 8) {
- hash = CombineHashes(hash,
- *reinterpret_cast<uint32_t*>(this_addr + offset));
- hash = CombineHashes(
- hash, *reinterpret_cast<uint32_t*>(this_addr + offset + 4));
+ const auto unboxed_fields_bitmap =
+ thread->isolate_group()->shared_class_table()->GetUnboxedFieldsMapAt(
+ GetClassId());
+
+ for (intptr_t offset = Instance::NextFieldOffset();
+ offset < cls.host_next_field_offset(); offset += kCompressedWordSize) {
+ if (unboxed_fields_bitmap.Get(offset / kCompressedWordSize)) {
+ if (kCompressedWordSize == 8) {
+ hash = CombineHashes(
+ hash, *reinterpret_cast<uint32_t*>(this_addr + offset));
+ hash = CombineHashes(
+ hash, *reinterpret_cast<uint32_t*>(this_addr + offset + 4));
+ } else {
+ hash = CombineHashes(
+ hash, *reinterpret_cast<uint32_t*>(this_addr + offset));
+ }
} else {
- hash = CombineHashes(hash,
- *reinterpret_cast<uint32_t*>(this_addr + offset));
- }
- } else {
- obj = reinterpret_cast<CompressedObjectPtr*>(this_addr + offset)
- ->Decompress(untag()->heap_base());
- if (obj.IsSentinel()) {
- hash = CombineHashes(hash, 11);
- } else {
- instance ^= obj.ptr();
- hash = CombineHashes(hash, instance.CanonicalizeHash());
+ obj = reinterpret_cast<CompressedObjectPtr*>(this_addr + offset)
+ ->Decompress(untag()->heap_base());
+ if (obj.IsSentinel()) {
+ hash = CombineHashes(hash, 11);
+ } else {
+ instance ^= obj.ptr();
+ hash = CombineHashes(hash, instance.CanonicalizeHash());
+ }
}
}
+ hash = FinalizeHash(hash, String::kHashBits);
}
- hash = FinalizeHash(hash, String::kHashBits);
thread->heap()->SetCanonicalHash(ptr(), hash);
return hash;
}
@@ -19027,8 +19122,9 @@
Zone* zone = thread->zone();
Instance& result = Instance::Handle(zone);
const Class& cls = Class::Handle(zone, this->clazz());
- SafepointMutexLocker ml(
- thread->isolate_group()->constant_canonicalization_mutex());
+ ASSERT(thread->isolate_group()
+ ->constant_canonicalization_mutex()
+ ->IsOwnedByCurrentThread());
result ^= cls.LookupCanonicalInstance(zone, *this);
return (result.ptr() == this->ptr());
}
@@ -21005,7 +21101,9 @@
ObjectStore* object_store = isolate_group->object_store();
{
- SafepointMutexLocker ml(isolate_group->type_canonicalization_mutex());
+ ASSERT(thread->isolate_group()
+ ->constant_canonicalization_mutex()
+ ->IsOwnedByCurrentThread());
CanonicalTypeSet table(zone, object_store->canonical_types());
type ^= table.GetOrNull(CanonicalTypeKey(*this));
object_store->set_canonical_types(table.Release());
@@ -21362,7 +21460,9 @@
FunctionType& type = FunctionType::Handle(zone);
ObjectStore* object_store = isolate_group->object_store();
{
- SafepointMutexLocker ml(isolate_group->type_canonicalization_mutex());
+ ASSERT(thread->isolate_group()
+ ->constant_canonicalization_mutex()
+ ->IsOwnedByCurrentThread());
CanonicalFunctionTypeSet table(zone,
object_store->canonical_function_types());
type ^= table.GetOrNull(CanonicalFunctionTypeKey(*this));
@@ -21913,7 +22013,9 @@
TypeParameter& type_parameter = TypeParameter::Handle(zone);
ObjectStore* object_store = isolate_group->object_store();
{
- SafepointMutexLocker ml(isolate_group->type_canonicalization_mutex());
+ ASSERT(thread->isolate_group()
+ ->constant_canonicalization_mutex()
+ ->IsOwnedByCurrentThread());
CanonicalTypeParameterSet table(zone,
object_store->canonical_type_parameters());
type_parameter ^= table.GetOrNull(CanonicalTypeParameterKey(*this));
@@ -24417,6 +24519,54 @@
return zone->PrintToString("_LinkedHashMap len:%" Pd, Length());
}
+LinkedHashSetPtr LinkedHashSet::New(const Array& data,
+ const TypedData& index,
+ intptr_t hash_mask,
+ intptr_t used_data,
+ intptr_t deleted_keys,
+ Heap::Space space) {
+ ASSERT(IsolateGroup::Current()->object_store()->linked_hash_map_class() !=
+ Class::null());
+ LinkedHashSet& result =
+ LinkedHashSet::Handle(LinkedHashSet::NewUninitialized(space));
+ result.SetData(data);
+ result.SetIndex(index);
+ result.SetHashMask(hash_mask);
+ result.SetUsedData(used_data);
+ result.SetDeletedKeys(deleted_keys);
+ return result.ptr();
+}
+
+LinkedHashSetPtr LinkedHashSet::NewDefault(Heap::Space space) {
+ const Array& data = Array::Handle(Array::New(kInitialIndexSize, space));
+ const TypedData& index = TypedData::Handle(
+ TypedData::New(kTypedDataUint32ArrayCid, kInitialIndexSize, space));
+ // On 32-bit, the top bits are wasted to avoid Mint allocation.
+ static const intptr_t kAvailableBits = (kSmiBits >= 32) ? 32 : kSmiBits;
+ static const intptr_t kInitialHashMask =
+ (1 << (kAvailableBits - kInitialIndexBits)) - 1;
+ return LinkedHashSet::New(data, index, kInitialHashMask, 0, 0, space);
+}
+
+LinkedHashSetPtr LinkedHashSet::NewUninitialized(Heap::Space space) {
+ ASSERT(IsolateGroup::Current()->object_store()->linked_hash_map_class() !=
+ Class::null());
+ LinkedHashSet& result = LinkedHashSet::Handle();
+ {
+ ObjectPtr raw =
+ Object::Allocate(kLinkedHashSetCid, LinkedHashSet::InstanceSize(),
+ space, LinkedHashSet::ContainsCompressedPointers());
+ NoSafepointScope no_safepoint;
+ result ^= raw;
+ }
+ return result.ptr();
+}
+
+const char* LinkedHashSet::ToCString() const {
+ Zone* zone = Thread::Current()->zone();
+ return zone->PrintToString("LinkedHashSet len:%" Pd, Length());
+}
+
const char* FutureOr::ToCString() const {
// FutureOr is an abstract class.
UNREACHABLE();
@@ -25030,17 +25180,6 @@
// Ignore function, context, hash.
}
-intptr_t Closure::NumTypeParameters(Thread* thread) const {
- // Only check for empty here, as the null TAV is used to mean that the
- // closed-over delayed type parameters were all of dynamic type.
- if (delayed_type_arguments() != Object::empty_type_arguments().ptr()) {
- return 0;
- } else {
- const auto& closure_function = Function::Handle(thread->zone(), function());
- return closure_function.NumTypeParameters();
- }
-}
-
const char* Closure::ToCString() const {
auto const thread = Thread::Current();
auto const zone = thread->zone();
@@ -25101,6 +25240,10 @@
const Function& function,
const Context& context,
Heap::Space space) {
+ // We store null delayed type arguments, not empty ones, in closures with
+ // non-generic functions a) to make method extraction slightly faster and
+ // b) to make the Closure::IsGeneric check fast.
+ // Keep in sync with StubCodeCompiler::GenerateBuildMethodExtractorStub.
return Closure::New(instantiator_type_arguments, function_type_arguments,
function.IsGeneric() ? Object::empty_type_arguments()
: Object::null_type_arguments(),
@@ -25158,7 +25301,7 @@
// We detect the case of a partial tearoff type application and substitute the
// type arguments for the type parameters of the function.
intptr_t num_free_params;
- if (delayed_type_args.ptr() != Object::empty_type_arguments().ptr()) {
+ if (!IsGeneric() && fun.IsGeneric()) {
num_free_params = kCurrentAndEnclosingFree;
fn_type_args = delayed_type_args.Prepend(
zone, fn_type_args, sig.NumParentTypeArguments(),
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 7cc8063..eb0d9e3 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -215,11 +215,9 @@
#define OBJECT_SERVICE_SUPPORT(object) protected: /* NOLINT */
#endif // !PRODUCT
-#define SNAPSHOT_READER_SUPPORT(object) \
- static object##Ptr ReadFrom(SnapshotReader* reader, intptr_t object_id, \
- intptr_t tags, Snapshot::Kind, \
- bool as_reference); \
- friend class SnapshotReader;
+#define SNAPSHOT_SUPPORT(object) \
+ friend class object##MessageSerializationCluster; \
+ friend class object##MessageDeserializationCluster;
#define OBJECT_IMPLEMENTATION(object, super) \
public: /* NOLINT */ \
@@ -243,7 +241,7 @@
ASSERT(ptr() != null()); \
return const_cast<Untagged##object*>(ptr()->untag()); \
} \
- SNAPSHOT_READER_SUPPORT(object) \
+ SNAPSHOT_SUPPORT(object) \
friend class StackFrame; \
friend class Thread;
@@ -268,7 +266,7 @@
return const_cast<Untagged##object*>(ptr()->untag()); \
} \
static intptr_t NextFieldOffset() { return -kWordSize; } \
- SNAPSHOT_READER_SUPPORT(rettype) \
+ SNAPSHOT_SUPPORT(rettype) \
friend class Object; \
friend class StackFrame; \
friend class Thread;
@@ -620,6 +618,8 @@
};
protected:
+ friend ObjectPtr AllocateObject(intptr_t, intptr_t);
+
// Used for extracting the C++ vtable during bringup.
Object() : ptr_(null_) {}
@@ -858,7 +858,6 @@
friend void ClassTable::Register(const Class& cls);
friend void UntaggedObject::Validate(IsolateGroup* isolate_group) const;
friend class Closure;
- friend class SnapshotReader;
friend class InstanceDeserializationCluster;
friend class OneByteString;
friend class TwoByteString;
@@ -1173,7 +1172,13 @@
intptr_t NumTypeArguments() const;
// Return true if this class declares type parameters.
- bool IsGeneric() const { return NumTypeParameters(Thread::Current()) > 0; }
+ bool IsGeneric() const {
+ // If the declaration is not loaded, fall back onto NumTypeParameters.
+ if (!is_declaration_loaded()) {
+ return NumTypeParameters(Thread::Current()) > 0;
+ }
+ return type_parameters() != Object::null();
+ }
// Returns a canonicalized vector of the type parameters instantiated
// to bounds. If non-generic, the empty type arguments vector is returned.
@@ -1320,8 +1325,7 @@
// Check if this class represents the 'Closure' class.
bool IsClosureClass() const { return id() == kClosureCid; }
static bool IsClosureClass(ClassPtr cls) {
- NoSafepointScope no_safepoint;
- return cls->untag()->id_ == kClosureCid;
+ return GetClassId(cls) == kClosureCid;
}
static bool IsInFullSnapshot(ClassPtr cls) {
@@ -1330,6 +1334,11 @@
cls->untag()->library()->untag()->flags_);
}
+ static intptr_t GetClassId(ClassPtr cls) {
+ NoSafepointScope no_safepoint;
+ return cls->untag()->id_;
+ }
+
// Returns true if the type specified by cls, type_arguments, and nullability
// is a subtype of the other type.
static bool IsSubtypeOf(const Class& cls,
@@ -1511,6 +1520,9 @@
void set_num_native_fields(uint16_t value) const {
StoreNonPointer(&untag()->num_native_fields_, value);
}
+ static uint16_t NumNativeFieldsOf(ClassPtr clazz) {
+ return clazz->untag()->num_native_fields_;
+ }
#if !defined(DART_PRECOMPILED_RUNTIME)
CodePtr allocation_stub() const { return untag()->allocation_stub(); }
@@ -2467,7 +2479,6 @@
friend class VMDeserializationRoots;
friend class ICDataTestTask;
friend class VMSerializationRoots;
- friend class SnapshotWriter;
};
// Often used constants for number of free function type parameters.
@@ -2670,33 +2681,23 @@
return signature()->untag()->type_parameters();
}
- intptr_t NumTypeParameters() const {
- return signature()
- ->untag()
- ->packed_type_parameter_counts_
- .Read<UntaggedFunctionType::PackedNumTypeParameters>();
- }
-
+ // Returns the number of local type arguments for this function.
+ intptr_t NumTypeParameters() const;
// Return the cumulative number of type arguments in all parent functions.
intptr_t NumParentTypeArguments() const;
-
- // Return the cumulative number of type arguments in all parent functions and
- // own type arguments.
- intptr_t NumTypeArguments() const {
- return NumParentTypeArguments() + NumTypeParameters();
- }
+ // Return the cumulative number of type arguments for this function, including
+ // type arguments for all parent functions.
+ intptr_t NumTypeArguments() const;
+ // Return whether this function declares local type arguments.
+ bool IsGeneric() const;
+ // Returns whether any parent function of this function is generic.
+ bool HasGenericParent() const { return NumParentTypeArguments() > 0; }
// Return the type parameter declared at index.
TypeParameterPtr TypeParameterAt(
intptr_t index,
Nullability nullability = Nullability::kNonNullable) const;
- // Return true if this function declares type parameters.
- // Generic dispatchers only set the number without actual type parameters.
- bool IsGeneric() const { return NumTypeParameters() > 0; }
- // Return true if any parent function of this function is generic.
- bool HasGenericParent() const { return NumParentTypeArguments() > 0; }
-
// Not thread-safe; must be called in the main thread.
// Sets function's code and code's function.
void InstallOptimizedCode(const Code& code) const;
@@ -2881,13 +2882,14 @@
static const char* KindToCString(UntaggedFunction::Kind kind);
+ bool IsConstructor() const {
+ return kind() == UntaggedFunction::kConstructor;
+ }
bool IsGenerativeConstructor() const {
- return (kind() == UntaggedFunction::kConstructor) && !is_static();
+ return IsConstructor() && !is_static();
}
bool IsImplicitConstructor() const;
- bool IsFactory() const {
- return (kind() == UntaggedFunction::kConstructor) && is_static();
- }
+ bool IsFactory() const { return IsConstructor() && is_static(); }
bool HasThisParameter() const {
return IsDynamicFunction(/*allow_abstract=*/true) ||
@@ -2996,46 +2998,25 @@
return OFFSET_OF(UntaggedFunction, packed_fields_);
}
- intptr_t num_fixed_parameters() const {
- return signature()
- ->untag()
- ->packed_parameter_counts_
- .Read<UntaggedFunctionType::PackedNumFixedParameters>();
- }
-
- bool HasOptionalParameters() const {
- return signature()
- ->untag()
- ->packed_parameter_counts_
- .Read<UntaggedFunctionType::PackedNumOptionalParameters>() > 0;
- }
- bool HasOptionalNamedParameters() const {
- return HasOptionalParameters() &&
- signature()
- ->untag()
- ->packed_parameter_counts_
- .Read<UntaggedFunctionType::PackedHasNamedOptionalParameters>();
- }
+ // Returns the number of required positional parameters.
+ intptr_t num_fixed_parameters() const;
+ // Returns the number of optional parameters, whether positional or named.
+ bool HasOptionalParameters() const;
+ // Returns whether the function has optional named parameters.
+ bool HasOptionalNamedParameters() const;
+ // Returns whether the fuction has required named parameters.
bool HasRequiredNamedParameters() const;
- bool HasOptionalPositionalParameters() const {
- return HasOptionalParameters() && !HasOptionalNamedParameters();
- }
- intptr_t NumOptionalParameters() const {
- return signature()
- ->untag()
- ->packed_parameter_counts_
- .Read<UntaggedFunctionType::PackedNumOptionalParameters>();
- }
- intptr_t NumOptionalPositionalParameters() const {
- return HasOptionalPositionalParameters() ? NumOptionalParameters() : 0;
- }
-
- intptr_t NumOptionalNamedParameters() const {
- return HasOptionalNamedParameters() ? NumOptionalParameters() : 0;
- }
-
+ // Returns whether the function has optional positional parameters.
+ bool HasOptionalPositionalParameters() const;
+ // Returns the number of optional parameters, or 0 if none.
+ intptr_t NumOptionalParameters() const;
+ // Returns the number of optional positional parameters, or 0 if none.
+ intptr_t NumOptionalPositionalParameters() const;
+ // Returns the number of optional named parameters, or 0 if none.
+ intptr_t NumOptionalNamedParameters() const;
+ // Returns the total number of both required and optional parameters.
intptr_t NumParameters() const;
-
+ // Returns the number of implicit parameters, e.g., this for instance methods.
intptr_t NumImplicitParameters() const;
#if defined(DART_PRECOMPILED_RUNTIME)
@@ -3117,7 +3098,7 @@
bool ForceOptimize() const {
return IsFfiFromAddress() || IsFfiGetAddress() || IsFfiLoad() ||
IsFfiStore() || IsFfiTrampoline() || IsTypedDataViewFactory() ||
- IsUtf8Scan();
+ IsUtf8Scan() || IsGetNativeField();
}
bool CanBeInlined() const;
@@ -3449,6 +3430,11 @@
return kind == MethodRecognizer::kFfiGetAddress;
}
+ bool IsGetNativeField() const {
+ const auto kind = recognized_kind();
+ return kind == MethodRecognizer::kGetNativeField;
+ }
+
bool IsUtf8Scan() const {
const auto kind = recognized_kind();
return kind == MethodRecognizer::kUtf8DecoderScan;
@@ -3564,6 +3550,7 @@
static FunctionPtr NewClosureFunctionWithKind(UntaggedFunction::Kind kind,
const String& name,
const Function& parent,
+ bool is_static,
TokenPosition token_pos,
const Object& owner);
@@ -3816,7 +3803,6 @@
FINAL_HEAP_OBJECT_IMPLEMENTATION(Function, Object);
friend class Class;
- friend class SnapshotWriter;
friend class Parser; // For set_eval_script.
// UntaggedFunction::VisitFunctionPointers accesses the private constructor of
// Function.
@@ -3860,7 +3846,6 @@
FINAL_HEAP_OBJECT_IMPLEMENTATION(ClosureData, Object);
friend class Class;
friend class Function;
- friend class HeapProfiler;
friend class Precompiler; // To wrap parent functions in WSRs.
};
@@ -3901,7 +3886,6 @@
FINAL_HEAP_OBJECT_IMPLEMENTATION(FfiTrampolineData, Object);
friend class Class;
friend class Function;
- friend class HeapProfiler;
};
class Field : public Object {
@@ -4462,7 +4446,6 @@
FINAL_HEAP_OBJECT_IMPLEMENTATION(Field, Object);
friend class Class;
- friend class HeapProfiler;
friend class UntaggedField;
friend class FieldSerializationCluster;
friend class FieldDeserializationCluster;
@@ -6714,7 +6697,6 @@
FINAL_HEAP_OBJECT_IMPLEMENTATION(Code, Object);
friend class Class;
friend class CodeTestHelper;
- friend class SnapshotWriter;
friend class StubCode; // for set_object_pool
friend class Precompiler; // for set_object_pool
friend class FunctionSerializationCluster;
@@ -6767,8 +6749,6 @@
static const intptr_t kControllerIndex = 1;
// Expected context index of chained futures in recognized async functions.
// These are used to unwind async stacks.
- static const intptr_t kFutureTimeoutFutureIndex = 2;
- static const intptr_t kFutureWaitFutureIndex = 2;
static const intptr_t kIsSyncIndex = 2;
struct ArrayTraits {
@@ -6968,8 +6948,6 @@
void EnsureContains(const Smi& class_id, const Object& target) const;
ObjectPtr Lookup(const Smi& class_id) const;
- void SwitchToBareInstructions();
-
static intptr_t InstanceSize() {
return RoundedAllocationSize(sizeof(UntaggedMegamorphicCache));
}
@@ -7443,6 +7421,8 @@
static intptr_t NextFieldOffset() { return sizeof(UntaggedInstance); }
+ static intptr_t NativeFieldsOffset() { return sizeof(UntaggedObject); }
+
protected:
#ifndef PRODUCT
virtual void PrintSharedInstanceJSON(JSONObject* jsobj, bool ref) const;
@@ -7508,7 +7488,6 @@
friend class Pointer;
friend class DeferredObject;
friend class RegExp;
- friend class SnapshotWriter;
friend class StubCode;
friend class TypedDataView;
friend class InstanceSerializationCluster;
@@ -8443,61 +8422,90 @@
bool IsSubtypeOf(const FunctionType& other, Heap::Space space) const;
- intptr_t NumParameters() const;
-
- // Return the number of type arguments in enclosing signature.
- intptr_t NumParentTypeArguments() const {
- return untag()
+ static intptr_t NumParentTypeArgumentsOf(FunctionTypePtr ptr) {
+ return ptr->untag()
->packed_type_parameter_counts_.Read<PackedNumParentTypeArguments>();
}
+ // Return the number of type arguments in the enclosing signature.
+ intptr_t NumParentTypeArguments() const {
+ return NumParentTypeArgumentsOf(ptr());
+ }
void SetNumParentTypeArguments(intptr_t value) const;
- intptr_t NumTypeParameters() const {
- return PackedNumTypeParameters::decode(
- untag()->packed_type_parameter_counts_);
+ static intptr_t NumTypeParametersOf(FunctionTypePtr ptr) {
+ return ptr->untag()
+ ->packed_type_parameter_counts_.Read<PackedNumTypeParameters>();
}
+ intptr_t NumTypeParameters() const { return NumTypeParametersOf(ptr()); }
- intptr_t NumTypeArguments() const {
- return NumParentTypeArguments() + NumTypeParameters();
+ static intptr_t NumTypeArgumentsOf(FunctionTypePtr ptr) {
+ return NumTypeParametersOf(ptr) + NumParentTypeArgumentsOf(ptr);
}
+ intptr_t NumTypeArguments() const { return NumTypeArgumentsOf(ptr()); }
intptr_t num_implicit_parameters() const {
return untag()
->packed_parameter_counts_.Read<PackedNumImplicitParameters>();
}
void set_num_implicit_parameters(intptr_t value) const;
- intptr_t num_fixed_parameters() const {
- return untag()->packed_parameter_counts_.Read<PackedNumFixedParameters>();
+
+ static intptr_t NumFixedParametersOf(FunctionTypePtr ptr) {
+ return ptr->untag()
+ ->packed_parameter_counts_.Read<PackedNumFixedParameters>();
}
+ intptr_t num_fixed_parameters() const { return NumFixedParametersOf(ptr()); }
void set_num_fixed_parameters(intptr_t value) const;
- bool HasOptionalParameters() const {
- return untag()
+ static bool HasOptionalParameters(FunctionTypePtr ptr) {
+ return ptr->untag()
->packed_parameter_counts_.Read<PackedNumOptionalParameters>() >
0;
}
+ bool HasOptionalParameters() const { return HasOptionalParameters(ptr()); }
+
+ static bool HasOptionalNamedParameters(FunctionTypePtr ptr) {
+ return ptr->untag()
+ ->packed_parameter_counts_.Read<PackedHasNamedOptionalParameters>();
+ }
bool HasOptionalNamedParameters() const {
- return HasOptionalParameters() &&
- untag()
- ->packed_parameter_counts_
- .Read<PackedHasNamedOptionalParameters>();
+ return HasOptionalNamedParameters(ptr());
+ }
+ bool HasRequiredNamedParameters() const;
+
+ static bool HasOptionalPositionalParameters(FunctionTypePtr ptr) {
+ return !HasOptionalNamedParameters(ptr) && HasOptionalParameters(ptr);
}
bool HasOptionalPositionalParameters() const {
- return HasOptionalParameters() && !HasOptionalNamedParameters();
+ return HasOptionalPositionalParameters(ptr());
+ }
+
+ static intptr_t NumOptionalParametersOf(FunctionTypePtr ptr) {
+ return ptr->untag()
+ ->packed_parameter_counts_.Read<PackedNumOptionalParameters>();
}
intptr_t NumOptionalParameters() const {
- return untag()
- ->packed_parameter_counts_.Read<PackedNumOptionalParameters>();
+ return NumOptionalParametersOf(ptr());
}
void SetNumOptionalParameters(intptr_t num_optional_parameters,
bool are_optional_positional) const;
+ static intptr_t NumOptionalPositionalParametersOf(FunctionTypePtr ptr) {
+ return HasOptionalNamedParameters(ptr) ? 0 : NumOptionalParametersOf(ptr);
+ }
intptr_t NumOptionalPositionalParameters() const {
- return HasOptionalPositionalParameters() ? NumOptionalParameters() : 0;
+ return NumOptionalPositionalParametersOf(ptr());
}
- intptr_t NumOptionalNamedParameters() const {
- return HasOptionalNamedParameters() ? NumOptionalParameters() : 0;
+ static intptr_t NumOptionalNamedParametersOf(FunctionTypePtr ptr) {
+ return HasOptionalNamedParameters(ptr) ? NumOptionalParametersOf(ptr) : 0;
}
+ intptr_t NumOptionalNamedParameters() const {
+ return NumOptionalNamedParametersOf(ptr());
+ }
+
+ static intptr_t NumParametersOf(FunctionTypePtr ptr) {
+ return NumFixedParametersOf(ptr) + NumOptionalParametersOf(ptr);
+ }
+ intptr_t NumParameters() const { return NumParametersOf(ptr()); }
uint32_t packed_parameter_counts() const {
return untag()->packed_parameter_counts_;
@@ -8592,7 +8600,10 @@
TrailPtr trail = nullptr) const;
// Return true if this function type declares type parameters.
- bool IsGeneric() const { return NumTypeParameters() > 0; }
+ static bool IsGeneric(FunctionTypePtr ptr) {
+ return ptr->untag()->type_parameters() != TypeParameters::null();
+ }
+ bool IsGeneric() const { return IsGeneric(ptr()); }
// Return true if any enclosing signature of this signature is generic.
bool HasGenericParent() const { return NumParentTypeArguments() > 0; }
@@ -8980,6 +8991,11 @@
static ClassPtr Class();
static intptr_t Value(const SmiPtr raw_smi) { return RawSmiValue(raw_smi); }
+#if defined(DART_COMPRESSED_POINTERS)
+ static intptr_t Value(const CompressedSmiPtr raw_smi) {
+ return Smi::Value(static_cast<SmiPtr>(raw_smi.DecompressSmi()));
+ }
+#endif
static intptr_t RawValue(intptr_t value) {
return static_cast<intptr_t>(New(value));
@@ -9055,6 +9071,7 @@
protected:
// Only Integer::NewXXX is allowed to call Mint::NewXXX directly.
friend class Integer;
+ friend class MintMessageDeserializationCluster;
static MintPtr New(int64_t value, Heap::Space space = Heap::kNew);
@@ -9107,6 +9124,14 @@
friend class Number;
};
+// TODO(http://dartbug.com/46716): Recognize Symbol in the VM.
+class Symbol : public AllStatic {
+ public:
+ static bool IsSymbolCid(Thread* thread, classid_t class_id);
+
+ static uint32_t CanonicalizeHash(Thread* thread, const Instance& instance);
+};
+
// String may not be '\0' terminated.
class String : public Instance {
public:
@@ -9457,14 +9482,6 @@
ASSERT(hash_set == value);
}
- template <typename HandleType, typename ElementType, typename CallbackType>
- static void ReadFromImpl(SnapshotReader* reader,
- String* str_obj,
- intptr_t len,
- intptr_t tags,
- CallbackType new_symbol,
- Snapshot::Kind kind);
-
FINAL_HEAP_OBJECT_IMPLEMENTATION(String, Instance);
friend class Class;
@@ -9634,20 +9651,14 @@
return &str.UnsafeMutableNonPointer(untag(str)->data())[0];
}
- static OneByteStringPtr ReadFrom(SnapshotReader* reader,
- intptr_t object_id,
- intptr_t tags,
- Snapshot::Kind kind,
- bool as_reference);
-
friend class Class;
friend class ExternalOneByteString;
friend class ImageWriter;
- friend class SnapshotReader;
friend class String;
friend class StringHasher;
friend class Symbols;
friend class Utf8;
+ friend class OneByteStringMessageSerializationCluster;
};
class TwoByteString : public AllStatic {
@@ -9760,18 +9771,12 @@
return &str.UnsafeMutableNonPointer(untag(str)->data())[0];
}
- static TwoByteStringPtr ReadFrom(SnapshotReader* reader,
- intptr_t object_id,
- intptr_t tags,
- Snapshot::Kind kind,
- bool as_reference);
-
friend class Class;
friend class ImageWriter;
- friend class SnapshotReader;
friend class String;
friend class StringHasher;
friend class Symbols;
+ friend class TwoByteStringMessageSerializationCluster;
};
class ExternalOneByteString : public AllStatic {
@@ -9855,12 +9860,6 @@
Dart_WeakPersistentHandle handle,
void* peer);
- static ExternalOneByteStringPtr ReadFrom(SnapshotReader* reader,
- intptr_t object_id,
- intptr_t tags,
- Snapshot::Kind kind,
- bool as_reference);
-
static intptr_t NextFieldOffset() {
// Indicates this class cannot be extended by dart code.
return -kWordSize;
@@ -9869,7 +9868,6 @@
friend class Class;
friend class String;
friend class StringHasher;
- friend class SnapshotReader;
friend class Symbols;
friend class Utf8;
};
@@ -9951,12 +9949,6 @@
Dart_WeakPersistentHandle handle,
void* peer);
- static ExternalTwoByteStringPtr ReadFrom(SnapshotReader* reader,
- intptr_t object_id,
- intptr_t tags,
- Snapshot::Kind kind,
- bool as_reference);
-
static intptr_t NextFieldOffset() {
// Indicates this class cannot be extended by dart code.
return -kWordSize;
@@ -9965,7 +9957,6 @@
friend class Class;
friend class String;
friend class StringHasher;
- friend class SnapshotReader;
friend class Symbols;
};
@@ -10201,6 +10192,7 @@
friend class ImmutableArray;
friend class Object;
friend class String;
+ friend class MessageDeserializer;
};
class ImmutableArray : public AllStatic {
@@ -10211,12 +10203,6 @@
static ImmutableArrayPtr New(intptr_t len, Heap::Space space = Heap::kNew);
- static ImmutableArrayPtr ReadFrom(SnapshotReader* reader,
- intptr_t object_id,
- intptr_t tags,
- Snapshot::Kind kind,
- bool as_reference);
-
static const ClassId kClassId = kImmutableArrayCid;
static intptr_t InstanceSize() { return Array::InstanceSize(); }
@@ -10874,8 +10860,6 @@
return OFFSET_OF(UntaggedPointer, type_arguments_);
}
- static intptr_t NextFieldOffset() { return sizeof(UntaggedPointer); }
-
static const intptr_t kNativeTypeArgPos = 0;
// Fetches the NativeType type argument.
@@ -10885,7 +10869,7 @@
}
private:
- HEAP_OBJECT_IMPLEMENTATION(Pointer, Instance);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(Pointer, Instance);
friend class Class;
};
@@ -11072,6 +11056,113 @@
friend class LinkedHashMapDeserializationCluster;
};
+class LinkedHashSet : public LinkedHashBase {
+ public:
+ static intptr_t InstanceSize() {
+ return RoundedAllocationSize(sizeof(UntaggedLinkedHashSet));
+ }
+
+ // Allocates a set with some default capacity, just like "new Set()".
+ static LinkedHashSetPtr NewDefault(Heap::Space space = Heap::kNew);
+ static LinkedHashSetPtr New(const Array& data,
+ const TypedData& index,
+ intptr_t hash_mask,
+ intptr_t used_data,
+ intptr_t deleted_keys,
+ Heap::Space space = Heap::kNew);
+
+ virtual TypeArgumentsPtr GetTypeArguments() const {
+ return untag()->type_arguments();
+ }
+ virtual void SetTypeArguments(const TypeArguments& value) const {
+ ASSERT(value.IsNull() ||
+ ((value.Length() >= 1) &&
+ value.IsInstantiated() /*&& value.IsCanonical()*/));
+ // TODO(asiva): Values read from a message snapshot are not properly marked
+ // as canonical. See for example tests/isolate/message3_test.dart.
+ untag()->set_type_arguments(value.ptr());
+ }
+
+ TypedDataPtr index() const { return untag()->index(); }
+ void SetIndex(const TypedData& value) const {
+ ASSERT(!value.IsNull());
+ untag()->set_index(value.ptr());
+ }
+
+ ArrayPtr data() const { return untag()->data(); }
+ void SetData(const Array& value) const { untag()->set_data(value.ptr()); }
+
+ SmiPtr hash_mask() const { return untag()->hash_mask(); }
+ void SetHashMask(intptr_t value) const {
+ untag()->set_hash_mask(Smi::New(value));
+ }
+
+ SmiPtr used_data() const { return untag()->used_data(); }
+ void SetUsedData(intptr_t value) const {
+ untag()->set_used_data(Smi::New(value));
+ }
+
+ SmiPtr deleted_keys() const { return untag()->deleted_keys(); }
+ void SetDeletedKeys(intptr_t value) const {
+ untag()->set_deleted_keys(Smi::New(value));
+ }
+
+ intptr_t Length() const {
+ // The map may be uninitialized.
+ if (untag()->used_data() == Object::null()) return 0;
+ if (untag()->deleted_keys() == Object::null()) return 0;
+
+ intptr_t used = Smi::Value(untag()->used_data());
+ intptr_t deleted = Smi::Value(untag()->deleted_keys());
+ return used - deleted;
+ }
+
+ // This iterator differs somewhat from its Dart counterpart (_CompactIterator
+ // in runtime/lib/compact_hash.dart):
+ // - There are no checks for concurrent modifications.
+ // - Accessing a key or value before the first call to MoveNext and after
+ // MoveNext returns false will result in crashes.
+ class Iterator : ValueObject {
+ public:
+ explicit Iterator(const LinkedHashSet& set)
+ : data_(Array::Handle(set.data())),
+ scratch_(Object::Handle()),
+ offset_(-1),
+ length_(Smi::Value(set.used_data())) {}
+
+ bool MoveNext() {
+ while (true) {
+ offset_++;
+ if (offset_ >= length_) {
+ return false;
+ }
+ scratch_ = data_.At(offset_);
+ if (scratch_.ptr() != data_.ptr()) {
+ // Slot is not deleted (self-reference indicates deletion).
+ return true;
+ }
+ }
+ }
+
+ ObjectPtr CurrentKey() const { return data_.At(offset_); }
+
+ private:
+ const Array& data_;
+ Object& scratch_;
+ intptr_t offset_;
+ const intptr_t length_;
+ };
+
+ private:
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(LinkedHashSet, LinkedHashBase);
+
+ // Allocate a set, but leave all fields set to null.
+ // Used during deserialization (since set might contain itself as key/value).
+ static LinkedHashSetPtr NewUninitialized(Heap::Space space = Heap::kNew);
+
+ friend class Class;
+};
+
class Closure : public Instance {
public:
#if defined(DART_PRECOMPILED_RUNTIME)
@@ -11118,27 +11209,23 @@
static intptr_t function_offset() {
return OFFSET_OF(UntaggedClosure, function_);
}
-
-#if defined(DART_PRECOMPILER)
- FunctionTypePtr signature() const {
- return FunctionType::RawCast(WeakSerializationReference::Unwrap(
- untag()->function()->untag()->signature()));
+ static FunctionPtr FunctionOf(ClosurePtr closure) {
+ return closure.untag()->function();
}
-#else
- FunctionTypePtr signature() const {
- return untag()->function()->untag()->signature();
- }
-#endif
ContextPtr context() const { return untag()->context(); }
static intptr_t context_offset() {
return OFFSET_OF(UntaggedClosure, context_);
}
+ static ContextPtr ContextOf(ClosurePtr closure) {
+ return closure.untag()->context();
+ }
- bool IsGeneric(Thread* thread) const { return NumTypeParameters(thread) > 0; }
- intptr_t NumTypeParameters(Thread* thread) const;
- // No need for num_parent_type_arguments, as a closure is always closed
- // over its parents type parameters (i.e., function_type_parameters() above).
+ // Returns whether the closure is generic, that is, it has a generic closure
+ // function and no delayed type arguments.
+ bool IsGeneric() const {
+ return delayed_type_arguments() == Object::empty_type_arguments().ptr();
+ }
SmiPtr hash() const { return untag()->hash(); }
static intptr_t hash_offset() { return OFFSET_OF(UntaggedClosure, hash_); }
@@ -11856,17 +11943,6 @@
const Object& target) {
ASSERT(target.IsNull() || target.IsFunction() || target.IsSmi());
array.SetAt((index * kEntryLength) + kClassIdIndex, class_id);
-#if defined(DART_PRECOMPILED_RUNTIME)
- if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
- if (target.IsFunction()) {
- const auto& function = Function::Cast(target);
- const auto& entry_point = Smi::Handle(
- Smi::FromAlignedAddress(Code::EntryPointOf(function.CurrentCode())));
- array.SetAt((index * kEntryLength) + kTargetFunctionIndex, entry_point);
- return;
- }
- }
-#endif // defined(DART_PRECOMPILED_RUNTIME)
array.SetAt((index * kEntryLength) + kTargetFunctionIndex, target);
}
diff --git a/runtime/vm/object_graph.cc b/runtime/vm/object_graph.cc
index 1bd42fa..e05b2ef 100644
--- a/runtime/vm/object_graph.cc
+++ b/runtime/vm/object_graph.cc
@@ -944,6 +944,10 @@
writer_->WriteUnsigned(kLengthData);
writer_->WriteUnsigned(
Smi::Value(static_cast<LinkedHashMapPtr>(obj)->untag()->used_data()));
+ } else if (cid == kLinkedHashSetCid) {
+ writer_->WriteUnsigned(kLengthData);
+ writer_->WriteUnsigned(
+ Smi::Value(static_cast<LinkedHashSetPtr>(obj)->untag()->used_data()));
} else if (cid == kObjectPoolCid) {
writer_->WriteUnsigned(kLengthData);
writer_->WriteUnsigned(static_cast<ObjectPoolPtr>(obj)->untag()->length_);
@@ -1158,11 +1162,10 @@
intptr_t field_count = 0;
intptr_t min_offset = kIntptrMax;
- for (intptr_t j = 0; OffsetsTable::offsets_table[j].class_id != -1;
- j++) {
- if (OffsetsTable::offsets_table[j].class_id == cid) {
+ for (const auto& entry : OffsetsTable::offsets_table()) {
+ if (entry.class_id == cid) {
field_count++;
- intptr_t offset = OffsetsTable::offsets_table[j].offset;
+ intptr_t offset = entry.offset;
min_offset = Utils::Minimum(min_offset, offset);
}
}
@@ -1183,16 +1186,15 @@
}
WriteUnsigned(field_count);
- for (intptr_t j = 0; OffsetsTable::offsets_table[j].class_id != -1;
- j++) {
- if (OffsetsTable::offsets_table[j].class_id == cid) {
+ for (const auto& entry : OffsetsTable::offsets_table()) {
+ if (entry.class_id == cid) {
intptr_t flags = 1; // Strong.
WriteUnsigned(flags);
- intptr_t offset = OffsetsTable::offsets_table[j].offset;
+ intptr_t offset = entry.offset;
intptr_t index = (offset - min_offset) / kCompressedWordSize;
ASSERT(index >= 0);
WriteUnsigned(index);
- WriteUtf8(OffsetsTable::offsets_table[j].field_name);
+ WriteUtf8(entry.field_name);
WriteUtf8(""); // Reserved
}
}
@@ -1308,6 +1310,7 @@
case kInstructionsSectionCid:
case kInstructionsTableCid:
case kLinkedHashMapCid:
+ case kLinkedHashSetCid:
case kMintCid:
case kNeverCid:
case kSentinelCid:
diff --git a/runtime/vm/object_graph_copy.cc b/runtime/vm/object_graph_copy.cc
new file mode 100644
index 0000000..7b9189f
--- /dev/null
+++ b/runtime/vm/object_graph_copy.cc
@@ -0,0 +1,1680 @@
+// 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.
+
+#include "vm/object_graph_copy.h"
+#include "vm/dart_api_state.h"
+#include "vm/flags.h"
+#include "vm/heap/weak_table.h"
+#include "vm/longjump.h"
+#include "vm/object.h"
+#include "vm/snapshot.h"
+#include "vm/symbols.h"
+
+#define Z zone_
+
+// The list here contains two kinds of classes of objects
+// * objects that will be shared and we will therefore never need to copy
+// * objects that user object graphs should never reference
+#define FOR_UNSUPPORTED_CLASSES(V) \
+ V(AbstractType) \
+ V(ApiError) \
+ V(Bool) \
+ V(CallSiteData) \
+ V(Capability) \
+ V(Class) \
+ V(ClosureData) \
+ V(Code) \
+ V(CodeSourceMap) \
+ V(CompressedStackMaps) \
+ V(Context) \
+ V(ContextScope) \
+ V(DynamicLibrary) \
+ V(Error) \
+ V(ExceptionHandlers) \
+ V(FfiTrampolineData) \
+ V(Field) \
+ V(Function) \
+ V(FunctionType) \
+ V(FutureOr) \
+ V(ICData) \
+ V(Instance) \
+ V(Instructions) \
+ V(InstructionsSection) \
+ V(InstructionsTable) \
+ V(Int32x4) \
+ V(Integer) \
+ V(KernelProgramInfo) \
+ V(LanguageError) \
+ V(Library) \
+ V(LibraryPrefix) \
+ V(LoadingUnit) \
+ V(LocalVarDescriptors) \
+ V(MegamorphicCache) \
+ V(Mint) \
+ V(MirrorReference) \
+ V(MonomorphicSmiableCall) \
+ V(Namespace) \
+ V(Number) \
+ V(ObjectPool) \
+ V(PatchClass) \
+ V(PcDescriptors) \
+ V(Pointer) \
+ V(ReceivePort) \
+ V(RegExp) \
+ V(Script) \
+ V(Sentinel) \
+ V(SendPort) \
+ V(SingleTargetCache) \
+ V(Smi) \
+ V(StackTrace) \
+ V(SubtypeTestCache) \
+ V(Type) \
+ V(TypeArguments) \
+ V(TypeParameter) \
+ V(TypeParameters) \
+ V(TypeRef) \
+ V(TypedDataBase) \
+ V(UnhandledException) \
+ V(UnlinkedCall) \
+ V(UnwindError) \
+ V(UserTag) \
+ V(WeakProperty) \
+ V(WeakSerializationReference)
+
+namespace dart {
+
+DEFINE_FLAG(bool,
+ enable_fast_object_copy,
+ true,
+ "Enable fast path for fast object copy.");
+DEFINE_FLAG(bool,
+ gc_on_foc_slow_path,
+ false,
+ "Cause a GC when falling off the fast path for fast object copy.");
+
+const char* kFastAllocationFailed = "fast allocation failed";
+
+struct PtrTypes {
+ using Object = ObjectPtr;
+ static const dart::UntaggedObject* UntagObject(Object arg) {
+ return arg.untag();
+ }
+ static const dart::ObjectPtr GetObjectPtr(Object arg) { return arg; }
+ static const dart::Object& HandlifyObject(ObjectPtr arg) {
+ return dart::Object::Handle(arg);
+ }
+
+#define DO(V) \
+ using V = V##Ptr; \
+ static Untagged##V* Untag##V(V##Ptr arg) { return arg.untag(); } \
+ static V##Ptr Get##V##Ptr(V##Ptr arg) { return arg; } \
+ static V##Ptr Cast##V(ObjectPtr arg) { return dart::V::RawCast(arg); }
+ CLASS_LIST_FOR_HANDLES(DO)
+#undef DO
+};
+
+struct HandleTypes {
+ using Object = const dart::Object&;
+ static const dart::UntaggedObject* UntagObject(Object arg) {
+ return arg.ptr().untag();
+ }
+ static dart::ObjectPtr GetObjectPtr(Object arg) { return arg.ptr(); }
+ static Object HandlifyObject(Object arg) { return arg; }
+
+#define DO(V) \
+ using V = const dart::V&; \
+ static Untagged##V* Untag##V(V arg) { return arg.ptr().untag(); } \
+ static V##Ptr Get##V##Ptr(V arg) { return arg.ptr(); } \
+ static V Cast##V(const dart::Object& arg) { return dart::V::Cast(arg); }
+ CLASS_LIST_FOR_HANDLES(DO)
+#undef DO
+};
+
+DART_FORCE_INLINE
+static ObjectPtr Marker() {
+ return Object::unknown_constant().ptr();
+}
+
+DART_FORCE_INLINE
+static bool CanShareObject(uword tags) {
+ if ((tags & UntaggedObject::CanonicalBit::mask_in_place()) != 0) {
+ return true;
+ }
+ const auto cid = UntaggedObject::ClassIdTag::decode(tags);
+ if (cid == kOneByteStringCid) return true;
+ if (cid == kTwoByteStringCid) return true;
+ if (cid == kExternalOneByteStringCid) return true;
+ if (cid == kExternalTwoByteStringCid) return true;
+ if (cid == kMintCid) return true;
+ if (cid == kImmutableArrayCid) return true;
+ if (cid == kNeverCid) return true;
+ if (cid == kSentinelCid) return true;
+#if defined(DART_PRECOMPILED_RUNTIME)
+ // In JIT mode we have field guards enabled which means
+ // double/float32x4/float64x2 boxes can be mutable and we therefore cannot
+ // share them.
+ if (cid == kDoubleCid || cid == kFloat32x4Cid || cid == kFloat64x2Cid) {
+ return true;
+ }
+#endif
+ if (cid == kInt32x4Cid) return true; // No field guards here.
+ if (cid == kSendPortCid) return true;
+ if (cid == kCapabilityCid) return true;
+ if (cid == kRegExpCid) return true;
+
+ return false;
+}
+
+// Whether executing `get:hashCode` (possibly in a different isolate) on an
+// object with the given [tags] might return a different answer than the source
+// object (if copying is needed) or on the same object (if the object is
+// shared).
+DART_FORCE_INLINE
+static bool MightNeedReHashing(ObjectPtr object) {
+ const uword tags = TagsFromUntaggedObject(object.untag());
+ const auto cid = UntaggedObject::ClassIdTag::decode(tags);
+ // These use structural hash codes and will therefore always result in the
+ // same hash codes.
+ if (cid == kOneByteStringCid) return false;
+ if (cid == kTwoByteStringCid) return false;
+ if (cid == kExternalOneByteStringCid) return false;
+ if (cid == kExternalTwoByteStringCid) return false;
+ if (cid == kMintCid) return false;
+ if (cid == kDoubleCid) return false;
+ if (cid == kBoolCid) return false;
+ if (cid == kSendPortCid) return false;
+ if (cid == kCapabilityCid) return false;
+ if (cid == kNullCid) return false;
+
+ // These are shared and use identity hash codes. If they are used as a key in
+ // a map or a value in a set, they will already have the identity hash code
+ // set.
+ if (cid == kImmutableArrayCid) return false;
+ if (cid == kRegExpCid) return false;
+ if (cid == kInt32x4Cid) return false;
+
+ // We copy those (instead of sharing them) - see [CanShareObjct]. They rely
+ // on the default hashCode implementation which uses identity hash codes
+ // (instead of structural hash code).
+ if (cid == kFloat32x4Cid || cid == kFloat64x2Cid) {
+ return !kDartPrecompiledRuntime;
+ }
+
+ // If the [tags] indicates this is a canonical object we'll share it instead
+ // of copying it. That would suggest we don't have to re-hash maps/sets
+ // containing this object on the receiver side.
+ //
+ // Though the object can be a constant of a user-defined class with a
+ // custom hash code that is misbehaving (e.g one that depends on global field
+ // state, ...). To be on the safe side we'll force re-hashing if such objects
+ // are encountered in maps/sets.
+ //
+ // => We might want to consider changing the implementation to avoid rehashing
+ // in such cases in the future and disambiguate the documentation.
+ return true;
+}
+
+DART_FORCE_INLINE
+uword TagsFromUntaggedObject(UntaggedObject* obj) {
+ return obj->tags_;
+}
+
+DART_FORCE_INLINE
+void SetNewSpaceTaggingWord(ObjectPtr to, classid_t cid, uint32_t size) {
+ uword tags = 0;
+
+ tags = UntaggedObject::SizeTag::update(size, tags);
+ tags = UntaggedObject::ClassIdTag::update(cid, tags);
+ tags = UntaggedObject::OldBit::update(false, tags);
+ tags = UntaggedObject::OldAndNotMarkedBit::update(false, tags);
+ tags = UntaggedObject::OldAndNotRememberedBit::update(false, tags);
+ tags = UntaggedObject::CanonicalBit::update(false, tags);
+ tags = UntaggedObject::NewBit::update(true, tags);
+#if defined(HASH_IN_OBJECT_HEADER)
+ tags = UntaggedObject::HashTag::update(0, tags);
+#endif
+ to.untag()->tags_ = tags;
+}
+
+DART_FORCE_INLINE
+ObjectPtr AllocateObject(intptr_t cid, intptr_t size) {
+#if defined(DART_COMPRESSED_POINTERS)
+ const bool compressed = true;
+#else
+ const bool compressed = false;
+#endif
+ return Object::Allocate(cid, size, Heap::kNew, compressed);
+}
+
+DART_FORCE_INLINE
+void UpdateLengthField(intptr_t cid, ObjectPtr from, ObjectPtr to) {
+ // We share these objects - never copy them.
+ ASSERT(!IsStringClassId(cid));
+ ASSERT(cid != kImmutableArrayCid);
+
+ // We update any in-heap variable sized object with the length to keep the
+ // length and the size in the object header in-sync for the GC.
+ if (cid == kArrayCid) {
+ static_cast<UntaggedArray*>(to.untag())->length_ =
+ static_cast<UntaggedArray*>(from.untag())->length_;
+ } else if (IsTypedDataClassId(cid)) {
+ static_cast<UntaggedTypedDataBase*>(to.untag())->length_ =
+ static_cast<UntaggedTypedDataBase*>(from.untag())->length_;
+ }
+}
+
+void InitializeExternalTypedData(intptr_t cid,
+ ExternalTypedDataPtr from,
+ ExternalTypedDataPtr to) {
+ auto raw_from = from.untag();
+ auto raw_to = to.untag();
+ const intptr_t length =
+ TypedData::ElementSizeInBytes(cid) * Smi::Value(raw_from->length_);
+
+ auto buffer = static_cast<uint8_t*>(malloc(length));
+ memmove(buffer, raw_from->data_, length);
+ raw_to->length_ = raw_from->length_;
+ raw_to->data_ = buffer;
+}
+
+void InitializeTypedDataView(TypedDataViewPtr obj) {
+ obj.untag()->typed_data_ = TypedDataBase::null();
+ obj.untag()->offset_in_bytes_ = 0;
+ obj.untag()->length_ = 0;
+}
+
+void FreeExternalTypedData(void* isolate_callback_data, void* buffer) {
+ free(buffer);
+}
+
+void FreeTransferablePeer(void* isolate_callback_data, void* peer) {
+ delete static_cast<TransferableTypedDataPeer*>(peer);
+}
+
+class ForwardMapBase {
+ public:
+ explicit ForwardMapBase(Thread* thread)
+ : thread_(thread), zone_(thread->zone()), isolate_(thread->isolate()) {}
+
+ protected:
+ friend class ObjectGraphCopier;
+
+ intptr_t GetObjectId(ObjectPtr object) {
+ if (object->IsNewObject()) {
+ return isolate_->forward_table_new()->GetValueExclusive(object);
+ } else {
+ return isolate_->forward_table_old()->GetValueExclusive(object);
+ }
+ }
+ void SetObjectId(ObjectPtr object, intptr_t id) {
+ if (object->IsNewObject()) {
+ isolate_->forward_table_new()->SetValueExclusive(object, id);
+ } else {
+ isolate_->forward_table_old()->SetValueExclusive(object, id);
+ }
+ }
+
+ void FinalizeTransferable(const TransferableTypedData& from,
+ const TransferableTypedData& to) {
+ // Get the old peer.
+ auto fpeer = static_cast<TransferableTypedDataPeer*>(
+ thread_->heap()->GetPeer(from.ptr()));
+ ASSERT(fpeer != nullptr && fpeer->data() != nullptr);
+ const intptr_t length = fpeer->length();
+
+ // Allocate new peer object with (data, length).
+ auto tpeer = new TransferableTypedDataPeer(fpeer->data(), length);
+ thread_->heap()->SetPeer(to.ptr(), tpeer);
+
+ // Move the handle itself to the new object.
+ fpeer->handle()->EnsureFreedExternal(thread_->isolate_group());
+ tpeer->set_handle(FinalizablePersistentHandle::New(
+ thread_->isolate_group(), to, tpeer, FreeTransferablePeer, length,
+ /*auto_delete=*/true));
+ fpeer->ClearData();
+ }
+
+ void FinalizeExternalTypedData(const ExternalTypedData& to) {
+ to.AddFinalizer(to.DataAddr(0), &FreeExternalTypedData, to.LengthInBytes());
+ }
+
+ Thread* thread_;
+ Zone* zone_;
+ Isolate* isolate_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ForwardMapBase);
+};
+
+class FastForwardMap : public ForwardMapBase {
+ public:
+ explicit FastForwardMap(Thread* thread)
+ : ForwardMapBase(thread),
+ raw_from_to_(thread->zone(), 20),
+ raw_transferables_from_to_(thread->zone(), 0),
+ raw_objects_to_rehash_(thread->zone(), 0) {
+ raw_from_to_.Resize(2);
+ raw_from_to_[0] = Object::null();
+ raw_from_to_[1] = Object::null();
+ fill_cursor_ = 2;
+ }
+
+ ObjectPtr ForwardedObject(ObjectPtr object) {
+ const intptr_t id = GetObjectId(object);
+ if (id == 0) return Marker();
+ return raw_from_to_[id + 1];
+ }
+
+ void Insert(ObjectPtr from, ObjectPtr to) {
+ ASSERT(ForwardedObject(from) == Marker());
+ ASSERT(raw_from_to_.length() == raw_from_to_.length());
+ const auto id = raw_from_to_.length();
+ SetObjectId(from, id);
+ raw_from_to_.Resize(id + 2);
+ raw_from_to_[id] = from;
+ raw_from_to_[id + 1] = to;
+ }
+
+ void AddTransferable(TransferableTypedDataPtr from,
+ TransferableTypedDataPtr to) {
+ raw_transferables_from_to_.Add(from);
+ raw_transferables_from_to_.Add(to);
+ }
+ void AddExternalTypedData(ExternalTypedDataPtr to) {
+ raw_external_typed_data_to_.Add(to);
+ }
+
+ void AddObjectToRehash(ObjectPtr to) { raw_objects_to_rehash_.Add(to); }
+
+ private:
+ friend class FastObjectCopy;
+ friend class ObjectGraphCopier;
+
+ GrowableArray<ObjectPtr> raw_from_to_;
+ GrowableArray<TransferableTypedDataPtr> raw_transferables_from_to_;
+ GrowableArray<ExternalTypedDataPtr> raw_external_typed_data_to_;
+ GrowableArray<ObjectPtr> raw_objects_to_rehash_;
+ intptr_t fill_cursor_ = 0;
+
+ DISALLOW_COPY_AND_ASSIGN(FastForwardMap);
+};
+
+class SlowForwardMap : public ForwardMapBase {
+ public:
+ explicit SlowForwardMap(Thread* thread)
+ : ForwardMapBase(thread),
+ from_to_(thread->zone(), 20),
+ transferables_from_to_(thread->zone(), 0) {
+ from_to_.Resize(2);
+ from_to_[0] = &Object::null_object();
+ from_to_[1] = &Object::null_object();
+ fill_cursor_ = 2;
+ }
+
+ ObjectPtr ForwardedObject(ObjectPtr object) {
+ const intptr_t id = GetObjectId(object);
+ if (id == 0) return Marker();
+ return from_to_[id + 1]->ptr();
+ }
+
+ void Insert(ObjectPtr from, ObjectPtr to) {
+ ASSERT(ForwardedObject(from) == Marker());
+ const auto id = from_to_.length();
+ SetObjectId(from, id);
+ from_to_.Resize(id + 2);
+ from_to_[id] = &Object::Handle(Z, from);
+ from_to_[id + 1] = &Object::Handle(Z, to);
+ }
+
+ void AddTransferable(const TransferableTypedData& from,
+ const TransferableTypedData& to) {
+ transferables_from_to_.Add(&TransferableTypedData::Handle(from.ptr()));
+ transferables_from_to_.Add(&TransferableTypedData::Handle(to.ptr()));
+ }
+
+ void AddExternalTypedData(ExternalTypedDataPtr to) {
+ external_typed_data_.Add(&ExternalTypedData::Handle(to));
+ }
+
+ void AddObjectToRehash(const Object& to) {
+ objects_to_rehash_.Add(&Object::Handle(to.ptr()));
+ }
+
+ void FinalizeTransferables() {
+ for (intptr_t i = 0; i < transferables_from_to_.length(); i += 2) {
+ auto from = transferables_from_to_[i];
+ auto to = transferables_from_to_[i + 1];
+ FinalizeTransferable(*from, *to);
+ }
+ }
+
+ void FinalizeExternalTypedData() {
+ for (intptr_t i = 0; i < external_typed_data_.length(); i++) {
+ auto to = external_typed_data_[i];
+ ForwardMapBase::FinalizeExternalTypedData(*to);
+ }
+ }
+
+ private:
+ friend class SlowObjectCopy;
+ friend class ObjectGraphCopier;
+
+ GrowableArray<const Object*> from_to_;
+ GrowableArray<const TransferableTypedData*> transferables_from_to_;
+ GrowableArray<const ExternalTypedData*> external_typed_data_;
+ GrowableArray<const Object*> objects_to_rehash_;
+ intptr_t fill_cursor_ = 0;
+
+ DISALLOW_COPY_AND_ASSIGN(SlowForwardMap);
+};
+
+class ObjectCopyBase {
+ public:
+ explicit ObjectCopyBase(Thread* thread)
+ : thread_(thread),
+ heap_base_(thread->heap_base()),
+ zone_(thread->zone()),
+ heap_(thread->isolate_group()->heap()),
+ class_table_(thread->isolate_group()->class_table()),
+ new_space_(heap_->new_space()),
+ tmp_(Object::Handle(thread->zone())) {}
+ ~ObjectCopyBase() {}
+
+ protected:
+ static ObjectPtr LoadPointer(ObjectPtr src, intptr_t offset) {
+ return src.untag()->LoadPointer(reinterpret_cast<ObjectPtr*>(
+ reinterpret_cast<uint8_t*>(src.untag()) + offset));
+ }
+ static CompressedObjectPtr LoadCompressedPointer(ObjectPtr src,
+ intptr_t offset) {
+ return src.untag()->LoadPointer(reinterpret_cast<CompressedObjectPtr*>(
+ reinterpret_cast<uint8_t*>(src.untag()) + offset));
+ }
+ static compressed_uword LoadCompressedNonPointerWord(ObjectPtr src,
+ intptr_t offset) {
+ return *reinterpret_cast<compressed_uword*>(
+ reinterpret_cast<uint8_t*>(src.untag()) + offset);
+ }
+ static void StorePointerBarrier(ObjectPtr obj,
+ intptr_t offset,
+ ObjectPtr value) {
+ obj.untag()->StorePointer(
+ reinterpret_cast<ObjectPtr*>(reinterpret_cast<uint8_t*>(obj.untag()) +
+ offset),
+ value);
+ }
+ static void StoreCompressedPointerBarrier(ObjectPtr obj,
+ intptr_t offset,
+ ObjectPtr value) {
+ obj.untag()->StoreCompressedPointer(
+ reinterpret_cast<CompressedObjectPtr*>(
+ reinterpret_cast<uint8_t*>(obj.untag()) + offset),
+ value);
+ }
+ void StoreCompressedLargeArrayPointerBarrier(ObjectPtr obj,
+ intptr_t offset,
+ ObjectPtr value) {
+ obj.untag()->StoreCompressedArrayPointer(
+ reinterpret_cast<CompressedObjectPtr*>(
+ reinterpret_cast<uint8_t*>(obj.untag()) + offset),
+ value, thread_);
+ }
+ static void StorePointerNoBarrier(ObjectPtr obj,
+ intptr_t offset,
+ ObjectPtr value) {
+ *reinterpret_cast<ObjectPtr*>(reinterpret_cast<uint8_t*>(obj.untag()) +
+ offset) = value;
+ }
+ template <typename T = ObjectPtr>
+ static void StoreCompressedPointerNoBarrier(ObjectPtr obj,
+ intptr_t offset,
+ T value) {
+ *reinterpret_cast<CompressedObjectPtr*>(
+ reinterpret_cast<uint8_t*>(obj.untag()) + offset) = value;
+ }
+ static void StoreCompressedNonPointerWord(ObjectPtr obj,
+ intptr_t offset,
+ compressed_uword value) {
+ *reinterpret_cast<compressed_uword*>(
+ reinterpret_cast<uint8_t*>(obj.untag()) + offset) = value;
+ }
+
+ DART_FORCE_INLINE
+ bool CanCopyObject(uword tags, ObjectPtr object) {
+ const auto cid = UntaggedObject::ClassIdTag::decode(tags);
+ if (cid > kNumPredefinedCids) {
+ const bool has_native_fields =
+ Class::NumNativeFieldsOf(class_table_->At(cid)) != 0;
+ if (has_native_fields) {
+ exception_msg_ =
+ "Illegal argument in isolate message: (object has native fields)";
+ return false;
+ }
+ return true;
+ }
+#define HANDLE_ILLEGAL_CASE(Type) \
+ case k##Type##Cid: { \
+ exception_msg_ = \
+ "Illegal argument in isolate message: " \
+ "(object is a" #Type ")"; \
+ return false; \
+ }
+
+ switch (cid) {
+ HANDLE_ILLEGAL_CASE(MirrorReference)
+ HANDLE_ILLEGAL_CASE(ReceivePort)
+ HANDLE_ILLEGAL_CASE(StackTrace)
+ HANDLE_ILLEGAL_CASE(UserTag)
+ HANDLE_ILLEGAL_CASE(DynamicLibrary)
+ HANDLE_ILLEGAL_CASE(Pointer)
+ case kClosureCid: {
+ if (!Function::IsImplicitStaticClosureFunction(
+ Closure::FunctionOf(Closure::RawCast(object)))) {
+ exception_msg_ =
+ "Illegal argument in isolate message: (object is a closure)";
+ return false;
+ }
+ ASSERT(Closure::ContextOf(Closure::RawCast(object)) == Object::null());
+ return true;
+ }
+ default:
+ return true;
+ }
+ }
+
+ Thread* thread_;
+ uword heap_base_;
+ Zone* zone_;
+ Heap* heap_;
+ ClassTable* class_table_;
+ Scavenger* new_space_;
+ Object& tmp_;
+
+ const char* exception_msg_ = nullptr;
+};
+
+class FastObjectCopyBase : public ObjectCopyBase {
+ public:
+ using Types = PtrTypes;
+
+ explicit FastObjectCopyBase(Thread* thread)
+ : ObjectCopyBase(thread), fast_forward_map_(thread) {}
+
+ protected:
+ DART_FORCE_INLINE
+ void ForwardCompressedPointers(ObjectPtr src,
+ ObjectPtr dst,
+ intptr_t offset,
+ intptr_t end_offset) {
+ for (; offset < end_offset; offset += kCompressedWordSize) {
+ ForwardCompressedPointer(src, dst, offset);
+ }
+ }
+
+ DART_FORCE_INLINE
+ void ForwardCompressedPointers(ObjectPtr src,
+ ObjectPtr dst,
+ intptr_t offset,
+ intptr_t end_offset,
+ UnboxedFieldBitmap bitmap) {
+ if (bitmap.IsEmpty()) {
+ ForwardCompressedPointers(src, dst, offset, end_offset);
+ return;
+ }
+ intptr_t bit = offset >> kCompressedWordSizeLog2;
+ for (; offset < end_offset; offset += kCompressedWordSize) {
+ if (bitmap.Get(bit++)) {
+ StoreCompressedNonPointerWord(
+ dst, offset, LoadCompressedNonPointerWord(src, offset));
+ } else {
+ ForwardCompressedPointer(src, dst, offset);
+ }
+ }
+ }
+
+ void ForwardCompressedArrayPointers(intptr_t array_length,
+ ObjectPtr src,
+ ObjectPtr dst,
+ intptr_t offset,
+ intptr_t end_offset) {
+ for (; offset < end_offset; offset += kCompressedWordSize) {
+ ForwardCompressedPointer(src, dst, offset);
+ }
+ }
+
+ DART_FORCE_INLINE
+ void ForwardCompressedPointer(ObjectPtr src, ObjectPtr dst, intptr_t offset) {
+ auto value = LoadCompressedPointer(src, offset);
+ if (!value.IsHeapObject()) {
+ StoreCompressedPointerNoBarrier(dst, offset, value);
+ return;
+ }
+ auto value_decompressed = value.Decompress(heap_base_);
+ const uword tags = TagsFromUntaggedObject(value_decompressed.untag());
+ if (CanShareObject(tags)) {
+ StoreCompressedPointerNoBarrier(dst, offset, value);
+ return;
+ }
+
+ ObjectPtr existing_to =
+ fast_forward_map_.ForwardedObject(value_decompressed);
+ if (existing_to != Marker()) {
+ StoreCompressedPointerNoBarrier(dst, offset, existing_to);
+ return;
+ }
+
+ if (UNLIKELY(!CanCopyObject(tags, value_decompressed))) {
+ ASSERT(exception_msg_ != nullptr);
+ StoreCompressedPointerNoBarrier(dst, offset, Object::null());
+ return;
+ }
+
+ auto to = Forward(tags, value.Decompress(heap_base_));
+ StoreCompressedPointerNoBarrier(dst, offset, to);
+ }
+
+ ObjectPtr Forward(uword tags, ObjectPtr from) {
+ const intptr_t header_size = UntaggedObject::SizeTag::decode(tags);
+ const auto cid = UntaggedObject::ClassIdTag::decode(tags);
+ const uword size =
+ header_size != 0 ? header_size : from.untag()->HeapSize();
+ if (Heap::IsAllocatableInNewSpace(size)) {
+ const uword alloc = new_space_->TryAllocate(thread_, size);
+ if (alloc != 0) {
+ ObjectPtr to(reinterpret_cast<UntaggedObject*>(alloc));
+ fast_forward_map_.Insert(from, to);
+
+ if (IsExternalTypedDataClassId(cid)) {
+ SetNewSpaceTaggingWord(to, cid, header_size);
+ InitializeExternalTypedData(cid, ExternalTypedData::RawCast(from),
+ ExternalTypedData::RawCast(to));
+ fast_forward_map_.AddExternalTypedData(
+ ExternalTypedData::RawCast(to));
+ } else if (IsTypedDataViewClassId(cid)) {
+ // We set the views backing store to `null` to satisfy an assertion in
+ // GCCompactor::VisitTypedDataViewPointers().
+ SetNewSpaceTaggingWord(to, cid, header_size);
+ InitializeTypedDataView(TypedDataView::RawCast(to));
+ }
+ return to;
+ }
+ }
+ exception_msg_ = kFastAllocationFailed;
+ return Marker();
+ }
+
+ void EnqueueTransferable(TransferableTypedDataPtr from,
+ TransferableTypedDataPtr to) {
+ fast_forward_map_.AddTransferable(from, to);
+ }
+ void EnqueueObjectToRehash(ObjectPtr to) {
+ fast_forward_map_.AddObjectToRehash(to);
+ }
+
+ static void StoreCompressedArrayPointers(intptr_t array_length,
+ ObjectPtr src,
+ ObjectPtr dst,
+ intptr_t offset,
+ intptr_t end_offset) {
+ StoreCompressedPointers(src, dst, offset, end_offset);
+ }
+ static void StoreCompressedPointers(ObjectPtr src,
+ ObjectPtr dst,
+ intptr_t offset,
+ intptr_t end_offset) {
+ StoreCompressedPointersNoBarrier(src, dst, offset, end_offset);
+ }
+ static void StoreCompressedPointersNoBarrier(ObjectPtr src,
+ ObjectPtr dst,
+ intptr_t offset,
+ intptr_t end_offset) {
+ for (; offset <= end_offset; offset += kCompressedWordSize) {
+ StoreCompressedPointerNoBarrier(dst, offset,
+ LoadCompressedPointer(src, offset));
+ }
+ }
+
+ protected:
+ friend class ObjectGraphCopier;
+
+ FastForwardMap fast_forward_map_;
+};
+
+class SlowObjectCopyBase : public ObjectCopyBase {
+ public:
+ using Types = HandleTypes;
+
+ explicit SlowObjectCopyBase(Thread* thread)
+ : ObjectCopyBase(thread), slow_forward_map_(thread) {}
+
+ protected:
+ DART_FORCE_INLINE
+ void ForwardCompressedPointers(const Object& src,
+ const Object& dst,
+ intptr_t offset,
+ intptr_t end_offset) {
+ for (; offset < end_offset; offset += kCompressedWordSize) {
+ ForwardCompressedPointer(src, dst, offset);
+ }
+ }
+
+ DART_FORCE_INLINE
+ void ForwardCompressedPointers(const Object& src,
+ const Object& dst,
+ intptr_t offset,
+ intptr_t end_offset,
+ UnboxedFieldBitmap bitmap) {
+ intptr_t bit = offset >> kCompressedWordSizeLog2;
+ for (; offset < end_offset; offset += kCompressedWordSize) {
+ if (bitmap.Get(bit++)) {
+ StoreCompressedNonPointerWord(
+ dst.ptr(), offset, LoadCompressedNonPointerWord(src.ptr(), offset));
+ } else {
+ ForwardCompressedPointer(src, dst, offset);
+ }
+ }
+ }
+
+ void ForwardCompressedArrayPointers(intptr_t array_length,
+ const Object& src,
+ const Object& dst,
+ intptr_t offset,
+ intptr_t end_offset) {
+ if (Array::UseCardMarkingForAllocation(array_length)) {
+ for (; offset < end_offset; offset += kCompressedWordSize) {
+ ForwardCompressedLargeArrayPointer(src, dst, offset);
+ }
+ } else {
+ for (; offset < end_offset; offset += kCompressedWordSize) {
+ ForwardCompressedPointer(src, dst, offset);
+ }
+ }
+ }
+
+ DART_FORCE_INLINE
+ void ForwardCompressedLargeArrayPointer(const Object& src,
+ const Object& dst,
+ intptr_t offset) {
+ auto value = LoadCompressedPointer(src.ptr(), offset);
+ if (!value.IsHeapObject()) {
+ StoreCompressedPointerNoBarrier(dst.ptr(), offset, value);
+ return;
+ }
+
+ auto value_decompressed = value.Decompress(heap_base_);
+ const uword tags = TagsFromUntaggedObject(value_decompressed.untag());
+ if (CanShareObject(tags)) {
+ StoreCompressedLargeArrayPointerBarrier(dst.ptr(), offset,
+ value_decompressed);
+ return;
+ }
+
+ ObjectPtr existing_to =
+ slow_forward_map_.ForwardedObject(value_decompressed);
+ if (existing_to != Marker()) {
+ StoreCompressedLargeArrayPointerBarrier(dst.ptr(), offset, existing_to);
+ return;
+ }
+
+ if (UNLIKELY(!CanCopyObject(tags, value_decompressed))) {
+ ASSERT(exception_msg_ != nullptr);
+ StoreCompressedLargeArrayPointerBarrier(dst.ptr(), offset,
+ Object::null());
+ return;
+ }
+
+ tmp_ = value_decompressed;
+ tmp_ = Forward(tags, tmp_); // Only this can cause allocation.
+ StoreCompressedLargeArrayPointerBarrier(dst.ptr(), offset, tmp_.ptr());
+ }
+ DART_FORCE_INLINE
+ void ForwardCompressedPointer(const Object& src,
+ const Object& dst,
+ intptr_t offset) {
+ auto value = LoadCompressedPointer(src.ptr(), offset);
+ if (!value.IsHeapObject()) {
+ StoreCompressedPointerNoBarrier(dst.ptr(), offset, value);
+ return;
+ }
+ auto value_decompressed = value.Decompress(heap_base_);
+ const uword tags = TagsFromUntaggedObject(value_decompressed.untag());
+ if (CanShareObject(tags)) {
+ StoreCompressedPointerBarrier(dst.ptr(), offset, value_decompressed);
+ return;
+ }
+
+ ObjectPtr existing_to =
+ slow_forward_map_.ForwardedObject(value_decompressed);
+ if (existing_to != Marker()) {
+ StoreCompressedPointerBarrier(dst.ptr(), offset, existing_to);
+ return;
+ }
+
+ if (UNLIKELY(!CanCopyObject(tags, value_decompressed))) {
+ ASSERT(exception_msg_ != nullptr);
+ StoreCompressedPointerNoBarrier(dst.ptr(), offset, Object::null());
+ return;
+ }
+
+ tmp_ = value_decompressed;
+ tmp_ = Forward(tags, tmp_); // Only this can cause allocation.
+ StoreCompressedPointerBarrier(dst.ptr(), offset, tmp_.ptr());
+ }
+ ObjectPtr Forward(uword tags, const Object& from) {
+ const intptr_t cid = UntaggedObject::ClassIdTag::decode(tags);
+ intptr_t size = UntaggedObject::SizeTag::decode(tags);
+ if (size == 0) {
+ size = from.ptr().untag()->HeapSize();
+ }
+ ObjectPtr to = AllocateObject(cid, size);
+ slow_forward_map_.Insert(from.ptr(), to);
+ UpdateLengthField(cid, from.ptr(), to);
+ if (cid == kArrayCid && !Heap::IsAllocatableInNewSpace(size)) {
+ to.untag()->SetCardRememberedBitUnsynchronized();
+ }
+ if (IsExternalTypedDataClassId(cid)) {
+ InitializeExternalTypedData(cid, ExternalTypedData::RawCast(from.ptr()),
+ ExternalTypedData::RawCast(to));
+ slow_forward_map_.AddExternalTypedData(ExternalTypedData::RawCast(to));
+ } else if (IsTypedDataViewClassId(cid)) {
+ // We set the views backing store to `null` to satisfy an assertion in
+ // GCCompactor::VisitTypedDataViewPointers().
+ InitializeTypedDataView(TypedDataView::RawCast(to));
+ }
+ return to;
+ }
+ void EnqueueTransferable(const TransferableTypedData& from,
+ const TransferableTypedData& to) {
+ slow_forward_map_.AddTransferable(from, to);
+ }
+ void EnqueueObjectToRehash(const Object& to) {
+ slow_forward_map_.AddObjectToRehash(to);
+ }
+
+ void StoreCompressedArrayPointers(intptr_t array_length,
+ const Object& src,
+ const Object& dst,
+ intptr_t offset,
+ intptr_t end_offset) {
+ auto src_ptr = src.ptr();
+ auto dst_ptr = dst.ptr();
+ if (Array::UseCardMarkingForAllocation(array_length)) {
+ for (; offset <= end_offset; offset += kCompressedWordSize) {
+ StoreCompressedLargeArrayPointerBarrier(
+ dst_ptr, offset,
+ LoadCompressedPointer(src_ptr, offset).Decompress(heap_base_));
+ }
+ } else {
+ for (; offset <= end_offset; offset += kCompressedWordSize) {
+ StoreCompressedPointerBarrier(
+ dst_ptr, offset,
+ LoadCompressedPointer(src_ptr, offset).Decompress(heap_base_));
+ }
+ }
+ }
+ void StoreCompressedPointers(const Object& src,
+ const Object& dst,
+ intptr_t offset,
+ intptr_t end_offset) {
+ auto src_ptr = src.ptr();
+ auto dst_ptr = dst.ptr();
+ for (; offset <= end_offset; offset += kCompressedWordSize) {
+ StoreCompressedPointerBarrier(
+ dst_ptr, offset,
+ LoadCompressedPointer(src_ptr, offset).Decompress(heap_base_));
+ }
+ }
+ static void StoreCompressedPointersNoBarrier(const Object& src,
+ const Object& dst,
+ intptr_t offset,
+ intptr_t end_offset) {
+ auto src_ptr = src.ptr();
+ auto dst_ptr = dst.ptr();
+ for (; offset <= end_offset; offset += kCompressedWordSize) {
+ StoreCompressedPointerNoBarrier(dst_ptr, offset,
+ LoadCompressedPointer(src_ptr, offset));
+ }
+ }
+
+ protected:
+ friend class ObjectGraphCopier;
+
+ SlowForwardMap slow_forward_map_;
+};
+
+template <typename Base>
+class ObjectCopy : public Base {
+ public:
+ using Types = typename Base::Types;
+
+ explicit ObjectCopy(Thread* thread) : Base(thread) {}
+
+ void CopyPredefinedInstance(typename Types::Object from,
+ typename Types::Object to,
+ intptr_t cid) {
+ if (IsImplicitFieldClassId(cid)) {
+ CopyUserdefinedInstance(from, to);
+ return;
+ }
+ switch (cid) {
+#define COPY_TO(clazz) \
+ case clazz::kClassId: { \
+ typename Types::clazz casted_from = Types::Cast##clazz(from); \
+ typename Types::clazz casted_to = Types::Cast##clazz(to); \
+ Copy##clazz(casted_from, casted_to); \
+ return; \
+ }
+
+ CLASS_LIST_NO_OBJECT_NOR_STRING_NOR_ARRAY_NOR_MAP(COPY_TO)
+ COPY_TO(Array)
+ COPY_TO(LinkedHashMap)
+ COPY_TO(LinkedHashSet)
+#undef COPY_TO
+
+#define COPY_TO(clazz) case kTypedData##clazz##Cid:
+
+ CLASS_LIST_TYPED_DATA(COPY_TO) {
+ typename Types::TypedData casted_from = Types::CastTypedData(from);
+ typename Types::TypedData casted_to = Types::CastTypedData(to);
+ CopyTypedData(casted_from, casted_to);
+ return;
+ }
+#undef COPY_TO
+
+ case kByteDataViewCid:
+#define COPY_TO(clazz) case kTypedData##clazz##ViewCid:
+ CLASS_LIST_TYPED_DATA(COPY_TO) {
+ typename Types::TypedDataView casted_from =
+ Types::CastTypedDataView(from);
+ typename Types::TypedDataView casted_to =
+ Types::CastTypedDataView(to);
+ CopyTypedDataView(casted_from, casted_to);
+ return;
+ }
+#undef COPY_TO
+
+#define COPY_TO(clazz) case kExternalTypedData##clazz##Cid:
+
+ CLASS_LIST_TYPED_DATA(COPY_TO) {
+ typename Types::ExternalTypedData casted_from =
+ Types::CastExternalTypedData(from);
+ typename Types::ExternalTypedData casted_to =
+ Types::CastExternalTypedData(to);
+ CopyExternalTypedData(casted_from, casted_to);
+ return;
+ }
+#undef COPY_TO
+ default:
+ break;
+ }
+
+ const Object& obj = Types::HandlifyObject(from);
+ FATAL1("Unexpected object: %s\n", obj.ToCString());
+ }
+
+#if defined(DART_PRECOMPILED_RUNTIME)
+ void CopyUserdefinedInstanceAOT(typename Types::Object from,
+ typename Types::Object to,
+ UnboxedFieldBitmap bitmap) {
+ const intptr_t instance_size = UntagObject(from)->HeapSize();
+ Base::ForwardCompressedPointers(from, to, kWordSize, instance_size, bitmap);
+ }
+#endif
+
+ void CopyUserdefinedInstance(typename Types::Object from,
+ typename Types::Object to) {
+ const intptr_t instance_size = UntagObject(from)->HeapSize();
+ Base::ForwardCompressedPointers(from, to, kWordSize, instance_size);
+ }
+
+ void CopyClosure(typename Types::Closure from, typename Types::Closure to) {
+ Base::StoreCompressedPointers(
+ from, to, OFFSET_OF(UntaggedClosure, instantiator_type_arguments_),
+ OFFSET_OF(UntaggedClosure, function_));
+ Base::ForwardCompressedPointer(from, to,
+ OFFSET_OF(UntaggedClosure, context_));
+ Base::StoreCompressedPointersNoBarrier(from, to,
+ OFFSET_OF(UntaggedClosure, hash_),
+ OFFSET_OF(UntaggedClosure, hash_));
+ ONLY_IN_PRECOMPILED(UntagClosure(to)->entry_point_ =
+ UntagClosure(from)->entry_point_);
+ }
+
+ void CopyArray(typename Types::Array from, typename Types::Array to) {
+ const intptr_t length = Smi::Value(UntagArray(from)->length());
+ Base::StoreCompressedArrayPointers(
+ length, from, to, OFFSET_OF(UntaggedArray, type_arguments_),
+ OFFSET_OF(UntaggedArray, type_arguments_));
+ Base::StoreCompressedPointersNoBarrier(from, to,
+ OFFSET_OF(UntaggedArray, length_),
+ OFFSET_OF(UntaggedArray, length_));
+ Base::ForwardCompressedArrayPointers(
+ length, from, to, Array::data_offset(),
+ Array::data_offset() + kCompressedWordSize * length);
+ }
+
+ void CopyGrowableObjectArray(typename Types::GrowableObjectArray from,
+ typename Types::GrowableObjectArray to) {
+ Base::StoreCompressedPointers(
+ from, to, OFFSET_OF(UntaggedGrowableObjectArray, type_arguments_),
+ OFFSET_OF(UntaggedGrowableObjectArray, type_arguments_));
+ Base::StoreCompressedPointersNoBarrier(
+ from, to, OFFSET_OF(UntaggedGrowableObjectArray, length_),
+ OFFSET_OF(UntaggedGrowableObjectArray, length_));
+ Base::ForwardCompressedPointer(
+ from, to, OFFSET_OF(UntaggedGrowableObjectArray, data_));
+ }
+
+ template <intptr_t one_for_set_two_for_map, typename T>
+ void CopyLinkedHashBase(T from,
+ T to,
+ UntaggedLinkedHashBase* from_untagged,
+ UntaggedLinkedHashBase* to_untagged) {
+ // We have to find out whether the map needs re-hashing on the receiver side
+ // due to keys being copied and the keys therefore possibly having different
+ // hash codes (e.g. due to user-defined hashCode implementation or due to
+ // new identity hash codes of the copied objects).
+ bool needs_rehashing = false;
+ ArrayPtr data = from_untagged->data_.Decompress(Base::heap_base_);
+ if (data != Array::null()) {
+ UntaggedArray* untagged_data = data.untag();
+ const intptr_t length = Smi::Value(untagged_data->length_);
+ auto key_value_pairs = untagged_data->data();
+ for (intptr_t i = 0; i < length; i += one_for_set_two_for_map) {
+ ObjectPtr key = key_value_pairs[i].Decompress(Base::heap_base_);
+ if (key->IsHeapObject()) {
+ if (MightNeedReHashing(key)) {
+ needs_rehashing = true;
+ break;
+ }
+ }
+ }
+ }
+
+ Base::StoreCompressedPointers(
+ from, to, OFFSET_OF(UntaggedLinkedHashBase, type_arguments_),
+ OFFSET_OF(UntaggedLinkedHashBase, type_arguments_));
+
+ // Compared with the snapshot-based (de)serializer we do preserve the same
+ // backing store (i.e. used_data/deleted_keys/data) and therefore do not
+ // magically shrink backing store based on usage.
+ //
+ // We do this to avoid making assumptions about the object graph and the
+ // linked hash map (e.g. assuming there's no other references to the data,
+ // assuming the linked hashmap is in a consistent state)
+ if (needs_rehashing) {
+ to_untagged->hash_mask_ = Smi::New(0);
+ to_untagged->index_ = TypedData::RawCast(Object::null());
+ Base::EnqueueObjectToRehash(to);
+ }
+
+ // From this point on we shouldn't use the raw pointers, since GC might
+ // happen when forwarding objects.
+ from_untagged = nullptr;
+ to_untagged = nullptr;
+
+ if (!needs_rehashing) {
+ Base::ForwardCompressedPointer(from, to,
+ OFFSET_OF(UntaggedLinkedHashBase, index_));
+ Base::StoreCompressedPointersNoBarrier(
+ from, to, OFFSET_OF(UntaggedLinkedHashBase, hash_mask_),
+ OFFSET_OF(UntaggedLinkedHashBase, hash_mask_));
+ }
+ Base::ForwardCompressedPointer(from, to,
+ OFFSET_OF(UntaggedLinkedHashBase, data_));
+ Base::StoreCompressedPointersNoBarrier(
+ from, to, OFFSET_OF(UntaggedLinkedHashBase, used_data_),
+ OFFSET_OF(UntaggedLinkedHashBase, used_data_));
+ Base::StoreCompressedPointersNoBarrier(
+ from, to, OFFSET_OF(UntaggedLinkedHashMap, deleted_keys_),
+ OFFSET_OF(UntaggedLinkedHashMap, deleted_keys_));
+ }
+
+ void CopyLinkedHashMap(typename Types::LinkedHashMap from,
+ typename Types::LinkedHashMap to) {
+ CopyLinkedHashBase<2, typename Types::LinkedHashMap>(
+ from, to, UntagLinkedHashMap(from), UntagLinkedHashMap(to));
+ }
+ void CopyLinkedHashSet(typename Types::LinkedHashSet from,
+ typename Types::LinkedHashSet to) {
+ CopyLinkedHashBase<1, typename Types::LinkedHashSet>(
+ from, to, UntagLinkedHashSet(from), UntagLinkedHashSet(to));
+ }
+
+ void CopyDouble(typename Types::Double from, typename Types::Double to) {
+#if !defined(DART_PRECOMPILED_RUNTIME)
+ auto raw_from = UntagDouble(from);
+ auto raw_to = UntagDouble(to);
+ raw_to->value_ = raw_from->value_;
+#else
+ // Will be shared and not copied.
+ UNREACHABLE();
+#endif
+ }
+
+ void CopyFloat32x4(typename Types::Float32x4 from,
+ typename Types::Float32x4 to) {
+#if !defined(DART_PRECOMPILED_RUNTIME)
+ auto raw_from = UntagFloat32x4(from);
+ auto raw_to = UntagFloat32x4(to);
+ raw_to->value_[0] = raw_from->value_[0];
+ raw_to->value_[1] = raw_from->value_[1];
+ raw_to->value_[2] = raw_from->value_[2];
+ raw_to->value_[3] = raw_from->value_[3];
+#else
+ // Will be shared and not copied.
+ UNREACHABLE();
+#endif
+ }
+
+ void CopyFloat64x2(typename Types::Float64x2 from,
+ typename Types::Float64x2 to) {
+#if !defined(DART_PRECOMPILED_RUNTIME)
+ auto raw_from = UntagFloat64x2(from);
+ auto raw_to = UntagFloat64x2(to);
+ raw_to->value_[0] = raw_from->value_[0];
+ raw_to->value_[1] = raw_from->value_[1];
+#else
+ // Will be shared and not copied.
+ UNREACHABLE();
+#endif
+ }
+
+ void CopyTypedData(typename Types::TypedData from,
+ typename Types::TypedData to) {
+ auto raw_from = UntagTypedData(from);
+ auto raw_to = UntagTypedData(to);
+ const intptr_t cid = Types::GetTypedDataPtr(from)->GetClassId();
+ raw_to->length_ = raw_from->length_;
+ raw_to->RecomputeDataField();
+ const intptr_t length =
+ TypedData::ElementSizeInBytes(cid) * Smi::Value(raw_from->length_);
+ memmove(raw_to->data_, raw_from->data_, length);
+ }
+
+ void CopyTypedDataView(typename Types::TypedDataView from,
+ typename Types::TypedDataView to) {
+ // This will forward & initialize the typed data.
+ Base::ForwardCompressedPointer(
+ from, to, OFFSET_OF(UntaggedTypedDataView, typed_data_));
+
+ auto raw_from = UntagTypedDataView(from);
+ auto raw_to = UntagTypedDataView(to);
+ raw_to->length_ = raw_from->length_;
+ raw_to->offset_in_bytes_ = raw_from->offset_in_bytes_;
+ raw_to->data_ = nullptr;
+
+ if (raw_to->typed_data_.Decompress(Base::heap_base_) == Object::null()) {
+ ASSERT(Base::exception_msg_ != nullptr);
+ return;
+ }
+
+ const bool is_external =
+ raw_from->data_ != raw_from->DataFieldForInternalTypedData();
+ if (is_external) {
+ // The raw_to is fully initialized at this point (see handling of external
+ // typed data in [ForwardCompressedPointer])
+ raw_to->RecomputeDataField();
+ } else {
+ // The raw_to isn't initialized yet, but it's address is valid, so we can
+ // compute the data field it would use.
+ raw_to->RecomputeDataFieldForInternalTypedData();
+ }
+ const bool is_external2 =
+ raw_to->data_ != raw_to->DataFieldForInternalTypedData();
+ ASSERT(is_external == is_external2);
+ }
+
+ void CopyExternalTypedData(typename Types::ExternalTypedData from,
+ typename Types::ExternalTypedData to) {
+ // The external typed data is initialized on the forwarding pass (where
+ // normally allocation but not initialization happens), so views on it
+ // can be initialized immediately.
+#if defined(DEBUG)
+ auto raw_from = UntagExternalTypedData(from);
+ auto raw_to = UntagExternalTypedData(to);
+ ASSERT(raw_to->data_ != nullptr);
+ ASSERT(raw_to->length_ == raw_from->length_);
+#endif
+ }
+
+ void CopyTransferableTypedData(typename Types::TransferableTypedData from,
+ typename Types::TransferableTypedData to) {
+ // The [TransferableTypedData] is an empty object with an associated heap
+ // peer object.
+ // -> We'll validate that there's a peer and enqueue the transferable to be
+ // transferred if the transitive copy is successful.
+ auto fpeer = static_cast<TransferableTypedDataPeer*>(
+ Base::heap_->GetPeer(Types::GetTransferableTypedDataPtr(from)));
+ ASSERT(fpeer != nullptr);
+ if (fpeer->data() == nullptr) {
+ Base::exception_msg_ =
+ "Illegal argument in isolate message"
+ " : (TransferableTypedData has been transferred already)";
+ return;
+ }
+ Base::EnqueueTransferable(from, to);
+ }
+
+#define DEFINE_UNSUPPORTED(clazz) \
+ void Copy##clazz(typename Types::clazz from, typename Types::clazz to) { \
+ FATAL("Objects of type " #clazz " should not occur in object graphs"); \
+ }
+
+ FOR_UNSUPPORTED_CLASSES(DEFINE_UNSUPPORTED)
+
+#undef DEFINE_UNSUPPORTED
+
+ UntaggedObject* UntagObject(typename Types::Object obj) {
+ return Types::GetObjectPtr(obj).Decompress(Base::heap_base_).untag();
+ }
+
+#define DO(V) \
+ DART_FORCE_INLINE \
+ Untagged##V* Untag##V(typename Types::V obj) { \
+ return Types::Get##V##Ptr(obj).Decompress(Base::heap_base_).untag(); \
+ }
+ CLASS_LIST_FOR_HANDLES(DO)
+#undef DO
+};
+
+class FastObjectCopy : public ObjectCopy<FastObjectCopyBase> {
+ public:
+ explicit FastObjectCopy(Thread* thread) : ObjectCopy(thread) {}
+ ~FastObjectCopy() {}
+
+ ObjectPtr TryCopyGraphFast(ObjectPtr root) {
+ NoSafepointScope no_safepoint_scope;
+
+ ObjectPtr root_copy = Forward(TagsFromUntaggedObject(root.untag()), root);
+ if (root_copy == Marker()) {
+ return root_copy;
+ }
+ while (fast_forward_map_.fill_cursor_ <
+ fast_forward_map_.raw_from_to_.length()) {
+ const intptr_t index = fast_forward_map_.fill_cursor_;
+ ObjectPtr from = fast_forward_map_.raw_from_to_[index];
+ ObjectPtr to = fast_forward_map_.raw_from_to_[index + 1];
+ FastCopyObject(from, to);
+ if (exception_msg_ != nullptr) {
+ return root_copy;
+ }
+ fast_forward_map_.fill_cursor_ += 2;
+ }
+ if (root_copy != Marker()) {
+ TryBuildArrayOfObjectsToRehash();
+ }
+ return root_copy;
+ }
+
+ void TryBuildArrayOfObjectsToRehash() {
+ const auto& objects_to_rehash = fast_forward_map_.raw_objects_to_rehash_;
+ const intptr_t length = objects_to_rehash.length();
+ if (length == 0) return;
+
+ const intptr_t size = Array::InstanceSize(length);
+ const uword array_addr = new_space_->TryAllocate(thread_, size);
+ if (array_addr == 0) {
+ exception_msg_ = kFastAllocationFailed;
+ return;
+ }
+
+ const uword header_size =
+ UntaggedObject::SizeTag::SizeFits(size) ? size : 0;
+ ArrayPtr array(reinterpret_cast<UntaggedArray*>(array_addr));
+ SetNewSpaceTaggingWord(array, kArrayCid, header_size);
+ StoreCompressedPointerNoBarrier(array, OFFSET_OF(UntaggedArray, length_),
+ Smi::New(length));
+ StoreCompressedPointerNoBarrier(array,
+ OFFSET_OF(UntaggedArray, type_arguments_),
+ TypeArguments::null());
+ auto array_data = array.untag()->data();
+ for (intptr_t i = 0; i < length; ++i) {
+ array_data[i] = objects_to_rehash[i];
+ }
+ raw_objects_to_rehash_ = array;
+ }
+
+ private:
+ friend class ObjectGraphCopier;
+
+ void FastCopyObject(ObjectPtr from, ObjectPtr to) {
+ const uword tags = TagsFromUntaggedObject(from.untag());
+ const intptr_t cid = UntaggedObject::ClassIdTag::decode(tags);
+ const intptr_t size = UntaggedObject::SizeTag::decode(tags);
+
+ // Ensure the last word is GC-safe (our heap objects are 2-word aligned, the
+ // object header stores the size in multiples of kObjectAlignment, the GC
+ // uses the information from the header and therefore might visit one slot
+ // more than the actual size of the instance).
+ *reinterpret_cast<ObjectPtr*>(UntaggedObject::ToAddr(to) +
+ from.untag()->HeapSize() - kWordSize) = 0;
+ SetNewSpaceTaggingWord(to, cid, size);
+
+ // Fall back to virtual variant for predefined classes
+ if (cid < kNumPredefinedCids && cid != kInstanceCid) {
+ CopyPredefinedInstance(from, to, cid);
+ return;
+ }
+#if defined(DART_PRECOMPILED_RUNTIME)
+ const auto bitmap =
+ class_table_->shared_class_table()->GetUnboxedFieldsMapAt(cid);
+ CopyUserdefinedInstanceAOT(Instance::RawCast(from), Instance::RawCast(to),
+ bitmap);
+#else
+ CopyUserdefinedInstance(Instance::RawCast(from), Instance::RawCast(to));
+#endif
+ }
+
+ ArrayPtr raw_objects_to_rehash_ = Array::null();
+};
+
+class SlowObjectCopy : public ObjectCopy<SlowObjectCopyBase> {
+ public:
+ explicit SlowObjectCopy(Thread* thread)
+ : ObjectCopy(thread), objects_to_rehash_(Array::Handle(thread->zone())) {}
+ ~SlowObjectCopy() {}
+
+ ObjectPtr ContinueCopyGraphSlow(const Object& root,
+ const Object& fast_root_copy) {
+ auto& root_copy = Object::Handle(Z, fast_root_copy.ptr());
+ if (root_copy.ptr() == Marker()) {
+ root_copy = Forward(TagsFromUntaggedObject(root.ptr().untag()), root);
+ }
+
+ Object& from = Object::Handle(Z);
+ Object& to = Object::Handle(Z);
+ while (slow_forward_map_.fill_cursor_ <
+ slow_forward_map_.from_to_.length()) {
+ const intptr_t index = slow_forward_map_.fill_cursor_;
+ from = slow_forward_map_.from_to_[index]->ptr();
+ to = slow_forward_map_.from_to_[index + 1]->ptr();
+ CopyObject(from, to);
+ slow_forward_map_.fill_cursor_ += 2;
+ if (exception_msg_ != nullptr) {
+ return Marker();
+ }
+ }
+ BuildArrayOfObjectsToRehash();
+ return root_copy.ptr();
+ }
+
+ void BuildArrayOfObjectsToRehash() {
+ const auto& objects_to_rehash = slow_forward_map_.objects_to_rehash_;
+ const intptr_t length = objects_to_rehash.length();
+ if (length == 0) return;
+
+ objects_to_rehash_ = Array::New(length);
+ for (intptr_t i = 0; i < length; ++i) {
+ objects_to_rehash_.SetAt(i, *objects_to_rehash[i]);
+ }
+ }
+
+ private:
+ friend class ObjectGraphCopier;
+
+ void CopyObject(const Object& from, const Object& to) {
+ const auto cid = from.GetClassId();
+
+ // Fall back to virtual variant for predefined classes
+ if (cid < kNumPredefinedCids && cid != kInstanceCid) {
+ CopyPredefinedInstance(from, to, cid);
+ return;
+ }
+#if defined(DART_PRECOMPILED_RUNTIME)
+ const auto bitmap =
+ class_table_->shared_class_table()->GetUnboxedFieldsMapAt(cid);
+ CopyUserdefinedInstanceAOT(from, to, bitmap);
+#else
+ CopyUserdefinedInstance(from, to);
+#endif
+ }
+
+ Array& objects_to_rehash_;
+};
+
+class ObjectGraphCopier {
+ public:
+ explicit ObjectGraphCopier(Thread* thread)
+ : thread_(thread),
+ zone_(thread->zone()),
+ fast_object_copy_(thread_),
+ slow_object_copy_(thread_) {
+ thread_->isolate()->set_forward_table_new(new WeakTable());
+ thread_->isolate()->set_forward_table_old(new WeakTable());
+ }
+ ~ObjectGraphCopier() {
+ thread_->isolate()->set_forward_table_new(nullptr);
+ thread_->isolate()->set_forward_table_old(nullptr);
+ }
+
+ // Result will be [<msg>, <objects-in-msg-to-rehash>]
+ ObjectPtr CopyObjectGraph(const Object& root) {
+ const char* volatile exception_msg = nullptr;
+ auto& result = Object::Handle(zone_);
+
+ {
+ LongJumpScope jump; // e.g. for OOMs.
+ if (setjmp(*jump.Set()) == 0) {
+ result = CopyObjectGraphInternal(root, &exception_msg);
+ // Any allocated external typed data must have finalizers attached so
+ // memory will get free()ed.
+ slow_object_copy_.slow_forward_map_.FinalizeExternalTypedData();
+ } else {
+ // Any allocated external typed data must have finalizers attached so
+ // memory will get free()ed.
+ slow_object_copy_.slow_forward_map_.FinalizeExternalTypedData();
+
+ // The copy failed due to non-application error (e.g. OOM error),
+ // propagate this error.
+ result = thread_->StealStickyError();
+ RELEASE_ASSERT(result.IsError());
+ }
+ }
+
+ if (result.IsError()) {
+ Exceptions::PropagateError(Error::Cast(result));
+ UNREACHABLE();
+ }
+ if (result.ptr() == Marker()) {
+ ASSERT(exception_msg != nullptr);
+ ThrowException(exception_msg);
+ UNREACHABLE();
+ }
+
+ // The copy was successful, then detach transferable data from the sender
+ // and attach to the copied graph.
+ slow_object_copy_.slow_forward_map_.FinalizeTransferables();
+ return result.ptr();
+ }
+
+ private:
+ ObjectPtr CopyObjectGraphInternal(const Object& root,
+ const char* volatile* exception_msg) {
+ const auto& result_array = Array::Handle(zone_, Array::New(2));
+ if (!root.ptr()->IsHeapObject()) {
+ result_array.SetAt(0, root);
+ return result_array.ptr();
+ }
+ const uword tags = TagsFromUntaggedObject(root.ptr().untag());
+ if (CanShareObject(tags)) {
+ result_array.SetAt(0, root);
+ return result_array.ptr();
+ }
+ if (!fast_object_copy_.CanCopyObject(tags, root.ptr())) {
+ ASSERT(fast_object_copy_.exception_msg_ != nullptr);
+ *exception_msg = fast_object_copy_.exception_msg_;
+ return Marker();
+ }
+
+ // We try a fast new-space only copy first that will not use any barriers.
+ auto& result = Object::Handle(Z, Marker());
+
+ // All allocated but non-initialized heap objects have to be made GC-visible
+ // at this point.
+ if (FLAG_enable_fast_object_copy) {
+ {
+ NoSafepointScope no_safepoint_scope;
+
+ result = fast_object_copy_.TryCopyGraphFast(root.ptr());
+ if (result.ptr() != Marker()) {
+ if (fast_object_copy_.exception_msg_ == nullptr) {
+ result_array.SetAt(0, result);
+ fast_object_copy_.tmp_ = fast_object_copy_.raw_objects_to_rehash_;
+ result_array.SetAt(1, fast_object_copy_.tmp_);
+ HandlifyExternalTypedData();
+ HandlifyTransferables();
+ return result_array.ptr();
+ }
+
+ // There are left-over uninitialized objects we'll have to make GC
+ // visible.
+ SwitchToSlowFowardingList();
+ }
+ }
+
+ if (FLAG_gc_on_foc_slow_path) {
+ // We use kLowMemory to force the GC to compact, which is more likely to
+ // discover untracked pointers (and other issues, like incorrect class
+ // table).
+ thread_->heap()->CollectAllGarbage(Heap::kLowMemory);
+ }
+
+ // Fast copy failed due to
+ // - either failure to allocate into new space
+ // - or failure to copy object which we cannot copy
+ ASSERT(fast_object_copy_.exception_msg_ != nullptr);
+ if (fast_object_copy_.exception_msg_ != kFastAllocationFailed) {
+ *exception_msg = fast_object_copy_.exception_msg_;
+ return Marker();
+ }
+ ASSERT(fast_object_copy_.exception_msg_ == kFastAllocationFailed);
+ }
+
+ // Use the slow copy approach.
+ result = slow_object_copy_.ContinueCopyGraphSlow(root, result);
+ ASSERT((result.ptr() == Marker()) ==
+ (slow_object_copy_.exception_msg_ != nullptr));
+ if (result.ptr() == Marker()) {
+ *exception_msg = slow_object_copy_.exception_msg_;
+ return Marker();
+ }
+
+ result_array.SetAt(0, result);
+ result_array.SetAt(1, slow_object_copy_.objects_to_rehash_);
+ return result_array.ptr();
+ }
+
+ void SwitchToSlowFowardingList() {
+ auto& fast_forward_map = fast_object_copy_.fast_forward_map_;
+ auto& slow_forward_map = slow_object_copy_.slow_forward_map_;
+
+ MakeUninitializedNewSpaceObjectsGCSafe();
+ HandlifyTransferables();
+ HandlifyExternalTypedData();
+ HandlifyObjectsToReHash();
+ HandlifyFromToObjects();
+ slow_forward_map.fill_cursor_ = fast_forward_map.fill_cursor_;
+ }
+
+ void MakeUninitializedNewSpaceObjectsGCSafe() {
+ auto& fast_forward_map = fast_object_copy_.fast_forward_map_;
+ const auto length = fast_forward_map.raw_from_to_.length();
+ const auto cursor = fast_forward_map.fill_cursor_;
+ for (intptr_t i = cursor; i < length; i += 2) {
+ auto from = fast_forward_map.raw_from_to_[i];
+ auto to = fast_forward_map.raw_from_to_[i + 1];
+ const uword tags = TagsFromUntaggedObject(from.untag());
+ const intptr_t cid = UntaggedObject::ClassIdTag::decode(tags);
+ const intptr_t size = UntaggedObject::SizeTag::decode(tags);
+ // External typed data is already initialized.
+ if (!IsExternalTypedDataClassId(cid) && !IsTypedDataViewClassId(cid)) {
+ memset(reinterpret_cast<void*>(to.untag()), 0,
+ from.untag()->HeapSize());
+ SetNewSpaceTaggingWord(to, cid, size);
+ UpdateLengthField(cid, from, to);
+ }
+ }
+ }
+ void HandlifyTransferables() {
+ auto& raw_transferables =
+ fast_object_copy_.fast_forward_map_.raw_transferables_from_to_;
+ const auto length = raw_transferables.length();
+ if (length > 0) {
+ auto& transferables =
+ slow_object_copy_.slow_forward_map_.transferables_from_to_;
+ transferables.Resize(length);
+ for (intptr_t i = 0; i < length; i++) {
+ transferables[i] =
+ &TransferableTypedData::Handle(Z, raw_transferables[i]);
+ }
+ raw_transferables.Clear();
+ }
+ }
+ void HandlifyExternalTypedData() {
+ auto& raw_external_typed_data =
+ fast_object_copy_.fast_forward_map_.raw_external_typed_data_to_;
+ const auto length = raw_external_typed_data.length();
+ if (length > 0) {
+ auto& external_typed_data =
+ slow_object_copy_.slow_forward_map_.external_typed_data_;
+ external_typed_data.Resize(length);
+ for (intptr_t i = 0; i < length; i++) {
+ external_typed_data[i] =
+ &ExternalTypedData::Handle(Z, raw_external_typed_data[i]);
+ }
+ raw_external_typed_data.Clear();
+ }
+ }
+ void HandlifyObjectsToReHash() {
+ auto& fast_forward_map = fast_object_copy_.fast_forward_map_;
+ auto& slow_forward_map = slow_object_copy_.slow_forward_map_;
+ const auto length = fast_forward_map.raw_transferables_from_to_.length();
+ if (length > 0) {
+ slow_forward_map.objects_to_rehash_.Resize(length);
+ for (intptr_t i = 0; i < length; i++) {
+ slow_forward_map.objects_to_rehash_[i] =
+ &Object::Handle(Z, fast_forward_map.raw_objects_to_rehash_[i]);
+ }
+ fast_forward_map.raw_objects_to_rehash_.Clear();
+ }
+ }
+ void HandlifyFromToObjects() {
+ auto& fast_forward_map = fast_object_copy_.fast_forward_map_;
+ auto& slow_forward_map = slow_object_copy_.slow_forward_map_;
+
+ const intptr_t cursor = fast_forward_map.fill_cursor_;
+ const intptr_t length = fast_forward_map.raw_from_to_.length();
+
+ slow_forward_map.from_to_.Resize(length);
+ for (intptr_t i = 2; i < length; i += 2) {
+ slow_forward_map.from_to_[i] =
+ i < cursor ? nullptr
+ : &Object::Handle(Z, fast_forward_map.raw_from_to_[i]);
+ slow_forward_map.from_to_[i + 1] =
+ &Object::Handle(Z, fast_forward_map.raw_from_to_[i + 1]);
+ }
+ fast_forward_map.raw_from_to_.Clear();
+ }
+ void ThrowException(const char* exception_msg) {
+ const auto& msg_obj = String::Handle(Z, String::New(exception_msg));
+ const auto& args = Array::Handle(Z, Array::New(1));
+ args.SetAt(0, msg_obj);
+ Exceptions::ThrowByType(Exceptions::kArgument, args);
+ UNREACHABLE();
+ }
+
+ Thread* thread_;
+ Zone* zone_;
+ FastObjectCopy fast_object_copy_;
+ SlowObjectCopy slow_object_copy_;
+};
+
+ObjectPtr CopyMutableObjectGraph(const Object& object) {
+ auto thread = Thread::Current();
+ ObjectGraphCopier copier(thread);
+ return copier.CopyObjectGraph(object);
+}
+
+} // namespace dart
diff --git a/runtime/vm/object_graph_copy.h b/runtime/vm/object_graph_copy.h
new file mode 100644
index 0000000..b33c3e4
--- /dev/null
+++ b/runtime/vm/object_graph_copy.h
@@ -0,0 +1,26 @@
+// 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.
+
+#ifndef RUNTIME_VM_OBJECT_GRAPH_COPY_H_
+#define RUNTIME_VM_OBJECT_GRAPH_COPY_H_
+
+namespace dart {
+
+class Object;
+class ObjectPtr;
+
+// Makes a transitive copy of the object graph referenced by [object]. Will not
+// copy objects that can be safely shared - due to being immutable.
+//
+// The result will be an array of length 2 of the format
+//
+// [<copy-of-root>, <array-of-objects-to-rehash / null>]
+//
+// If the array of objects to rehash is not `null` the receiver should re-hash
+// those objects.
+ObjectPtr CopyMutableObjectGraph(const Object& root);
+
+} // namespace dart
+
+#endif // RUNTIME_VM_OBJECT_GRAPH_COPY_H_
diff --git a/runtime/vm/object_reload.cc b/runtime/vm/object_reload.cc
index 2f404f5..7fe26f1 100644
--- a/runtime/vm/object_reload.cc
+++ b/runtime/vm/object_reload.cc
@@ -6,6 +6,7 @@
#include "platform/unaligned.h"
#include "vm/code_patcher.h"
+#include "vm/dart_entry.h"
#include "vm/hash_table.h"
#include "vm/isolate_reload.h"
#include "vm/log.h"
diff --git a/runtime/vm/object_service.cc b/runtime/vm/object_service.cc
index 2fa6cda..1685ebf 100644
--- a/runtime/vm/object_service.cc
+++ b/runtime/vm/object_service.cc
@@ -94,6 +94,15 @@
jsobj.AddProperty("library", Object::Handle(library()));
+ const intptr_t num_type_params = NumTypeParameters();
+ if (num_type_params > 0) {
+ JSONArray jsarr(&jsobj, "typeParameters");
+ TypeParameter& type_param = TypeParameter::Handle();
+ for (intptr_t i = 0; i < num_type_params; ++i) {
+ type_param = TypeParameterAt(i);
+ jsarr.AddValue(type_param);
+ }
+ }
if (ref) {
return;
}
@@ -172,8 +181,10 @@
}
void TypeParameters::PrintJSONImpl(JSONStream* stream, bool ref) const {
+ // Consider making this type public if we decide to expose TypeParameters
+ // through the protocol.
JSONObject jsobj(stream);
- jsobj.AddProperty("kind", "TypeParameters");
+ jsobj.AddProperty("kind", "_TypeParameters");
jsobj.AddProperty("flags", Array::Handle(flags()));
jsobj.AddProperty("names", Array::Handle(names()));
jsobj.AddProperty("bounds", TypeArguments::Handle(bounds()));
@@ -317,6 +328,7 @@
jsobj.AddProperty("_kind", kind_string);
jsobj.AddProperty("static", is_static());
jsobj.AddProperty("const", is_const());
+ jsobj.AddProperty("implicit", IsImplicitGetterOrSetter());
jsobj.AddProperty("_intrinsic", is_intrinsic());
jsobj.AddProperty("_native", is_native());
@@ -328,6 +340,9 @@
if (ref) {
return;
}
+ const FunctionType& sig = FunctionType::Handle(signature());
+ jsobj.AddProperty("signature", sig);
+
Code& code = Code::Handle(CurrentCode());
if (!code.IsNull()) {
jsobj.AddProperty("code", code);
@@ -1178,7 +1193,38 @@
JSONObject jsobj(stream);
PrintSharedInstanceJSON(&jsobj, ref);
jsobj.AddProperty("kind", "FunctionType");
- // TODO(regis): Function types were not handled before, necessary now?
+ AbstractType& type = AbstractType::Handle(result_type());
+ jsobj.AddProperty("returnType", type);
+
+ const int type_params_count = NumTypeParameters();
+ if (type_params_count > 0) {
+ JSONArray arr(&jsobj, "typeParameters");
+ TypeParameter& type_param = TypeParameter::Handle();
+ for (intptr_t i = 0; i < type_params_count; ++i) {
+ type_param = TypeParameterAt(i);
+ arr.AddValue(type_param);
+ }
+ }
+
+ {
+ JSONArray jsarr(&jsobj, "parameters");
+ String& name = String::Handle();
+ const intptr_t param_count = NumParameters();
+ const intptr_t fixed_param_count = num_fixed_parameters();
+ const bool has_named = HasOptionalNamedParameters();
+ for (intptr_t i = 0; i < param_count; ++i) {
+ JSONObject param(&jsarr);
+ type = ParameterTypeAt(i);
+ param.AddProperty("parameterType", type);
+ bool fixed = i < fixed_param_count;
+ param.AddProperty("fixed", fixed);
+ if (!fixed && has_named) {
+ name = ParameterNameAt(i);
+ param.AddProperty("name", name.ToCString());
+ param.AddProperty("required", IsRequiredAt(i));
+ }
+ }
+ }
}
void TypeRef::PrintJSONImpl(JSONStream* stream, bool ref) const {
@@ -1390,6 +1436,41 @@
}
}
+void LinkedHashSet::PrintJSONImpl(JSONStream* stream, bool ref) const {
+ JSONObject jsobj(stream);
+ PrintSharedInstanceJSON(&jsobj, ref);
+ jsobj.AddProperty("kind", "PlainInstance");
+ jsobj.AddServiceId(*this);
+ jsobj.AddProperty("length", Length());
+ if (ref) {
+ return;
+ }
+ intptr_t offset;
+ intptr_t count;
+ stream->ComputeOffsetAndCount(Length(), &offset, &count);
+ if (offset > 0) {
+ jsobj.AddProperty("offset", offset);
+ }
+ if (count < Length()) {
+ jsobj.AddProperty("count", count);
+ }
+ intptr_t limit = offset + count;
+ ASSERT(limit <= Length());
+ {
+ JSONArray jsarr(&jsobj, "elements");
+ Object& object = Object::Handle();
+ LinkedHashSet::Iterator iterator(*this);
+ int i = 0;
+ while (iterator.MoveNext() && i < limit) {
+ if (i >= offset) {
+ object = iterator.CurrentKey();
+ jsarr.AddValue(object);
+ }
+ i++;
+ }
+ }
+}
+
void Float32x4::PrintJSONImpl(JSONStream* stream, bool ref) const {
JSONObject jsobj(stream);
PrintSharedInstanceJSON(&jsobj, ref);
diff --git a/runtime/vm/object_store.cc b/runtime/vm/object_store.cc
index 2ffb6ce..33bede3 100644
--- a/runtime/vm/object_store.cc
+++ b/runtime/vm/object_store.cc
@@ -91,7 +91,20 @@
return Error::null();
}
-ObjectStore::ObjectStore() {
+ObjectStore::ObjectStore()
+ :
+#define EMIT_FIELD_INIT(type, name) name##_(nullptr),
+ OBJECT_STORE_FIELD_LIST(EMIT_FIELD_INIT,
+ EMIT_FIELD_INIT,
+ EMIT_FIELD_INIT,
+ EMIT_FIELD_INIT,
+ EMIT_FIELD_INIT,
+ EMIT_FIELD_INIT,
+ EMIT_FIELD_INIT,
+ EMIT_FIELD_INIT)
+#undef EMIT_FIELD_INIT
+ unused_field_(0) // Just to prevent a trailing comma.
+{
for (ObjectPtr* current = from(); current <= to(); current++) {
*current = Object::null();
}
@@ -121,8 +134,9 @@
Object& value = Object::Handle();
static const char* const names[] = {
#define EMIT_FIELD_NAME(type, name) #name "_",
- OBJECT_STORE_FIELD_LIST(EMIT_FIELD_NAME, EMIT_FIELD_NAME,
- EMIT_FIELD_NAME, EMIT_FIELD_NAME)
+ OBJECT_STORE_FIELD_LIST(
+ EMIT_FIELD_NAME, EMIT_FIELD_NAME, EMIT_FIELD_NAME, EMIT_FIELD_NAME,
+ EMIT_FIELD_NAME, EMIT_FIELD_NAME, EMIT_FIELD_NAME, EMIT_FIELD_NAME)
#undef EMIT_FIELD_NAME
};
ObjectPtr* current = from();
@@ -270,10 +284,6 @@
}
}
- const Library& internal_lib = Library::Handle(zone, _internal_library());
- cls = internal_lib.LookupClass(Symbols::Symbol());
- set_symbol_class(cls);
-
const Library& core_lib = Library::Handle(zone, core_library());
cls = core_lib.LookupClassAllowPrivate(Symbols::_CompileTimeError());
ASSERT(!cls.IsNull());
@@ -282,11 +292,13 @@
cls = core_lib.LookupClassAllowPrivate(Symbols::Pragma());
ASSERT(!cls.IsNull());
set_pragma_class(cls);
+ RELEASE_ASSERT(cls.EnsureIsFinalized(thread) == Error::null());
set_pragma_name(Field::Handle(zone, cls.LookupField(Symbols::name())));
set_pragma_options(Field::Handle(zone, cls.LookupField(Symbols::options())));
cls = core_lib.LookupClassAllowPrivate(Symbols::_GrowableList());
ASSERT(!cls.IsNull());
+ RELEASE_ASSERT(cls.EnsureIsFinalized(thread) == Error::null());
growable_list_factory_ =
cls.LookupFactoryAllowPrivate(Symbols::_GrowableListFactory());
ASSERT(growable_list_factory_ != Function::null());
@@ -295,6 +307,10 @@
ASSERT(!cls.IsNull());
set_error_class(cls);
+ cls = core_lib.LookupClassAllowPrivate(Symbols::Expando());
+ ASSERT(!cls.IsNull());
+ set_expando_class(cls);
+
// Cache the core private functions used for fast instance of checks.
simple_instance_of_function_ =
PrivateObjectLookup(Symbols::_simpleInstanceOf());
@@ -306,6 +322,7 @@
// Ensure AddSmiSmiCheckForFastSmiStubs run by the background compiler
// will not create new functions.
const Class& smi_class = Class::Handle(zone, this->smi_class());
+ RELEASE_ASSERT(smi_class.EnsureIsFinalized(thread) == Error::null());
function_name =
Function::CreateDynamicInvocationForwarderName(Symbols::Plus());
Resolver::ResolveDynamicAnyArgs(zone, smi_class, function_name);
@@ -333,41 +350,64 @@
#endif
}
-void ObjectStore::LazyInitCoreTypes() {
- if (list_class_ == Type::null()) {
- ASSERT(non_nullable_list_rare_type_ == Type::null());
- ASSERT(non_nullable_map_rare_type_ == Type::null());
- Thread* thread = Thread::Current();
- Zone* zone = thread->zone();
- const Library& core_lib = Library::Handle(zone, Library::CoreLibrary());
- Class& cls = Class::Handle(zone, core_lib.LookupClass(Symbols::List()));
+void ObjectStore::LazyInitCoreMembers() {
+ auto* const thread = Thread::Current();
+ SafepointWriteRwLocker locker(thread,
+ thread->isolate_group()->program_lock());
+ if (list_class_.load() == Type::null()) {
+ ASSERT(non_nullable_list_rare_type_.load() == Type::null());
+ ASSERT(non_nullable_map_rare_type_.load() == Type::null());
+ ASSERT(_object_equals_function_.load() == Function::null());
+ ASSERT(_object_hash_code_function_.load() == Function::null());
+ ASSERT(_object_to_string_function_.load() == Function::null());
+
+ auto* const zone = thread->zone();
+ const auto& core_lib = Library::Handle(zone, Library::CoreLibrary());
+ auto& cls = Class::Handle(zone);
+
+ cls = core_lib.LookupClass(Symbols::List());
ASSERT(!cls.IsNull());
- set_list_class(cls);
- Type& type = Type::Handle(zone);
+ list_class_.store(cls.ptr());
+
+ auto& type = Type::Handle(zone);
type ^= cls.RareType();
- set_non_nullable_list_rare_type(type);
+ non_nullable_list_rare_type_.store(type.ptr());
+
cls = core_lib.LookupClass(Symbols::Map());
ASSERT(!cls.IsNull());
type ^= cls.RareType();
- set_non_nullable_map_rare_type(type);
+ non_nullable_map_rare_type_.store(type.ptr());
+
+ auto& function = Function::Handle(zone);
+
+ function = core_lib.LookupFunctionAllowPrivate(Symbols::_objectHashCode());
+ ASSERT(!function.IsNull());
+ _object_hash_code_function_.store(function.ptr());
+
+ function = core_lib.LookupFunctionAllowPrivate(Symbols::_objectEquals());
+ ASSERT(!function.IsNull());
+ _object_equals_function_.store(function.ptr());
+
+ function = core_lib.LookupFunctionAllowPrivate(Symbols::_objectToString());
+ ASSERT(!function.IsNull());
+ _object_to_string_function_.store(function.ptr());
}
}
-void ObjectStore::LazyInitFutureTypes() {
- if (non_nullable_future_rare_type_ == Type::null()) {
- ASSERT(non_nullable_future_never_type_ == Type::null() &&
- nullable_future_null_type_ == Type::null());
- Thread* thread = Thread::Current();
- Zone* zone = thread->zone();
- Class& cls = Class::Handle(zone, future_class());
- if (cls.IsNull()) {
- const Library& async_lib = Library::Handle(zone, async_library());
- ASSERT(!async_lib.IsNull());
- cls = async_lib.LookupClass(Symbols::Future());
- ASSERT(!cls.IsNull());
- }
- TypeArguments& type_args = TypeArguments::Handle(zone);
- Type& type = Type::Handle(zone);
+void ObjectStore::LazyInitAsyncMembers() {
+ auto* const thread = Thread::Current();
+ SafepointWriteRwLocker locker(thread,
+ thread->isolate_group()->program_lock());
+ if (non_nullable_future_rare_type_.load() == Type::null()) {
+ ASSERT(non_nullable_future_never_type_.load() == Type::null());
+ ASSERT(nullable_future_null_type_.load() == Type::null());
+
+ auto* const zone = thread->zone();
+ const auto& cls = Class::Handle(zone, future_class());
+ ASSERT(!cls.IsNull());
+
+ auto& type_args = TypeArguments::Handle(zone);
+ auto& type = Type::Handle(zone);
type = never_type();
ASSERT(!type.IsNull());
type_args = TypeArguments::New(1);
@@ -375,7 +415,8 @@
type = Type::New(cls, type_args, Nullability::kNonNullable);
type.SetIsFinalized();
type ^= type.Canonicalize(thread, nullptr);
- set_non_nullable_future_never_type(type);
+ non_nullable_future_never_type_.store(type.ptr());
+
type = null_type();
ASSERT(!type.IsNull());
type_args = TypeArguments::New(1);
@@ -383,9 +424,67 @@
type = Type::New(cls, type_args, Nullability::kNullable);
type.SetIsFinalized();
type ^= type.Canonicalize(thread, nullptr);
- set_nullable_future_null_type(type);
+ nullable_future_null_type_.store(type.ptr());
+
type ^= cls.RareType();
- set_non_nullable_future_rare_type(type);
+ non_nullable_future_rare_type_.store(type.ptr());
+ }
+}
+
+void ObjectStore::LazyInitIsolateMembers() {
+ auto* const thread = Thread::Current();
+ SafepointWriteRwLocker locker(thread,
+ thread->isolate_group()->program_lock());
+ if (lookup_port_handler_.load() == Type::null()) {
+ ASSERT(lookup_open_ports_.load() == Type::null());
+ ASSERT(handle_message_function_.load() == Type::null());
+
+ auto* const zone = thread->zone();
+ const auto& isolate_lib = Library::Handle(zone, Library::IsolateLibrary());
+ auto& cls = Class::Handle(zone);
+ auto& function = Function::Handle(zone);
+
+ cls = isolate_lib.LookupClassAllowPrivate(Symbols::_RawReceivePortImpl());
+ ASSERT(!cls.IsNull());
+ const auto& error = cls.EnsureIsFinalized(thread);
+ ASSERT(error == Error::null());
+
+ function = cls.LookupFunctionAllowPrivate(Symbols::_lookupHandler());
+ ASSERT(!function.IsNull());
+ lookup_port_handler_.store(function.ptr());
+
+ function = cls.LookupFunctionAllowPrivate(Symbols::_lookupOpenPorts());
+ ASSERT(!function.IsNull());
+ lookup_open_ports_.store(function.ptr());
+
+ function = cls.LookupFunctionAllowPrivate(Symbols::_handleMessage());
+ ASSERT(!function.IsNull());
+ handle_message_function_.store(function.ptr());
+ }
+}
+
+void ObjectStore::LazyInitInternalMembers() {
+ auto* const thread = Thread::Current();
+ SafepointWriteRwLocker locker(thread,
+ thread->isolate_group()->program_lock());
+ if (symbol_class_.load() == Type::null()) {
+ ASSERT(symbol_name_field_.load() == Field::null());
+
+ auto* const zone = thread->zone();
+ auto& cls = Class::Handle(zone);
+ auto& field = Field::Handle(zone);
+
+ const auto& internal_lib =
+ Library::Handle(zone, Library::InternalLibrary());
+ cls = internal_lib.LookupClass(Symbols::Symbol());
+ ASSERT(!cls.IsNull());
+ const auto& error = cls.EnsureIsFinalized(thread);
+ ASSERT(error == Error::null());
+ symbol_class_.store(cls.ptr());
+
+ field = cls.LookupInstanceFieldAllowPrivate(Symbols::_name());
+ ASSERT(!field.IsNull());
+ symbol_name_field_.store(field.ptr());
}
}
diff --git a/runtime/vm/object_store.h b/runtime/vm/object_store.h
index eec9974e..a944d89 100644
--- a/runtime/vm/object_store.h
+++ b/runtime/vm/object_store.h
@@ -36,9 +36,28 @@
//
// R_ - needs getter only
// RW - needs getter and setter
-// CW - needs lazy Core init getter and setter
-// FW - needs lazy Future init getter and setter
-#define OBJECT_STORE_FIELD_LIST(R_, RW, CW, FW) \
+// ARW_RELAXED - needs getter and setter with relaxed atomic access
+// ARW_AR - needs getter and setter with acq/rel atomic access
+// LAZY_CORE - needs lazy init getter for a "dart:core" member
+// LAZY_ASYNC - needs lazy init getter for a "dart:async" member
+// LAZY_ISOLATE - needs lazy init getter for a "dart:isolate" member
+// LAZY_INTERNAL - needs lazy init getter for a "dart:_internal" member
+#define OBJECT_STORE_FIELD_LIST(R_, RW, ARW_RELAXED, ARW_AR, LAZY_CORE, \
+ LAZY_ASYNC, LAZY_ISOLATE, LAZY_INTERNAL) \
+ LAZY_CORE(Class, list_class) \
+ LAZY_CORE(Type, non_nullable_list_rare_type) \
+ LAZY_CORE(Type, non_nullable_map_rare_type) \
+ LAZY_CORE(Function, _object_equals_function) \
+ LAZY_CORE(Function, _object_hash_code_function) \
+ LAZY_CORE(Function, _object_to_string_function) \
+ LAZY_INTERNAL(Class, symbol_class) \
+ LAZY_INTERNAL(Field, symbol_name_field) \
+ LAZY_ASYNC(Type, non_nullable_future_rare_type) \
+ LAZY_ASYNC(Type, non_nullable_future_never_type) \
+ LAZY_ASYNC(Type, nullable_future_null_type) \
+ LAZY_ISOLATE(Function, lookup_port_handler) \
+ LAZY_ISOLATE(Function, lookup_open_ports) \
+ LAZY_ISOLATE(Function, handle_message_function) \
RW(Class, object_class) \
RW(Type, object_type) \
RW(Type, legacy_object_type) \
@@ -81,12 +100,6 @@
RW(Type, string_type) \
RW(Type, legacy_string_type) \
RW(Type, non_nullable_string_type) \
- CW(Class, list_class) /* maybe be null, lazily built */ \
- CW(Type, non_nullable_list_rare_type) /* maybe be null, lazily built */ \
- CW(Type, non_nullable_map_rare_type) /* maybe be null, lazily built */ \
- FW(Type, non_nullable_future_rare_type) /* maybe be null, lazily built */ \
- FW(Type, non_nullable_future_never_type) /* maybe be null, lazily built */ \
- FW(Type, nullable_future_null_type) /* maybe be null, lazily built */ \
RW(TypeArguments, type_argument_int) \
RW(TypeArguments, type_argument_legacy_int) \
RW(TypeArguments, type_argument_non_nullable_int) \
@@ -108,7 +121,6 @@
RW(Field, pragma_options) \
RW(Class, future_class) \
RW(Class, completer_class) \
- RW(Class, symbol_class) \
RW(Class, one_byte_string_class) \
RW(Class, two_byte_string_class) \
RW(Class, external_one_byte_string_class) \
@@ -129,8 +141,9 @@
RW(Class, int32x4_class) \
RW(Class, float64x2_class) \
RW(Class, error_class) \
+ RW(Class, expando_class) \
RW(Class, weak_property_class) \
- RW(Array, symbol_table) \
+ ARW_AR(Array, symbol_table) \
RW(Array, canonical_types) \
RW(Array, canonical_function_types) \
RW(Array, canonical_type_parameters) \
@@ -158,12 +171,6 @@
RW(GrowableObjectArray, pending_classes) \
RW(Instance, stack_overflow) \
RW(Instance, out_of_memory) \
- RW(Function, _object_equals_function) \
- RW(Function, _object_hash_code_function) \
- RW(Function, _object_to_string_function) \
- RW(Function, lookup_port_handler) \
- RW(Function, lookup_open_ports) \
- RW(Function, handle_message_function) \
RW(Function, growable_list_factory) \
RW(Function, simple_instance_of_function) \
RW(Function, simple_instance_of_true_function) \
@@ -172,11 +179,14 @@
RW(Function, complete_on_async_return) \
RW(Function, complete_on_async_error) \
RW(Class, async_star_stream_controller) \
+ ARW_RELAXED(Smi, future_timeout_future_index) \
+ ARW_RELAXED(Smi, future_wait_future_index) \
RW(CompressedStackMaps, canonicalized_stack_map_entries) \
RW(ObjectPool, global_object_pool) \
RW(Array, unique_dynamic_targets) \
RW(GrowableObjectArray, megamorphic_cache_table) \
- RW(Code, build_method_extractor_code) \
+ RW(Code, build_generic_method_extractor_code) \
+ RW(Code, build_nongeneric_method_extractor_code) \
RW(Code, dispatch_table_null_error_stub) \
RW(Code, late_initialization_error_stub_with_fpu_regs_stub) \
RW(Code, late_initialization_error_stub_without_fpu_regs_stub) \
@@ -387,35 +397,62 @@
ObjectStore();
~ObjectStore();
+#define DECLARE_OFFSET(name) \
+ static intptr_t name##_offset() { return OFFSET_OF(ObjectStore, name##_); }
#define DECLARE_GETTER(Type, name) \
Type##Ptr name() const { return name##_; } \
- static intptr_t name##_offset() { return OFFSET_OF(ObjectStore, name##_); }
+ DECLARE_OFFSET(name)
#define DECLARE_GETTER_AND_SETTER(Type, name) \
DECLARE_GETTER(Type, name) \
void set_##name(const Type& value) { name##_ = value.ptr(); }
+#define DECLARE_RELAXED_ATOMIC_GETTER_AND_SETTER(Type, name) \
+ template <std::memory_order order = std::memory_order_relaxed> \
+ Type##Ptr name() const { \
+ return name##_.load(order); \
+ } \
+ template <std::memory_order order = std::memory_order_relaxed> \
+ void set_##name(const Type& value) { \
+ name##_.store(value.ptr(), order); \
+ } \
+ DECLARE_OFFSET(name)
+#define DECLARE_ACQREL_ATOMIC_GETTER_AND_SETTER(Type, name) \
+ Type##Ptr name() const { return name##_.load(); } \
+ void set_##name(const Type& value) { name##_.store(value.ptr()); } \
+ DECLARE_OFFSET(name)
#define DECLARE_LAZY_INIT_GETTER(Type, name, init) \
Type##Ptr name() { \
- if (name##_ == Type::null()) { \
+ if (name##_.load() == Type::null()) { \
init(); \
} \
- return name##_; \
+ return name##_.load(); \
} \
- static intptr_t name##_offset() { return OFFSET_OF(ObjectStore, name##_); }
-#define DECLARE_LAZY_INIT_CORE_GETTER_AND_SETTER(Type, name) \
- DECLARE_LAZY_INIT_GETTER(Type, name, LazyInitCoreTypes) \
- void set_##name(const Type& value) { name##_ = value.ptr(); }
-#define DECLARE_LAZY_INIT_FUTURE_GETTER_AND_SETTER(Type, name) \
- DECLARE_LAZY_INIT_GETTER(Type, name, LazyInitFutureTypes) \
- void set_##name(const Type& value) { name##_ = value.ptr(); }
+ DECLARE_OFFSET(name)
+#define DECLARE_LAZY_INIT_CORE_GETTER(Type, name) \
+ DECLARE_LAZY_INIT_GETTER(Type, name, LazyInitCoreMembers)
+#define DECLARE_LAZY_INIT_ASYNC_GETTER(Type, name) \
+ DECLARE_LAZY_INIT_GETTER(Type, name, LazyInitAsyncMembers)
+#define DECLARE_LAZY_INIT_ISOLATE_GETTER(Type, name) \
+ DECLARE_LAZY_INIT_GETTER(Type, name, LazyInitIsolateMembers)
+#define DECLARE_LAZY_INIT_INTERNAL_GETTER(Type, name) \
+ DECLARE_LAZY_INIT_GETTER(Type, name, LazyInitInternalMembers)
OBJECT_STORE_FIELD_LIST(DECLARE_GETTER,
DECLARE_GETTER_AND_SETTER,
- DECLARE_LAZY_INIT_CORE_GETTER_AND_SETTER,
- DECLARE_LAZY_INIT_FUTURE_GETTER_AND_SETTER)
+ DECLARE_RELAXED_ATOMIC_GETTER_AND_SETTER,
+ DECLARE_ACQREL_ATOMIC_GETTER_AND_SETTER,
+ DECLARE_LAZY_INIT_CORE_GETTER,
+ DECLARE_LAZY_INIT_ASYNC_GETTER,
+ DECLARE_LAZY_INIT_ISOLATE_GETTER,
+ DECLARE_LAZY_INIT_INTERNAL_GETTER)
+#undef DECLARE_OFFSET
#undef DECLARE_GETTER
#undef DECLARE_GETTER_AND_SETTER
+#undef DECLARE_RELAXED_ATOMIC_GETTER_AND_SETTER
+#undef DECLARE_ACQREL_ATOMIC_GETTER_AND_SETTER
#undef DECLARE_LAZY_INIT_GETTER
-#undef DECLARE_LAZY_INIT_CORE_GETTER_AND_SETTER
-#undef DECLARE_LAZY_INIT_FUTURE_GETTER_AND_SETTER
+#undef DECLARE_LAZY_INIT_CORE_GETTER
+#undef DECLARE_LAZY_INIT_ASYNC_GETTER
+#undef DECLARE_LAZY_INIT_ISOLATE_GETTER
+#undef DECLARE_LAZY_INIT_INTERNAL_GETTER
LibraryPtr bootstrap_library(BootstrapLibraryId index) {
switch (index) {
@@ -463,19 +500,31 @@
#endif
private:
- void LazyInitCoreTypes();
- void LazyInitFutureTypes();
+ void LazyInitCoreMembers();
+ void LazyInitAsyncMembers();
+ void LazyInitIsolateMembers();
+ void LazyInitInternalMembers();
// Finds a core library private method in Object.
FunctionPtr PrivateObjectLookup(const String& name);
- ObjectPtr* from() { return reinterpret_cast<ObjectPtr*>(&object_class_); }
+ ObjectPtr* from() { return reinterpret_cast<ObjectPtr*>(&list_class_); }
#define DECLARE_OBJECT_STORE_FIELD(type, name) type##Ptr name##_;
+#define DECLARE_ATOMIC_OBJECT_STORE_FIELD(type, name) \
+ std::atomic<type##Ptr> name##_;
+#define DECLARE_LAZY_OBJECT_STORE_FIELD(type, name) \
+ AcqRelAtomic<type##Ptr> name##_;
OBJECT_STORE_FIELD_LIST(DECLARE_OBJECT_STORE_FIELD,
DECLARE_OBJECT_STORE_FIELD,
- DECLARE_OBJECT_STORE_FIELD,
- DECLARE_OBJECT_STORE_FIELD)
+ DECLARE_ATOMIC_OBJECT_STORE_FIELD,
+ DECLARE_LAZY_OBJECT_STORE_FIELD,
+ DECLARE_LAZY_OBJECT_STORE_FIELD,
+ DECLARE_LAZY_OBJECT_STORE_FIELD,
+ DECLARE_LAZY_OBJECT_STORE_FIELD,
+ DECLARE_LAZY_OBJECT_STORE_FIELD)
#undef DECLARE_OBJECT_STORE_FIELD
+#undef DECLARE_ATOMIC_OBJECT_STORE_FIELD
+#undef DECLARE_LAZY_OBJECT_STORE_FIELD
ObjectPtr* to() {
return reinterpret_cast<ObjectPtr*>(&ffi_as_function_internal_);
}
@@ -487,7 +536,6 @@
case Snapshot::kFullJIT:
case Snapshot::kFullAOT:
return reinterpret_cast<ObjectPtr*>(&slow_tts_stub_);
- case Snapshot::kMessage:
case Snapshot::kNone:
case Snapshot::kInvalid:
break;
@@ -495,6 +543,7 @@
UNREACHABLE();
return NULL;
}
+ uword unused_field_;
friend class ProgramSerializationRoots;
friend class ProgramDeserializationRoots;
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index 7e5c738..93cfc12 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -2532,8 +2532,8 @@
const VariableIndex first_local_index(-1);
bool found_captured_vars = false;
VariableIndex next_index = parent_scope->AllocateVariables(
- first_parameter_index, num_parameters, first_local_index, NULL,
- &found_captured_vars);
+ Function::null_function(), first_parameter_index, num_parameters,
+ first_local_index, NULL, &found_captured_vars);
// Variables a, c and var_ta are captured, therefore are not allocated in
// frame.
EXPECT_EQ(0, next_index.value() -
@@ -4345,7 +4345,7 @@
ISOLATE_UNIT_TEST_CASE(PrintJSONPrimitives) {
// WARNING: This MUST be big enough for the serialised JSON string.
- const int kBufferSize = 1024;
+ const int kBufferSize = 4096;
char buffer[kBufferSize];
Isolate* isolate = Isolate::Current();
@@ -4396,6 +4396,7 @@
"\"library\":{\"type\":\"@Library\",\"fixedId\":true,\"id\":\"\","
"\"name\":\"dart.core\",\"uri\":\"dart:core\"}},"
"\"_kind\":\"RegularFunction\",\"static\":false,\"const\":false,"
+ "\"implicit\":false,"
"\"_intrinsic\":false,\"_native\":false,"
"\"location\":{\"type\":\"SourceLocation\","
"\"script\":{\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\","
@@ -4543,18 +4544,42 @@
ElideJSONSubstring("objects", buffer, buffer);
ElideJSONSubstring("libraries", buffer, buffer);
ElideJSONSubstring("_List@", buffer, buffer);
- StripTokenPositions(buffer);
- EXPECT_STREQ(
+ ElideJSONSubstring("_TypeParameter@", buffer, buffer);
+ EXPECT_SUBSTRING(
"{\"type\":\"@Instance\",\"_vmType\":\"Array\",\"class\":{\"type\":\"@"
"Class\",\"fixedId\":true,\"id\":\"\",\"name\":\"_List\",\"_vmName\":"
"\"\",\"location\":{\"type\":\"SourceLocation\",\"script\":{\"type\":"
- "\"@Script\",\"fixedId\":true,\"id\":\"\",\"uri\":\"dart:core-"
- "patch\\/array.dart\",\"_kind\":\"kernel\"}"
- "},\"library\":{\"type\":\"@Library\",\"fixedId\":"
+ "\"@Script\",\"fixedId\":true,\"id\":\"\",\"uri\":\"dart:core-patch\\/"
+ "array.dart\",\"_kind\":\"kernel\"},\"tokenPos\":248,\"endTokenPos\":"
+ "7758},\"library\":{\"type\":\"@Library\",\"fixedId\":true,\"id\":\"\","
+ "\"name\":\"dart.core\",\"uri\":\"dart:core\"},\"typeParameters\":[{"
+ "\"type\":\"@"
+ "Instance\",\"_vmType\":\"TypeParameter\",\"class\":{\"type\":\"@"
+ "Class\",\"fixedId\":true,\"id\":\"\",\"name\":\"_TypeParameter\",\"_"
+ "vmName\":\"\",\"location\":{\"type\":"
+ "\"SourceLocation\",\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
+ "\"id\":\"\",\"uri\":\"dart:core-patch\\/"
+ "type_patch.dart\",\"_kind\":\"kernel\"},\"tokenPos\":1584,"
+ "\"endTokenPos\":1729},\"library\":{\"type\":\"@Library\",\"fixedId\":"
"true,\"id\":\"\",\"name\":\"dart.core\",\"uri\":\"dart:core\"}},"
+ "\"identityHashCode\":",
+ buffer);
+
+ EXPECT_SUBSTRING(
+ "\"kind\":\"TypeParameter\",\"id\":\"\",\"name\":\"X0\","
+ "\"parameterizedClass\":{\"type\":\"@Instance\",\"_vmType\":\"Class\","
+ "\"class\":{\"type\":\"@Class\",\"fixedId\":true,\"id\":\"\",\"name\":"
+ "\"Null\",\"location\":{\"type\":\"SourceLocation\",\"script\":{"
+ "\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\",\"uri\":\"dart:"
+ "core\\/"
+ "null.dart\",\"_kind\":\"kernel\"},\"tokenPos\":925,\"endTokenPos\":"
+ "1165},\"library\":{\"type\":\"@Library\",\"fixedId\":true,\"id\":\"\","
+ "\"name\":\"dart.core\",\"uri\":\"dart:core\"}},\"kind\":\"Null\","
+ "\"fixedId\":true,\"id\":\"\",\"valueAsString\":\"null\"}}]},"
"\"identityHashCode\":0,\"kind\":\"List\",\"id\":\"\",\"length\":0}",
buffer);
}
+ OS::PrintErr("\n\n\n");
// GrowableObjectArray reference
{
JSONStream js;
@@ -4568,16 +4593,40 @@
ElideJSONSubstring("libraries", buffer, buffer);
ElideJSONSubstring("_GrowableList@", buffer, buffer);
StripTokenPositions(buffer);
- EXPECT_STREQ(
+ ElideJSONSubstring("_TypeParameter@", buffer, buffer);
+ EXPECT_SUBSTRING(
"{\"type\":\"@Instance\",\"_vmType\":\"GrowableObjectArray\",\"class\":"
"{\"type\":\"@Class\",\"fixedId\":true,\"id\":\"\",\"name\":\"_"
"GrowableList\",\"_vmName\":\"\",\"location\":{\"type\":"
"\"SourceLocation\",\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
- "\"id\":\"\",\"uri\":\"dart:core-patch\\/growable_array.dart\",\"_"
- "kind\":\"kernel\"}},"
- "\"library\":{\"type\":\"@Library\",\"fixedId\":true,\"id\":\"\","
- "\"name\":\"dart.core\",\"uri\":\"dart:core\"}},\"identityHashCode\":0,"
- "\"kind\":\"List\",\"id\":\"\",\"length\":0}",
+ "\"id\":\"\",\"uri\":\"dart:core-patch\\/"
+ "growable_array.dart\",\"_kind\":\"kernel\"}"
+ "},\"library\":{\"type\":\"@Library\",\"fixedId\":"
+ "true,\"id\":\"\",\"name\":\"dart.core\",\"uri\":\"dart:core\"},"
+ "\"typeParameters\":[{\"type\":\"@Instance\",\"_vmType\":"
+ "\"TypeParameter\",\"class\":{\"type\":\"@Class\",\"fixedId\":true,"
+ "\"id\":\"\",\"name\":\"_TypeParameter\",\"_vmName\":\""
+ "\",\"location\":{\"type\":\"SourceLocation\",\"script\":{"
+ "\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\",\"uri\":\"dart:core-"
+ "patch\\/"
+ "type_patch.dart\",\"_kind\":\"kernel\"}"
+ "},\"library\":{\"type\":\"@Library\",\"fixedId\":"
+ "true,\"id\":\"\",\"name\":\"dart.core\",\"uri\":\"dart:core\"}},"
+ "\"identityHashCode\":",
+ buffer);
+
+ EXPECT_SUBSTRING(
+ "\"kind\":\"TypeParameter\",\"id\":"
+ "\"\",\"name\":\"X0\",\"parameterizedClass\":{\"type\":\"@Instance\","
+ "\"_vmType\":\"Class\",\"class\":{\"type\":\"@Class\",\"fixedId\":true,"
+ "\"id\":\"\",\"name\":\"Null\",\"location\":{\"type\":"
+ "\"SourceLocation\",\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
+ "\"id\":\"\",\"uri\":\"dart:core\\/"
+ "null.dart\",\"_kind\":\"kernel\"}"
+ "},\"library\":{\"type\":\"@Library\",\"fixedId\":true,\"id\":\"\","
+ "\"name\":\"dart.core\",\"uri\":\"dart:core\"}},\"kind\":\"Null\","
+ "\"fixedId\":true,\"id\":\"\",\"valueAsString\":\"null\"}}]},"
+ "\"identityHashCode\":0,\"kind\":\"List\",\"id\":\"\",\"length\":0}",
buffer);
}
// LinkedHashMap reference
@@ -4593,15 +4642,61 @@
ElideJSONSubstring("libraries", buffer, buffer);
ElideJSONSubstring("_InternalLinkedHashMap@", buffer, buffer);
StripTokenPositions(buffer);
- EXPECT_STREQ(
+ ElideJSONSubstring("_TypeParameter@", buffer, buffer);
+ EXPECT_SUBSTRING(
"{\"type\":\"@Instance\",\"_vmType\":\"LinkedHashMap\",\"class\":{"
"\"type\":\"@Class\",\"fixedId\":true,\"id\":\"\",\"name\":\"_"
"InternalLinkedHashMap\",\"_vmName\":\"\",\"location\":{\"type\":"
"\"SourceLocation\",\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
- "\"id\":\"\",\"uri\":\"dart:collection-patch\\/compact_hash.dart\",\"_"
- "kind\":\"kernel\"}},"
- "\"library\":{\"type\":\"@Library\",\"fixedId\":true,\"id\":\"\","
- "\"name\":\"dart.collection\",\"uri\":\"dart:collection\"}},"
+ "\"id\":\"\",\"uri\":\"dart:collection-patch\\/"
+ "compact_hash.dart\",\"_kind\":\"kernel\"}"
+ "},\"library\":{\"type\":\"@Library\",\"fixedId\":"
+ "true,\"id\":\"\",\"name\":\"dart.collection\",\"uri\":\"dart:"
+ "collection\"},\"typeParameters\":[{\"type\":\"@Instance\",\"_vmType\":"
+ "\"TypeParameter\",\"class\":{\"type\":\"@Class\",\"fixedId\":true,"
+ "\"id\":\"\",\"name\":\"_TypeParameter\",\"_vmName\":\""
+ "\",\"location\":{\"type\":\"SourceLocation\",\"script\":{"
+ "\"type\":\"@Script\",\"fixedId\":true,\"id\":\"\",\"uri\":\"dart:core-"
+ "patch\\/"
+ "type_patch.dart\",\"_kind\":\"kernel\"}"
+ "},\"library\":{\"type\":\"@Library\",\"fixedId\":"
+ "true,\"id\":\"\",\"name\":\"dart.core\",\"uri\":\"dart:core\"}},"
+ "\"identityHashCode\":",
+ buffer);
+
+ EXPECT_SUBSTRING(
+ "\"kind\":\"TypeParameter\",\"id\":"
+ "\"\",\"name\":\"X0\",\"parameterizedClass\":{\"type\":\"@Instance\","
+ "\"_vmType\":\"Class\",\"class\":{\"type\":\"@Class\",\"fixedId\":true,"
+ "\"id\":\"\",\"name\":\"Null\",\"location\":{\"type\":"
+ "\"SourceLocation\",\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
+ "\"id\":\"\",\"uri\":\"dart:core\\/"
+ "null.dart\",\"_kind\":\"kernel\"}"
+ "},\"library\":{\"type\":\"@Library\",\"fixedId\":true,\"id\":\"\","
+ "\"name\":\"dart.core\",\"uri\":\"dart:core\"}},\"kind\":\"Null\","
+ "\"fixedId\":true,\"id\":\"\",\"valueAsString\":\"null\"}},{\"type\":"
+ "\"@Instance\",\"_vmType\":\"TypeParameter\",\"class\":{\"type\":\"@"
+ "Class\",\"fixedId\":true,\"id\":\"\",\"name\":\"_TypeParameter\",\"_"
+ "vmName\":\"\",\"location\":{\"type\":"
+ "\"SourceLocation\",\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
+ "\"id\":\"\",\"uri\":\"dart:core-patch\\/"
+ "type_patch.dart\",\"_kind\":\"kernel\"}"
+ "},\"library\":{\"type\":\"@Library\",\"fixedId\":"
+ "true,\"id\":\"\",\"name\":\"dart.core\",\"uri\":\"dart:core\"}},"
+ "\"identityHashCode\":",
+ buffer);
+
+ EXPECT_SUBSTRING(
+ "\"kind\":\"TypeParameter\",\"id\":"
+ "\"\",\"name\":\"X1\",\"parameterizedClass\":{\"type\":\"@Instance\","
+ "\"_vmType\":\"Class\",\"class\":{\"type\":\"@Class\",\"fixedId\":true,"
+ "\"id\":\"\",\"name\":\"Null\",\"location\":{\"type\":"
+ "\"SourceLocation\",\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
+ "\"id\":\"\",\"uri\":\"dart:core\\/"
+ "null.dart\",\"_kind\":\"kernel\"}"
+ "},\"library\":{\"type\":\"@Library\",\"fixedId\":true,\"id\":\"\","
+ "\"name\":\"dart.core\",\"uri\":\"dart:core\"}},\"kind\":\"Null\","
+ "\"fixedId\":true,\"id\":\"\",\"valueAsString\":\"null\"}}]},"
"\"identityHashCode\":0,\"kind\":\"Map\",\"id\":\"\",\"length\":0}",
buffer);
}
@@ -4779,8 +4874,7 @@
const char* value_script,
uint32_t hashcode_canonicalize_vm = kCalculateCanonizalizeHash,
bool check_identity = true,
- bool check_hashcode = true,
- bool print_failure = true) {
+ bool check_hashcode = true) {
auto kScriptChars = Utils::CStringUniquePtr(
OS::SCreate(nullptr,
"%s"
@@ -4834,7 +4928,7 @@
success &= identity_hashcode_dart == hashcode_canonicalize_vm;
}
- if (!success && print_failure) {
+ if (!success) {
LogBlock lb;
THR_Print(
"Dart hashCode or Dart identityHashCode does not equal VM "
@@ -4896,6 +4990,15 @@
EXPECT(HashCodeEqualsCanonicalizeHash(kScript));
}
+TEST_CASE(HashCode_Symbol) {
+ const char* kScript =
+ "value() {\n"
+ " return #A;\n"
+ "}\n";
+ EXPECT(HashCodeEqualsCanonicalizeHash(kScript, kCalculateCanonizalizeHash,
+ /*check_identity=*/false));
+}
+
TEST_CASE(HashCode_True) {
const char* kScript =
"value() {\n"
@@ -4926,6 +5029,64 @@
/*check_identity=*/false));
}
+// Because we want to reuse CanonicalizeHash for hashCode, we should not have
+// collisions.
+TEST_CASE(CanonicalizeHash_Const_Instances) {
+ const char* kScript =
+ "class A {\n"
+ " final int n;\n"
+ " \n"
+ " const A(this.n);\n"
+ "}\n"
+ "\n"
+ "class B {\n"
+ " final int n;\n"
+ " \n"
+ " const B(this.n);\n"
+ "}\n"
+ "\n"
+ "valueA() {\n"
+ " return const A(5);\n"
+ "}\n"
+ "\n"
+ "valueB() {\n"
+ " return const B(5);\n"
+ "}\n";
+
+ Dart_Handle lib = TestCase::LoadTestScript(kScript, nullptr);
+ EXPECT_VALID(lib);
+
+ Dart_Handle value_a_result =
+ Dart_Invoke(lib, NewString("valueA"), 0, nullptr);
+ EXPECT_VALID(value_a_result);
+ Dart_Handle value_b_result =
+ Dart_Invoke(lib, NewString("valueB"), 0, nullptr);
+ EXPECT_VALID(value_b_result);
+
+ TransitionNativeToVM transition(Thread::Current());
+
+ const auto& value_a_dart = Instance::CheckedHandle(
+ Thread::Current()->zone(), Api::UnwrapHandle(value_a_result));
+ const auto& value_b_dart = Instance::CheckedHandle(
+ Thread::Current()->zone(), Api::UnwrapHandle(value_b_result));
+
+ const uint32_t canonicalize_hash_a = value_a_dart.CanonicalizeHash();
+ const uint32_t canonicalize_hash_b = value_b_dart.CanonicalizeHash();
+
+ bool success = canonicalize_hash_a != canonicalize_hash_b;
+
+ if (!success) {
+ LogBlock lb;
+ THR_Print("Hash collision between %s and %s\n", value_a_dart.ToCString(),
+ value_b_dart.ToCString());
+ THR_Print("VM CanonicalizeHash a %" Px32 " %" Pd32 "\n",
+ canonicalize_hash_a, canonicalize_hash_a);
+ THR_Print("VM CanonicalizeHash b %" Px32 " %" Pd32 "\n",
+ canonicalize_hash_b, canonicalize_hash_b);
+ }
+ EXPECT(success);
+}
+
TEST_CASE(LinkedHashMap_iteration) {
const char* kScript =
"makeMap() {\n"
@@ -4965,6 +5126,41 @@
EXPECT(!iterator.MoveNext());
}
+TEST_CASE(LinkedHashSet_iteration) {
+ const char* kScript =
+ "makeSet() {\n"
+ " var set = {'x', 'y', 'z', 'w'};\n"
+ " set.remove('y');\n"
+ " set.remove('w');\n"
+ " return set;\n"
+ "}";
+ Dart_Handle h_lib = TestCase::LoadTestScript(kScript, NULL);
+ EXPECT_VALID(h_lib);
+ Dart_Handle h_result = Dart_Invoke(h_lib, NewString("makeSet"), 0, NULL);
+ EXPECT_VALID(h_result);
+
+ TransitionNativeToVM transition(thread);
+ Instance& dart_set = Instance::Handle();
+ dart_set ^= Api::UnwrapHandle(h_result);
+ ASSERT(dart_set.IsLinkedHashSet());
+ const LinkedHashSet& cc_set = LinkedHashSet::Cast(dart_set);
+
+ EXPECT_EQ(2, cc_set.Length());
+
+ LinkedHashSet::Iterator iterator(cc_set);
+ Object& object = Object::Handle();
+
+ EXPECT(iterator.MoveNext());
+ object = iterator.CurrentKey();
+ EXPECT_STREQ("x", object.ToCString());
+
+ EXPECT(iterator.MoveNext());
+ object = iterator.CurrentKey();
+ EXPECT_STREQ("z", object.ToCString());
+
+ EXPECT(!iterator.MoveNext());
+}
+
static void CheckConcatAll(const String* data[], intptr_t n) {
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 866d0aa..7c6592f 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -287,7 +287,7 @@
VariableIndex first_local_index =
VariableIndex(parameter_index_start.value() > 0 ? 0 : -num_params);
VariableIndex next_free_index = scope->AllocateVariables(
- parameter_index_start, num_params, first_local_index, NULL,
+ function(), parameter_index_start, num_params, first_local_index, NULL,
&found_captured_variables);
num_stack_locals_ = -next_free_index.value();
diff --git a/runtime/vm/port.cc b/runtime/vm/port.cc
index c7312de..a671373 100644
--- a/runtime/vm/port.cc
+++ b/runtime/vm/port.cc
@@ -243,7 +243,9 @@
MutexLocker ml(mutex_);
auto it = ports_->TryLookup(receiver);
if (it == ports_->end()) return false;
- return (*it).handler->isolate()->group() == group;
+ auto isolate = (*it).handler->isolate();
+ if (isolate == nullptr) return false;
+ return isolate->group() == group;
}
void PortMap::Init() {
diff --git a/runtime/vm/port.h b/runtime/vm/port.h
index 1405362..4999ad4 100644
--- a/runtime/vm/port.h
+++ b/runtime/vm/port.h
@@ -63,6 +63,7 @@
// Returns the owning Isolate for port 'id'.
static Isolate* GetIsolate(Dart_Port id);
+ // Whether the destination port's isolate is a member of [isolate_group].
static bool IsReceiverInThisIsolateGroup(Dart_Port receiver,
IsolateGroup* group);
diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc
index 532eb63..2436574 100644
--- a/runtime/vm/profiler.cc
+++ b/runtime/vm/profiler.cc
@@ -19,6 +19,7 @@
#include "vm/object.h"
#include "vm/os.h"
#include "vm/profiler.h"
+#include "vm/profiler_service.h"
#include "vm/reusable_handles.h"
#include "vm/signal_handler.h"
#include "vm/simulator.h"
@@ -61,8 +62,8 @@
#ifndef PRODUCT
RelaxedAtomic<bool> Profiler::initialized_ = false;
-SampleBuffer* Profiler::sample_buffer_ = NULL;
-AllocationSampleBuffer* Profiler::allocation_sample_buffer_ = NULL;
+SampleBlockBuffer* Profiler::sample_block_buffer_ = nullptr;
+AllocationSampleBuffer* Profiler::allocation_sample_buffer_ = nullptr;
ProfilerCounters Profiler::counters_ = {};
void Profiler::Init() {
@@ -75,9 +76,9 @@
SetSamplePeriod(FLAG_profile_period);
// The profiler may have been shutdown previously, in which case the sample
// buffer will have already been initialized.
- if (sample_buffer_ == NULL) {
- intptr_t capacity = CalculateSampleBufferCapacity();
- sample_buffer_ = new SampleBuffer(capacity);
+ if (sample_block_buffer_ == nullptr) {
+ intptr_t num_blocks = CalculateSampleBufferCapacity();
+ sample_block_buffer_ = new SampleBlockBuffer(num_blocks);
Profiler::InitAllocationSampleBuffer();
}
ThreadInterrupter::Init();
@@ -92,14 +93,28 @@
}
}
+class SampleBlockCleanupVisitor : public IsolateVisitor {
+ public:
+ SampleBlockCleanupVisitor() = default;
+ virtual ~SampleBlockCleanupVisitor() = default;
+
+ void VisitIsolate(Isolate* isolate) {
+ isolate->set_current_allocation_sample_block(nullptr);
+ {
+ MutexLocker ml(isolate->current_sample_block_lock());
+ isolate->set_current_sample_block(nullptr);
+ }
+ }
+};
+
void Profiler::Cleanup() {
if (!FLAG_profiler) {
return;
}
ASSERT(initialized_);
ThreadInterrupter::Cleanup();
- delete sample_buffer_;
- sample_buffer_ = NULL;
+ SampleBlockCleanupVisitor visitor;
+ Isolate::VisitIsolates(&visitor);
initialized_ = false;
}
@@ -130,16 +145,16 @@
intptr_t Profiler::CalculateSampleBufferCapacity() {
if (FLAG_sample_buffer_duration <= 0) {
- return SampleBuffer::kDefaultBufferCapacity;
+ return SampleBlockBuffer::kDefaultBlockCount;
}
// Deeper stacks require more than a single Sample object to be represented
// correctly. These samples are chained, so we need to determine the worst
// case sample chain length for a single stack.
const intptr_t max_sample_chain_length =
FLAG_max_profile_depth / kMaxSamplesPerTick;
- const intptr_t buffer_size = FLAG_sample_buffer_duration *
- SamplesPerSecond() * max_sample_chain_length;
- return buffer_size;
+ const intptr_t sample_count = FLAG_sample_buffer_duration *
+ SamplesPerSecond() * max_sample_chain_length;
+ return (sample_count / SampleBlock::kSamplesPerBlock) + 1;
}
void Profiler::SetSamplePeriod(intptr_t period) {
@@ -156,7 +171,171 @@
SetSamplePeriod(FLAG_profile_period);
}
-SampleBuffer::SampleBuffer(intptr_t capacity) {
+SampleBlockBuffer::SampleBlockBuffer(intptr_t blocks,
+ intptr_t samples_per_block) {
+ const intptr_t size = Utils::RoundUp(
+ blocks * samples_per_block * sizeof(Sample), VirtualMemory::PageSize());
+ const bool kNotExecutable = false;
+ memory_ = VirtualMemory::Allocate(size, kNotExecutable, "dart-profiler");
+ if (memory_ == NULL) {
+ OUT_OF_MEMORY();
+ }
+ sample_buffer_ = reinterpret_cast<Sample*>(memory_->address());
+ blocks_ = new SampleBlock[blocks];
+ for (intptr_t i = 0; i < blocks; ++i) {
+ blocks_[i].Init(&sample_buffer_[i * samples_per_block], samples_per_block);
+ }
+ capacity_ = blocks;
+ cursor_ = 0;
+ free_list_head_ = nullptr;
+ free_list_tail_ = nullptr;
+}
+
+SampleBlockBuffer::~SampleBlockBuffer() {
+ delete[] blocks_;
+ blocks_ = nullptr;
+ delete memory_;
+ memory_ = nullptr;
+ capacity_ = 0;
+ cursor_ = 0;
+}
+
+SampleBlock* SampleBlockBuffer::ReserveSampleBlock() {
+ // Don't increment right away to avoid unlikely wrap-around errors.
+ if (cursor_.load() < capacity_) {
+ intptr_t index = cursor_.fetch_add(1u);
+ // Check the index again to make sure the last block hasn't been snatched
+ // from underneath us.
+ if (index < capacity_) {
+ return &blocks_[index];
+ }
+ }
+ // Try to re-use a previously freed SampleBlock once we've handed out each
+ // block at least once. Freed blocks aren't cleared immediately and are still
+ // valid until they're re-allocated, similar to how a ring buffer would clear
+ // the oldest samples.
+ SampleBlock* block = GetFreeBlock();
+ if (block != nullptr) {
+ block->Clear();
+ }
+ return block;
+}
+
+void SampleBlockBuffer::ProcessCompletedBlocks() {
+ Thread* thread = Thread::Current();
+ int64_t start = Dart_TimelineGetMicros();
+ for (intptr_t i = 0; i < capacity_; ++i) {
+ SampleBlock* block = &blocks_[i];
+ if (block->is_full() && !block->evictable()) {
+ if (Service::profiler_stream.enabled()) {
+ Profile profile(block->owner());
+ profile.Build(thread, nullptr, block);
+ ServiceEvent event(block->owner(), ServiceEvent::kCpuSamples);
+ event.set_cpu_profile(&profile);
+ Service::HandleEvent(&event);
+ }
+ block->evictable_ = true;
+ FreeBlock(block);
+ }
+ }
+ int64_t end = Dart_TimelineGetMicros();
+ Dart_TimelineEvent("SampleBlockBuffer::ProcessCompletedBlocks", start, end,
+ Dart_Timeline_Event_Duration, 0, nullptr, nullptr);
+}
+
+ProcessedSampleBuffer* SampleBlockBuffer::BuildProcessedSampleBuffer(
+ SampleFilter* filter,
+ ProcessedSampleBuffer* buffer) {
+ ASSERT(filter != NULL);
+ Thread* thread = Thread::Current();
+ Zone* zone = thread->zone();
+
+ if (buffer == nullptr) {
+ buffer = new (zone) ProcessedSampleBuffer();
+ }
+
+ for (intptr_t i = 0; i < capacity_; ++i) {
+ (&blocks_[i])->BuildProcessedSampleBuffer(filter, buffer);
+ }
+
+ return buffer;
+}
+
+Sample* SampleBlock::ReserveSample() {
+ if (full_.load()) {
+ return nullptr;
+ }
+ intptr_t slot = cursor_.fetch_add(1u);
+ if (slot + 1 == capacity_) {
+ full_ = true;
+ }
+ return (slot < capacity_) ? At(slot) : nullptr;
+}
+
+Sample* SampleBlock::ReserveSampleAndLink(Sample* previous) {
+ ASSERT(previous != nullptr);
+ SampleBlockBuffer* buffer = Profiler::sample_block_buffer();
+ Isolate* isolate = owner_;
+ ASSERT(isolate != nullptr);
+ Sample* next = previous->is_allocation_sample()
+ ? buffer->ReserveAllocationSample(isolate)
+ : buffer->ReserveCPUSample(isolate);
+ if (next == nullptr) {
+ return nullptr; // No blocks left, so drop sample.
+ }
+ next->Init(previous->port(), previous->timestamp(), previous->tid());
+ next->set_head_sample(false);
+ // Mark that previous continues at next.
+ previous->SetContinuation(next);
+ return next;
+}
+
+Sample* SampleBlockBuffer::ReserveCPUSample(Isolate* isolate) {
+ return ReserveSampleImpl(isolate, false);
+}
+
+Sample* SampleBlockBuffer::ReserveAllocationSample(Isolate* isolate) {
+ return ReserveSampleImpl(isolate, true);
+}
+
+Sample* SampleBlockBuffer::ReserveSampleImpl(Isolate* isolate,
+ bool allocation_sample) {
+ SampleBlock* block = allocation_sample
+ ? isolate->current_allocation_sample_block()
+ : isolate->current_sample_block();
+ Sample* sample = nullptr;
+ if (block != nullptr) {
+ sample = block->ReserveSample();
+ }
+ if (sample != nullptr) {
+ return sample;
+ }
+ SampleBlock* next = nullptr;
+ if (allocation_sample) {
+ // We only need to be locked while accessing the CPU sample block since
+ // Dart allocations can only occur on the mutator thread.
+ next = ReserveSampleBlock();
+ if (next == nullptr) {
+ // We're out of blocks to reserve. Drop the sample.
+ return nullptr;
+ }
+ isolate->set_current_allocation_sample_block(next);
+ } else {
+ MutexLocker locker(isolate->current_sample_block_lock());
+ next = ReserveSampleBlock();
+ if (next == nullptr) {
+ // We're out of blocks to reserve. Drop the sample.
+ return nullptr;
+ }
+ isolate->set_current_sample_block(next);
+ }
+ next->set_is_allocation_block(allocation_sample);
+ can_process_block_.store(true);
+ isolate->mutator_thread()->ScheduleInterrupts(Thread::kVMInterrupt);
+ return ReserveSampleImpl(isolate, allocation_sample);
+}
+
+AllocationSampleBuffer::AllocationSampleBuffer(intptr_t capacity) {
const intptr_t size =
Utils::RoundUp(capacity * sizeof(Sample), VirtualMemory::PageSize());
const bool kNotExecutable = false;
@@ -164,85 +343,24 @@
if (memory_ == NULL) {
OUT_OF_MEMORY();
}
-
- samples_ = reinterpret_cast<Sample*>(memory_->address());
- capacity_ = capacity;
+ Init(reinterpret_cast<Sample*>(memory_->address()), capacity);
+ free_sample_list_ = nullptr;
cursor_ = 0;
-
- if (FLAG_trace_profiler) {
- OS::PrintErr("Profiler holds %" Pd " samples\n", capacity);
- OS::PrintErr("Profiler sample is %" Pd " bytes\n", sizeof(Sample));
- OS::PrintErr("Profiler memory usage = %" Pd " bytes\n", size);
- }
- if (FLAG_sample_buffer_duration != 0) {
- OS::PrintErr(
- "** WARNING ** Custom sample buffer size provided via "
- "--sample-buffer-duration\n");
- OS::PrintErr(
- "The sample buffer can hold at least %ds worth of "
- "samples with stacks depths of up to %d, collected at "
- "a sample rate of %" Pd "Hz.\n",
- FLAG_sample_buffer_duration, FLAG_max_profile_depth,
- SamplesPerSecond());
- OS::PrintErr("The resulting sample buffer size is %" Pd " bytes.\n", size);
- }
-}
-
-AllocationSampleBuffer::AllocationSampleBuffer(intptr_t capacity)
- : SampleBuffer(capacity), mutex_(), free_sample_list_(NULL) {}
-
-SampleBuffer::~SampleBuffer() {
- delete memory_;
}
AllocationSampleBuffer::~AllocationSampleBuffer() {
-}
-
-Sample* SampleBuffer::At(intptr_t idx) const {
- ASSERT(idx >= 0);
- ASSERT(idx < capacity_);
- return &samples_[idx];
-}
-
-intptr_t SampleBuffer::ReserveSampleSlot() {
- ASSERT(samples_ != NULL);
- uintptr_t cursor = cursor_.fetch_add(1u);
- // Map back into sample buffer range.
- cursor = cursor % capacity_;
- return cursor;
-}
-
-Sample* SampleBuffer::ReserveSample() {
- return At(ReserveSampleSlot());
-}
-
-Sample* SampleBuffer::ReserveSampleAndLink(Sample* previous) {
- ASSERT(previous != NULL);
- intptr_t next_index = ReserveSampleSlot();
- Sample* next = At(next_index);
- next->Init(previous->port(), previous->timestamp(), previous->tid());
- next->set_head_sample(false);
- // Mark that previous continues at next.
- previous->SetContinuationIndex(next_index);
- return next;
+ delete memory_;
+ memory_ = nullptr;
}
void AllocationSampleBuffer::FreeAllocationSample(Sample* sample) {
MutexLocker ml(&mutex_);
- while (sample != NULL) {
- intptr_t continuation_index = -1;
- if (sample->is_continuation_sample()) {
- continuation_index = sample->continuation_index();
- }
+ while (sample != nullptr) {
+ Sample* next = sample->continuation_sample();
sample->Clear();
sample->set_next_free(free_sample_list_);
free_sample_list_ = sample;
-
- if (continuation_index != -1) {
- sample = At(continuation_index);
- } else {
- sample = NULL;
- }
+ sample = next;
}
}
@@ -255,7 +373,7 @@
uint8_t* free_sample_ptr = reinterpret_cast<uint8_t*>(free_sample);
return static_cast<intptr_t>((free_sample_ptr - samples_array_ptr) /
sizeof(Sample));
- } else if (cursor_ < static_cast<uintptr_t>(capacity_ - 1)) {
+ } else if (cursor_ < static_cast<intptr_t>(capacity_ - 1)) {
return cursor_ += 1;
} else {
return -1;
@@ -277,7 +395,7 @@
previous->native_allocation_size_bytes());
next->set_head_sample(false);
// Mark that previous continues at next.
- previous->SetContinuationIndex(next_index);
+ previous->SetContinuation(next);
return next;
}
@@ -957,12 +1075,16 @@
}
static Sample* SetupSample(Thread* thread,
- SampleBuffer* sample_buffer,
+ bool allocation_sample,
ThreadId tid) {
ASSERT(thread != NULL);
Isolate* isolate = thread->isolate();
- ASSERT(sample_buffer != NULL);
- Sample* sample = sample_buffer->ReserveSample();
+ SampleBlockBuffer* buffer = Profiler::sample_block_buffer();
+ Sample* sample = allocation_sample ? buffer->ReserveAllocationSample(isolate)
+ : buffer->ReserveCPUSample(isolate);
+ if (sample == nullptr) {
+ return nullptr;
+ }
sample->Init(isolate->main_port(), OS::GetCurrentMonotonicMicros(), tid);
uword vm_tag = thread->vm_tag();
#if defined(USING_SIMULATOR)
@@ -980,7 +1102,8 @@
return sample;
}
-static Sample* SetupSampleNative(SampleBuffer* sample_buffer, ThreadId tid) {
+static Sample* SetupSampleNative(AllocationSampleBuffer* sample_buffer,
+ ThreadId tid) {
Sample* sample = sample_buffer->ReserveSample();
if (sample == NULL) {
return NULL;
@@ -1129,11 +1252,10 @@
if (!CheckIsolate(isolate)) {
return;
}
-
const bool exited_dart_code = thread->HasExitedDartCode();
- SampleBuffer* sample_buffer = Profiler::sample_buffer();
- if (sample_buffer == NULL) {
+ SampleBlockBuffer* buffer = Profiler::sample_block_buffer();
+ if (buffer == nullptr) {
// Profiler not initialized.
return;
}
@@ -1157,24 +1279,30 @@
return;
}
- Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id());
+ Sample* sample =
+ SetupSample(thread, /*allocation_block*/ true, os_thread->trace_id());
+ if (sample == nullptr) {
+ // We were unable to assign a sample for this allocation.
+ counters_.sample_allocation_failure++;
+ return;
+ }
sample->SetAllocationCid(cid);
sample->set_allocation_identity_hash(identity_hash);
if (FLAG_profile_vm_allocation) {
ProfilerNativeStackWalker native_stack_walker(
&counters_, (isolate != NULL) ? isolate->main_port() : ILLEGAL_PORT,
- sample, sample_buffer, stack_lower, stack_upper, pc, fp, sp);
+ sample, isolate->current_allocation_sample_block(), stack_lower,
+ stack_upper, pc, fp, sp);
native_stack_walker.walk();
} else if (exited_dart_code) {
ProfilerDartStackWalker dart_exit_stack_walker(
- thread, sample, sample_buffer, pc, fp, /* allocation_sample*/ true);
+ thread, sample, isolate->current_allocation_sample_block(), pc, fp,
+ /* allocation_sample*/ true);
dart_exit_stack_walker.walk();
} else {
// Fall back.
uintptr_t pc = OS::GetProgramCounter();
- Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id());
- sample->SetAllocationCid(cid);
sample->SetAt(0, pc);
}
}
@@ -1231,20 +1359,16 @@
return sample;
}
-void Profiler::SampleThreadSingleFrame(Thread* thread, uintptr_t pc) {
+void Profiler::SampleThreadSingleFrame(Thread* thread,
+ Sample* sample,
+ uintptr_t pc) {
ASSERT(thread != NULL);
OSThread* os_thread = thread->os_thread();
ASSERT(os_thread != NULL);
Isolate* isolate = thread->isolate();
- SampleBuffer* sample_buffer = Profiler::sample_buffer();
- if (sample_buffer == NULL) {
- // Profiler not initialized.
- return;
- }
+ ASSERT(Profiler::sample_block_buffer() != nullptr);
- // Setup sample.
- Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id());
// Increment counter for vm tag.
VMTagCounters* counters = isolate->vm_tag_counters();
ASSERT(counters != NULL);
@@ -1306,22 +1430,37 @@
return;
}
+ SampleBlockBuffer* sample_block_buffer = Profiler::sample_block_buffer();
+ if (sample_block_buffer == nullptr) {
+ // Profiler not initialized.
+ return;
+ }
+
+ // Setup sample.
+ Sample* sample =
+ SetupSample(thread, /*allocation_block*/ false, os_thread->trace_id());
+ if (sample == nullptr) {
+ // We were unable to assign a sample for this profiler tick.
+ counters_.sample_allocation_failure++;
+ return;
+ }
+
if (thread->IsMutatorThread()) {
if (isolate->IsDeoptimizing()) {
counters_.single_frame_sample_deoptimizing.fetch_add(1);
- SampleThreadSingleFrame(thread, pc);
+ SampleThreadSingleFrame(thread, sample, pc);
return;
}
if (isolate->group()->compaction_in_progress()) {
// The Dart stack isn't fully walkable.
- SampleThreadSingleFrame(thread, pc);
+ SampleThreadSingleFrame(thread, sample, pc);
return;
}
}
if (!InitialRegisterCheck(pc, fp, sp)) {
counters_.single_frame_sample_register_check.fetch_add(1);
- SampleThreadSingleFrame(thread, pc);
+ SampleThreadSingleFrame(thread, sample, pc);
return;
}
@@ -1331,20 +1470,13 @@
&stack_upper)) {
counters_.single_frame_sample_get_and_validate_stack_bounds.fetch_add(1);
// Could not get stack boundary.
- SampleThreadSingleFrame(thread, pc);
+ SampleThreadSingleFrame(thread, sample, pc);
return;
}
// At this point we have a valid stack boundary for this isolate and
// know that our initial stack and frame pointers are within the boundary.
- SampleBuffer* sample_buffer = Profiler::sample_buffer();
- if (sample_buffer == NULL) {
- // Profiler not initialized.
- return;
- }
- // Setup sample.
- Sample* sample = SetupSample(thread, sample_buffer, os_thread->trace_id());
// Increment counter for vm tag.
VMTagCounters* counters = isolate->vm_tag_counters();
ASSERT(counters != NULL);
@@ -1354,9 +1486,11 @@
ProfilerNativeStackWalker native_stack_walker(
&counters_, (isolate != NULL) ? isolate->main_port() : ILLEGAL_PORT,
- sample, sample_buffer, stack_lower, stack_upper, pc, fp, sp);
+ sample, isolate->current_sample_block(), stack_lower, stack_upper, pc, fp,
+ sp);
const bool exited_dart_code = thread->HasExitedDartCode();
- ProfilerDartStackWalker dart_stack_walker(thread, sample, sample_buffer, pc,
+ ProfilerDartStackWalker dart_stack_walker(thread, sample,
+ isolate->current_sample_block(), pc,
fp, /* allocation_sample*/ false);
// All memory access is done inside CollectSample.
@@ -1480,12 +1614,14 @@
}
ProcessedSampleBuffer* SampleBuffer::BuildProcessedSampleBuffer(
- SampleFilter* filter) {
- ASSERT(filter != NULL);
+ SampleFilter* filter,
+ ProcessedSampleBuffer* buffer) {
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
- ProcessedSampleBuffer* buffer = new (zone) ProcessedSampleBuffer();
+ if (buffer == nullptr) {
+ buffer = new (zone) ProcessedSampleBuffer();
+ }
const intptr_t length = capacity();
for (intptr_t i = 0; i < length; i++) {
@@ -1498,12 +1634,6 @@
// An inner sample in a chain of samples.
continue;
}
- // If we're requesting all the native allocation samples, we don't care
- // whether or not we're in the same isolate as the sample.
- if (sample->port() != filter->port()) {
- // Another isolate.
- continue;
- }
if (sample->timestamp() == 0) {
// Empty.
continue;
@@ -1512,17 +1642,25 @@
// No frames.
continue;
}
- if (!filter->TimeFilterSample(sample)) {
- // Did not pass time filter.
- continue;
- }
- if (!filter->TaskFilterSample(sample)) {
- // Did not pass task filter.
- continue;
- }
- if (!filter->FilterSample(sample)) {
- // Did not pass filter.
- continue;
+ if (filter != nullptr) {
+ // If we're requesting all the native allocation samples, we don't care
+ // whether or not we're in the same isolate as the sample.
+ if (sample->port() != filter->port()) {
+ // Another isolate.
+ continue;
+ }
+ if (!filter->TimeFilterSample(sample)) {
+ // Did not pass time filter.
+ continue;
+ }
+ if (!filter->TaskFilterSample(sample)) {
+ // Did not pass task filter.
+ continue;
+ }
+ if (!filter->FilterSample(sample)) {
+ // Did not pass filter.
+ continue;
+ }
}
buffer->Add(BuildProcessedSample(sample, buffer->code_lookup_table()));
}
@@ -1577,7 +1715,7 @@
Sample* SampleBuffer::Next(Sample* sample) {
if (!sample->is_continuation_sample()) return NULL;
- Sample* next_sample = At(sample->continuation_index());
+ Sample* next_sample = sample->continuation_sample();
// Sanity check.
ASSERT(sample != next_sample);
// Detect invalid chaining.
diff --git a/runtime/vm/profiler.h b/runtime/vm/profiler.h
index 2f9ea17..dd30bcc 100644
--- a/runtime/vm/profiler.h
+++ b/runtime/vm/profiler.h
@@ -29,7 +29,7 @@
class Sample;
class AllocationSampleBuffer;
-class SampleBuffer;
+class SampleBlock;
class ProfileTrieNode;
#define PROFILER_COUNTERS(V) \
@@ -46,7 +46,8 @@
V(incomplete_sample_fp_bounds) \
V(incomplete_sample_fp_step) \
V(incomplete_sample_bad_pc) \
- V(failure_native_allocation_sample)
+ V(failure_native_allocation_sample) \
+ V(sample_allocation_failure)
struct ProfilerCounters {
#define DECLARE_PROFILER_COUNTER(name) RelaxedAtomic<int64_t> name;
@@ -69,7 +70,9 @@
// service protocol.
static void UpdateRunningState();
- static SampleBuffer* sample_buffer() { return sample_buffer_; }
+ static SampleBlockBuffer* sample_block_buffer() {
+ return sample_block_buffer_;
+ }
static AllocationSampleBuffer* allocation_sample_buffer() {
return allocation_sample_buffer_;
}
@@ -111,10 +114,12 @@
static intptr_t CalculateSampleBufferCapacity();
// Does not walk the thread's stack.
- static void SampleThreadSingleFrame(Thread* thread, uintptr_t pc);
+ static void SampleThreadSingleFrame(Thread* thread,
+ Sample* sample,
+ uintptr_t pc);
static RelaxedAtomic<bool> initialized_;
- static SampleBuffer* sample_buffer_;
+ static SampleBlockBuffer* sample_block_buffer_;
static AllocationSampleBuffer* allocation_sample_buffer_;
static ProfilerCounters counters_;
@@ -129,6 +134,8 @@
virtual void VisitSample(Sample* sample) = 0;
+ virtual void Reset() { visited_ = 0; }
+
intptr_t visited() const { return visited_; }
void IncrementVisited() { visited_++; }
@@ -189,11 +196,14 @@
// Each Sample holds a stack trace from an isolate.
class Sample {
public:
+ Sample() = default;
+
void Init(Dart_Port port, int64_t timestamp, ThreadId tid) {
Clear();
timestamp_ = timestamp;
tid_ = tid;
port_ = port;
+ next_ = nullptr;
}
Dart_Port port() const { return port_; }
@@ -214,7 +224,7 @@
vm_tag_ = VMTag::kInvalidTagId;
user_tag_ = UserTags::kDefaultUserTag;
state_ = 0;
- continuation_index_ = -1;
+ next_ = nullptr;
allocation_identity_hash_ = 0;
#if defined(DART_USE_TCMALLOC) && defined(DEBUG)
native_allocation_address_ = 0;
@@ -352,18 +362,14 @@
return ContinuationSampleBit::decode(state_);
}
- void SetContinuationIndex(intptr_t index) {
+ void SetContinuation(Sample* next) {
ASSERT(!is_continuation_sample());
- ASSERT(continuation_index_ == -1);
+ ASSERT(next_ == nullptr);
state_ = ContinuationSampleBit::update(true, state_);
- continuation_index_ = index;
- ASSERT(is_continuation_sample());
+ next_ = next;
}
- intptr_t continuation_index() const {
- ASSERT(is_continuation_sample());
- return continuation_index_;
- }
+ Sample* continuation_sample() const { return next_; }
intptr_t allocation_cid() const {
ASSERT(is_allocation_sample());
@@ -431,7 +437,7 @@
uword vm_tag_;
uword user_tag_;
uint32_t state_;
- int32_t continuation_index_;
+ Sample* next_;
uint32_t allocation_identity_hash_;
#if defined(DART_USE_TCMALLOC) && defined(DEBUG)
@@ -623,21 +629,26 @@
DISALLOW_COPY_AND_ASSIGN(CodeLookupTable);
};
-// Ring buffer of Samples that is (usually) shared by many isolates.
-class SampleBuffer {
+// Interface for a class that can create a ProcessedSampleBuffer.
+class ProcessedSampleBufferBuilder {
public:
- // Up to 1 minute @ 1000Hz, less if samples are deep.
- static const intptr_t kDefaultBufferCapacity = 60000;
+ virtual ~ProcessedSampleBufferBuilder() = default;
+ virtual ProcessedSampleBuffer* BuildProcessedSampleBuffer(
+ SampleFilter* filter,
+ ProcessedSampleBuffer* buffer = nullptr) = 0;
+};
- explicit SampleBuffer(intptr_t capacity = kDefaultBufferCapacity);
- virtual ~SampleBuffer();
+class SampleBuffer : public ProcessedSampleBufferBuilder {
+ public:
+ SampleBuffer() = default;
+ virtual ~SampleBuffer() = default;
- intptr_t capacity() const { return capacity_; }
-
- Sample* At(intptr_t idx) const;
- intptr_t ReserveSampleSlot();
- virtual Sample* ReserveSample();
- virtual Sample* ReserveSampleAndLink(Sample* previous);
+ virtual void Init(Sample* samples, intptr_t capacity) {
+ ASSERT(samples != nullptr);
+ ASSERT(capacity > 0);
+ samples_ = samples;
+ capacity_ = capacity;
+ }
void VisitSamples(SampleVisitor* visitor) {
ASSERT(visitor != NULL);
@@ -669,45 +680,218 @@
}
}
- ProcessedSampleBuffer* BuildProcessedSampleBuffer(SampleFilter* filter);
+ virtual Sample* ReserveSample() = 0;
+ virtual Sample* ReserveSampleAndLink(Sample* previous) = 0;
- intptr_t Size() { return memory_->size(); }
+ Sample* At(intptr_t idx) const {
+ ASSERT(idx >= 0);
+ ASSERT(idx < capacity_);
+ return &samples_[idx];
+ }
+
+ intptr_t capacity() const { return capacity_; }
+
+ virtual ProcessedSampleBuffer* BuildProcessedSampleBuffer(
+ SampleFilter* filter,
+ ProcessedSampleBuffer* buffer = nullptr);
protected:
- ProcessedSample* BuildProcessedSample(Sample* sample,
- const CodeLookupTable& clt);
Sample* Next(Sample* sample);
- VirtualMemory* memory_;
+ ProcessedSample* BuildProcessedSample(Sample* sample,
+ const CodeLookupTable& clt);
+
Sample* samples_;
intptr_t capacity_;
- RelaxedAtomic<uintptr_t> cursor_;
+
+ DISALLOW_COPY_AND_ASSIGN(SampleBuffer);
+};
+
+class SampleBlock : public SampleBuffer {
+ public:
+ // The default number of samples per block. Overridden by some tests.
+ static const intptr_t kSamplesPerBlock = 1000;
+
+ SampleBlock() = default;
+ virtual ~SampleBlock() = default;
+
+ void Clear() {
+ allocation_block_ = false;
+ cursor_ = 0;
+ full_ = false;
+ evictable_ = false;
+ next_free_ = nullptr;
+ }
+
+ // Returns the number of samples contained within this block.
+ intptr_t capacity() const { return capacity_; }
+
+ // Specify whether or not this block is used for assigning allocation
+ // samples.
+ void set_is_allocation_block(bool is_allocation_block) {
+ allocation_block_ = is_allocation_block;
+ }
+
+ Isolate* owner() const { return owner_; }
+ void set_owner(Isolate* isolate) { owner_ = isolate; }
+
+ // Manually marks the block as full so it can be processed and added back to
+ // the pool of available blocks.
+ void release_block() { full_.store(true); }
+
+ // When true, this sample block is considered complete and will no longer be
+ // used to assign new Samples. This block is **not** available for
+ // re-allocation simply because it's full. It must be processed by
+ // SampleBlockBuffer::ProcessCompletedBlocks before it can be considered
+ // evictable and available for re-allocation.
+ bool is_full() const { return full_.load(); }
+
+ // When true, this sample block is available for re-allocation.
+ bool evictable() const { return evictable_.load(); }
+
+ virtual Sample* ReserveSample();
+ virtual Sample* ReserveSampleAndLink(Sample* previous);
+
+ protected:
+ Isolate* owner_ = nullptr;
+ bool allocation_block_ = false;
+
+ intptr_t index_;
+ RelaxedAtomic<int> cursor_ = 0;
+ RelaxedAtomic<bool> full_ = false;
+ RelaxedAtomic<bool> evictable_ = false;
+
+ SampleBlock* next_free_ = nullptr;
private:
- DISALLOW_COPY_AND_ASSIGN(SampleBuffer);
+ friend class SampleBlockBuffer;
+
+ DISALLOW_COPY_AND_ASSIGN(SampleBlock);
+};
+
+class SampleBlockBuffer : public ProcessedSampleBufferBuilder {
+ public:
+ static const intptr_t kDefaultBlockCount = 60;
+
+ // Creates a SampleBlockBuffer with a predetermined number of blocks.
+ //
+ // Defaults to kDefaultBlockCount blocks. Block size is fixed to
+ // SampleBlock::kSamplesPerBlock samples per block, except for in tests.
+ explicit SampleBlockBuffer(
+ intptr_t blocks = kDefaultBlockCount,
+ intptr_t samples_per_block = SampleBlock::kSamplesPerBlock);
+
+ virtual ~SampleBlockBuffer();
+
+ void VisitSamples(SampleVisitor* visitor) {
+ ASSERT(visitor != NULL);
+ for (intptr_t i = 0; i < cursor_.load(); ++i) {
+ (&blocks_[i])->VisitSamples(visitor);
+ }
+ }
+
+ // Returns true when there is at least a single block that needs to be
+ // processed.
+ //
+ // NOTE: this should only be called from the interrupt handler as
+ // invocation will have the side effect of clearing the underlying flag.
+ bool process_blocks() { return can_process_block_.exchange(false); }
+
+ // Iterates over the blocks in the buffer and processes blocks marked as
+ // full. Processing consists of sending a service event with the samples from
+ // completed, unprocessed blocks and marking these blocks are evictable
+ // (i.e., safe to be re-allocated and re-used).
+ void ProcessCompletedBlocks();
+
+ // Reserves a sample for a CPU profile.
+ //
+ // Returns nullptr when a sample can't be reserved.
+ Sample* ReserveCPUSample(Isolate* isolate);
+
+ // Reserves a sample for a Dart object allocation profile.
+ //
+ // Returns nullptr when a sample can't be reserved.
+ Sample* ReserveAllocationSample(Isolate* isolate);
+
+ intptr_t Size() const { return memory_->size(); }
+
+ virtual ProcessedSampleBuffer* BuildProcessedSampleBuffer(
+ SampleFilter* filter,
+ ProcessedSampleBuffer* buffer = nullptr);
+
+ private:
+ Sample* ReserveSampleImpl(Isolate* isolate, bool allocation_sample);
+
+ // Returns nullptr if there are no available blocks.
+ SampleBlock* ReserveSampleBlock();
+
+ void FreeBlock(SampleBlock* block) {
+ ASSERT(block->next_free_ == nullptr);
+ MutexLocker ml(&free_block_lock_);
+ if (free_list_head_ == nullptr) {
+ free_list_head_ = block;
+ free_list_tail_ = block;
+ return;
+ }
+ free_list_tail_->next_free_ = block;
+ free_list_tail_ = block;
+ }
+
+ SampleBlock* GetFreeBlock() {
+ MutexLocker ml(&free_block_lock_);
+ if (free_list_head_ == nullptr) {
+ return nullptr;
+ }
+ SampleBlock* block = free_list_head_;
+ free_list_head_ = block->next_free_;
+ if (free_list_head_ == nullptr) {
+ free_list_tail_ = nullptr;
+ }
+ block->next_free_ = nullptr;
+ return block;
+ }
+
+ Mutex free_block_lock_;
+ RelaxedAtomic<bool> can_process_block_ = false;
+
+ // Sample block management.
+ RelaxedAtomic<int> cursor_;
+ SampleBlock* blocks_;
+ intptr_t capacity_;
+ SampleBlock* free_list_head_;
+ SampleBlock* free_list_tail_;
+
+ // Sample buffer management.
+ VirtualMemory* memory_;
+ Sample* sample_buffer_;
+ DISALLOW_COPY_AND_ASSIGN(SampleBlockBuffer);
};
class AllocationSampleBuffer : public SampleBuffer {
public:
- explicit AllocationSampleBuffer(intptr_t capacity = kDefaultBufferCapacity);
+ explicit AllocationSampleBuffer(intptr_t capacity = 60000);
virtual ~AllocationSampleBuffer();
- intptr_t ReserveSampleSlotLocked();
virtual Sample* ReserveSample();
virtual Sample* ReserveSampleAndLink(Sample* previous);
void FreeAllocationSample(Sample* sample);
+ intptr_t Size() { return memory_->size(); }
+
private:
+ intptr_t ReserveSampleSlotLocked();
+
Mutex mutex_;
Sample* free_sample_list_;
-
+ VirtualMemory* memory_;
+ RelaxedAtomic<int> cursor_ = 0;
DISALLOW_COPY_AND_ASSIGN(AllocationSampleBuffer);
};
intptr_t Profiler::Size() {
intptr_t size = 0;
- if (sample_buffer_ != nullptr) {
- size += sample_buffer_->Size();
+ if (sample_block_buffer_ != nullptr) {
+ size += sample_block_buffer_->Size();
}
if (allocation_sample_buffer_ != nullptr) {
size += allocation_sample_buffer_->Size();
diff --git a/runtime/vm/profiler_service.cc b/runtime/vm/profiler_service.cc
index a61fb94..e9f333e 100644
--- a/runtime/vm/profiler_service.cc
+++ b/runtime/vm/profiler_service.cc
@@ -7,6 +7,7 @@
#include "platform/text_buffer.h"
#include "vm/growable_array.h"
#include "vm/hash_map.h"
+#include "vm/heap/safepoint.h"
#include "vm/log.h"
#include "vm/malloc_hooks.h"
#include "vm/native_symbol.h"
@@ -15,6 +16,8 @@
#include "vm/profiler.h"
#include "vm/reusable_handles.h"
#include "vm/scope_timer.h"
+#include "vm/service.h"
+#include "vm/service_event.h"
#include "vm/timeline.h"
namespace dart {
@@ -919,7 +922,7 @@
ProfileBuilder(Thread* thread,
SampleFilter* filter,
- SampleBuffer* sample_buffer,
+ ProcessedSampleBufferBuilder* sample_buffer,
Profile* profile)
: thread_(thread),
vm_isolate_(Dart::vm_isolate()),
@@ -932,8 +935,6 @@
inlined_functions_cache_(new ProfileCodeInlinedFunctionsCache()),
samples_(NULL),
info_kind_(kNone) {
- ASSERT((sample_buffer_ == Profiler::sample_buffer()) ||
- (sample_buffer_ == Profiler::allocation_sample_buffer()));
ASSERT(profile_ != NULL);
}
@@ -975,7 +976,7 @@
bool FilterSamples() {
ScopeTimer sw("ProfileBuilder::FilterSamples", FLAG_trace_profiler);
- ASSERT(sample_buffer_ != NULL);
+ ASSERT(sample_buffer_ != nullptr);
samples_ = sample_buffer_->BuildProcessedSampleBuffer(filter_);
profile_->samples_ = samples_;
profile_->sample_count_ = samples_->length();
@@ -1439,7 +1440,7 @@
Thread* thread_;
Isolate* vm_isolate_;
SampleFilter* filter_;
- SampleBuffer* sample_buffer_;
+ ProcessedSampleBufferBuilder* sample_buffer_;
Profile* profile_;
const AbstractCode null_code_;
const Function& null_function_;
@@ -1466,11 +1467,10 @@
void Profile::Build(Thread* thread,
SampleFilter* filter,
- SampleBuffer* sample_buffer) {
+ ProcessedSampleBufferBuilder* sample_buffer) {
// Disable thread interrupts while processing the buffer.
DisableThreadInterruptsScope dtis(thread);
ThreadInterrupter::SampleBufferReaderScope scope;
-
ProfileBuilder builder(thread, filter, sample_buffer, this);
builder.Build();
}
@@ -1722,12 +1722,16 @@
}
void Profile::PrintProfileJSON(JSONStream* stream, bool include_code_samples) {
- ScopeTimer sw("Profile::PrintProfileJSON", FLAG_trace_profiler);
JSONObject obj(stream);
- obj.AddProperty("type", "CpuSamples");
- PrintHeaderJSON(&obj);
+ PrintProfileJSON(&obj, include_code_samples);
+}
+
+void Profile::PrintProfileJSON(JSONObject* obj, bool include_code_samples) {
+ ScopeTimer sw("Profile::PrintProfileJSON", FLAG_trace_profiler);
+ obj->AddProperty("type", "CpuSamples");
+ PrintHeaderJSON(obj);
if (include_code_samples) {
- JSONArray codes(&obj, "_codes");
+ JSONArray codes(obj, "_codes");
for (intptr_t i = 0; i < live_code_->length(); i++) {
ProfileCode* code = live_code_->At(i);
ASSERT(code != NULL);
@@ -1746,30 +1750,30 @@
}
{
- JSONArray functions(&obj, "functions");
+ JSONArray functions(obj, "functions");
for (intptr_t i = 0; i < functions_->length(); i++) {
ProfileFunction* function = functions_->At(i);
ASSERT(function != NULL);
function->PrintToJSONArray(&functions);
}
}
- PrintSamplesJSON(&obj, include_code_samples);
+ PrintSamplesJSON(obj, include_code_samples);
}
void ProfilerService::PrintJSONImpl(Thread* thread,
JSONStream* stream,
SampleFilter* filter,
- SampleBuffer* sample_buffer,
+ ProcessedSampleBufferBuilder* buffer,
bool include_code_samples) {
Isolate* isolate = thread->isolate();
// We should bail out in service.cc if the profiler is disabled.
- ASSERT(sample_buffer != NULL);
+ ASSERT(buffer != nullptr);
StackZone zone(thread);
HANDLESCOPE(thread);
Profile profile(isolate);
- profile.Build(thread, filter, sample_buffer);
+ profile.Build(thread, filter, buffer);
profile.PrintProfileJSON(stream, include_code_samples);
}
@@ -1795,7 +1799,7 @@
Isolate* isolate = thread->isolate();
NoAllocationSampleFilter filter(isolate->main_port(), Thread::kMutatorTask,
time_origin_micros, time_extent_micros);
- PrintJSONImpl(thread, stream, &filter, Profiler::sample_buffer(),
+ PrintJSONImpl(thread, stream, &filter, Profiler::sample_block_buffer(),
include_code_samples);
}
@@ -1820,7 +1824,7 @@
Isolate* isolate = thread->isolate();
AllocationSampleFilter filter(isolate->main_port(), Thread::kMutatorTask,
time_origin_micros, time_extent_micros);
- PrintJSONImpl(thread, stream, &filter, Profiler::sample_buffer(), true);
+ PrintJSONImpl(thread, stream, &filter, Profiler::sample_block_buffer(), true);
}
class ClassAllocationSampleFilter : public SampleFilter {
@@ -1856,7 +1860,7 @@
ClassAllocationSampleFilter filter(isolate->main_port(), cls,
Thread::kMutatorTask, time_origin_micros,
time_extent_micros);
- PrintJSONImpl(thread, stream, &filter, Profiler::sample_buffer(), true);
+ PrintJSONImpl(thread, stream, &filter, Profiler::sample_block_buffer(), true);
}
void ProfilerService::PrintNativeAllocationJSON(JSONStream* stream,
@@ -1870,8 +1874,8 @@
}
void ProfilerService::ClearSamples() {
- SampleBuffer* sample_buffer = Profiler::sample_buffer();
- if (sample_buffer == NULL) {
+ SampleBlockBuffer* sample_block_buffer = Profiler::sample_block_buffer();
+ if (sample_block_buffer == nullptr) {
return;
}
@@ -1883,7 +1887,7 @@
ThreadInterrupter::SampleBufferReaderScope scope;
ClearProfileVisitor clear_profile(isolate);
- sample_buffer->VisitSamples(&clear_profile);
+ sample_block_buffer->VisitSamples(&clear_profile);
}
#endif // !PRODUCT
diff --git a/runtime/vm/profiler_service.h b/runtime/vm/profiler_service.h
index 8009207..1c02db3 100644
--- a/runtime/vm/profiler_service.h
+++ b/runtime/vm/profiler_service.h
@@ -367,7 +367,9 @@
explicit Profile(Isolate* isolate);
// Build a filtered model using |filter|.
- void Build(Thread* thread, SampleFilter* filter, SampleBuffer* sample_buffer);
+ void Build(Thread* thread,
+ SampleFilter* filter,
+ ProcessedSampleBufferBuilder* sample_block_buffer);
// After building:
int64_t min_time() const { return min_time_; }
@@ -383,6 +385,7 @@
ProfileCode* GetCodeFromPC(uword pc, int64_t timestamp);
void PrintProfileJSON(JSONStream* stream, bool include_code_samples);
+ void PrintProfileJSON(JSONObject* obj, bool include_code_samples);
ProfileFunction* FindFunction(const Function& function);
@@ -445,7 +448,7 @@
static void PrintJSONImpl(Thread* thread,
JSONStream* stream,
SampleFilter* filter,
- SampleBuffer* sample_buffer,
+ ProcessedSampleBufferBuilder* buffer,
bool include_code_samples);
};
diff --git a/runtime/vm/profiler_test.cc b/runtime/vm/profiler_test.cc
index 1829169..1171458 100644
--- a/runtime/vm/profiler_test.cc
+++ b/runtime/vm/profiler_test.cc
@@ -22,6 +22,12 @@
DECLARE_FLAG(int, max_profile_depth);
DECLARE_FLAG(int, optimization_counter_threshold);
+// SampleVisitor ignores samples with timestamp == 0.
+const int64_t kValidTimeStamp = 1;
+
+// SampleVisitor ignores samples with pc == 0.
+const uword kValidPc = 0xFF;
+
// Some tests are written assuming native stack trace profiling is disabled.
class DisableNativeProfileScope : public ValueObject {
public:
@@ -71,87 +77,123 @@
const intptr_t FLAG_max_profile_depth_;
};
-class ProfileSampleBufferTestHelper {
+class ProfileSampleBufferTestHelper : public SampleVisitor {
public:
- static intptr_t IterateCount(const Dart_Port port,
- const SampleBuffer& sample_buffer) {
- intptr_t c = 0;
- for (intptr_t i = 0; i < sample_buffer.capacity(); i++) {
- Sample* sample = sample_buffer.At(i);
- if (sample->port() != port) {
- continue;
- }
- c++;
- }
- return c;
+ explicit ProfileSampleBufferTestHelper(Dart_Port port)
+ : SampleVisitor(port) {}
+
+ void VisitSample(Sample* sample) { sum_ += sample->At(0); }
+
+ void Reset() {
+ sum_ = 0;
+ SampleVisitor::Reset();
}
- static intptr_t IterateSumPC(const Dart_Port port,
- const SampleBuffer& sample_buffer) {
- intptr_t c = 0;
- for (intptr_t i = 0; i < sample_buffer.capacity(); i++) {
- Sample* sample = sample_buffer.At(i);
- if (sample->port() != port) {
- continue;
- }
- c += sample->At(0);
- }
- return c;
- }
+ intptr_t sum() const { return sum_; }
+
+ private:
+ intptr_t sum_ = 0;
};
+void VisitSamples(SampleBlockBuffer* buffer, SampleVisitor* visitor) {
+ // Mark the completed blocks as free so they can be re-used.
+ buffer->ProcessCompletedBlocks();
+ visitor->Reset();
+ buffer->VisitSamples(visitor);
+}
+
TEST_CASE(Profiler_SampleBufferWrapTest) {
- SampleBuffer* sample_buffer = new SampleBuffer(3);
+ Isolate* isolate = Isolate::Current();
+ SampleBlockBuffer* sample_buffer = new SampleBlockBuffer(3, 1);
Dart_Port i = 123;
- EXPECT_EQ(0, ProfileSampleBufferTestHelper::IterateSumPC(i, *sample_buffer));
+ ProfileSampleBufferTestHelper visitor(i);
+
+ VisitSamples(sample_buffer, &visitor);
+ EXPECT_EQ(0, visitor.sum());
Sample* s;
- s = sample_buffer->ReserveSample();
- s->Init(i, 0, 0);
+
+ s = sample_buffer->ReserveCPUSample(isolate);
+ s->Init(i, kValidTimeStamp, 0);
s->SetAt(0, 2);
- EXPECT_EQ(2, ProfileSampleBufferTestHelper::IterateSumPC(i, *sample_buffer));
- s = sample_buffer->ReserveSample();
- s->Init(i, 0, 0);
+ VisitSamples(sample_buffer, &visitor);
+ EXPECT_EQ(2, visitor.sum());
+
+ s = sample_buffer->ReserveCPUSample(isolate);
+ s->Init(i, kValidTimeStamp, 0);
s->SetAt(0, 4);
- EXPECT_EQ(6, ProfileSampleBufferTestHelper::IterateSumPC(i, *sample_buffer));
- s = sample_buffer->ReserveSample();
- s->Init(i, 0, 0);
+ VisitSamples(sample_buffer, &visitor);
+ EXPECT_EQ(6, visitor.sum());
+
+ s = sample_buffer->ReserveCPUSample(isolate);
+ s->Init(i, kValidTimeStamp, 0);
s->SetAt(0, 6);
- EXPECT_EQ(12, ProfileSampleBufferTestHelper::IterateSumPC(i, *sample_buffer));
- s = sample_buffer->ReserveSample();
- s->Init(i, 0, 0);
+ VisitSamples(sample_buffer, &visitor);
+ EXPECT_EQ(12, visitor.sum());
+
+ // Mark the completed blocks as free so they can be re-used.
+ sample_buffer->ProcessCompletedBlocks();
+
+ s = sample_buffer->ReserveCPUSample(isolate);
+ s->Init(i, kValidTimeStamp, 0);
s->SetAt(0, 8);
- EXPECT_EQ(18, ProfileSampleBufferTestHelper::IterateSumPC(i, *sample_buffer));
+ VisitSamples(sample_buffer, &visitor);
+ EXPECT_EQ(18, visitor.sum());
+ {
+ MutexLocker ml(isolate->current_sample_block_lock());
+ isolate->set_current_sample_block(nullptr);
+ }
delete sample_buffer;
}
TEST_CASE(Profiler_SampleBufferIterateTest) {
- SampleBuffer* sample_buffer = new SampleBuffer(3);
+ Isolate* isolate = Isolate::Current();
+ SampleBlockBuffer* sample_buffer = new SampleBlockBuffer(3, 1);
Dart_Port i = 123;
- EXPECT_EQ(0, ProfileSampleBufferTestHelper::IterateCount(i, *sample_buffer));
+ ProfileSampleBufferTestHelper visitor(i);
+
+ sample_buffer->VisitSamples(&visitor);
+ EXPECT_EQ(0, visitor.visited());
Sample* s;
- s = sample_buffer->ReserveSample();
- s->Init(i, 0, 0);
- EXPECT_EQ(1, ProfileSampleBufferTestHelper::IterateCount(i, *sample_buffer));
- s = sample_buffer->ReserveSample();
- s->Init(i, 0, 0);
- EXPECT_EQ(2, ProfileSampleBufferTestHelper::IterateCount(i, *sample_buffer));
- s = sample_buffer->ReserveSample();
- s->Init(i, 0, 0);
- EXPECT_EQ(3, ProfileSampleBufferTestHelper::IterateCount(i, *sample_buffer));
- s = sample_buffer->ReserveSample();
- s->Init(i, 0, 0);
- EXPECT_EQ(3, ProfileSampleBufferTestHelper::IterateCount(i, *sample_buffer));
+ s = sample_buffer->ReserveCPUSample(isolate);
+ s->Init(i, kValidTimeStamp, 0);
+ s->SetAt(0, kValidPc);
+ VisitSamples(sample_buffer, &visitor);
+ EXPECT_EQ(1, visitor.visited());
+
+ s = sample_buffer->ReserveCPUSample(isolate);
+ s->Init(i, kValidTimeStamp, 0);
+ s->SetAt(0, kValidPc);
+ VisitSamples(sample_buffer, &visitor);
+ EXPECT_EQ(2, visitor.visited());
+
+ s = sample_buffer->ReserveCPUSample(isolate);
+ s->Init(i, kValidTimeStamp, 0);
+ s->SetAt(0, kValidPc);
+ VisitSamples(sample_buffer, &visitor);
+ EXPECT_EQ(3, visitor.visited());
+
+ s = sample_buffer->ReserveCPUSample(isolate);
+ s->Init(i, kValidTimeStamp, 0);
+ s->SetAt(0, kValidPc);
+ VisitSamples(sample_buffer, &visitor);
+ EXPECT_EQ(3, visitor.visited());
+
+ {
+ MutexLocker ml(isolate->current_sample_block_lock());
+ isolate->set_current_sample_block(nullptr);
+ }
delete sample_buffer;
}
TEST_CASE(Profiler_AllocationSampleTest) {
Isolate* isolate = Isolate::Current();
- SampleBuffer* sample_buffer = new SampleBuffer(3);
- Sample* sample = sample_buffer->ReserveSample();
+ SampleBlockBuffer* sample_buffer = new SampleBlockBuffer(1, 1);
+ Sample* sample = sample_buffer->ReserveAllocationSample(isolate);
sample->Init(isolate->main_port(), 0, 0);
sample->set_metadata(99);
sample->set_is_allocation_sample(true);
EXPECT_EQ(99, sample->allocation_cid());
+ isolate->set_current_allocation_sample_block(nullptr);
delete sample_buffer;
}
@@ -443,7 +485,7 @@
AllocationFilter filter(isolate->main_port(), class_a.id(),
before_allocations_micros,
allocation_extent_micros);
- profile.Build(thread, &filter, Profiler::sample_buffer());
+ profile.Build(thread, &filter, Profiler::sample_block_buffer());
// We should have 1 allocation sample.
EXPECT_EQ(1, profile.sample_count());
ProfileStackWalker walker(&profile);
@@ -471,7 +513,7 @@
Profile profile(isolate);
AllocationFilter filter(isolate->main_port(), class_a.id(),
Dart_TimelineGetMicros(), 16000);
- profile.Build(thread, &filter, Profiler::sample_buffer());
+ profile.Build(thread, &filter, Profiler::sample_block_buffer());
// We should have no allocation samples because none occured within
// the specified time range.
EXPECT_EQ(0, profile.sample_count());
@@ -561,7 +603,7 @@
// Filter for the class in the time range.
NativeAllocationSampleFilter filter(before_allocations_micros,
allocation_extent_micros);
- profile.Build(thread, &filter, Profiler::sample_buffer());
+ profile.Build(thread, &filter, Profiler::sample_block_buffer());
// We should have 0 allocation samples since we freed the memory.
EXPECT_EQ(0, profile.sample_count());
}
@@ -574,7 +616,7 @@
HANDLESCOPE(thread);
Profile profile(isolate);
NativeAllocationSampleFilter filter(Dart_TimelineGetMicros(), 16000);
- profile.Build(thread, &filter, Profiler::sample_buffer());
+ profile.Build(thread, &filter, Profiler::sample_block_buffer());
// We should have no allocation samples because none occured within
// the specified time range.
EXPECT_EQ(0, profile.sample_count());
@@ -620,7 +662,7 @@
HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate->main_port(), class_a.id());
- profile.Build(thread, &filter, Profiler::sample_buffer());
+ profile.Build(thread, &filter, Profiler::sample_block_buffer());
// We should have no allocation samples.
EXPECT_EQ(0, profile.sample_count());
}
@@ -637,7 +679,7 @@
HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate->main_port(), class_a.id());
- profile.Build(thread, &filter, Profiler::sample_buffer());
+ profile.Build(thread, &filter, Profiler::sample_block_buffer());
// We should have one allocation sample.
EXPECT_EQ(1, profile.sample_count());
ProfileStackWalker walker(&profile);
@@ -667,7 +709,7 @@
HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate->main_port(), class_a.id());
- profile.Build(thread, &filter, Profiler::sample_buffer());
+ profile.Build(thread, &filter, Profiler::sample_block_buffer());
// We should still only have one allocation sample.
EXPECT_EQ(1, profile.sample_count());
}
@@ -705,7 +747,7 @@
HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate->main_port(), class_a.id());
- profile.Build(thread, &filter, Profiler::sample_buffer());
+ profile.Build(thread, &filter, Profiler::sample_block_buffer());
// We should have no allocation samples.
EXPECT_EQ(0, profile.sample_count());
}
@@ -725,7 +767,7 @@
HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate->main_port(), class_a.id());
- profile.Build(thread, &filter, Profiler::sample_buffer());
+ profile.Build(thread, &filter, Profiler::sample_block_buffer());
// We should have three allocation samples.
EXPECT_EQ(3, profile.sample_count());
ProfileStackWalker walker(&profile);
@@ -780,7 +822,7 @@
HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate->main_port(), class_a.id());
- profile.Build(thread, &filter, Profiler::sample_buffer());
+ profile.Build(thread, &filter, Profiler::sample_block_buffer());
// We should have no allocation samples.
EXPECT_EQ(0, profile.sample_count());
}
@@ -800,7 +842,7 @@
HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate->main_port(), class_a.id());
- profile.Build(thread, &filter, Profiler::sample_buffer());
+ profile.Build(thread, &filter, Profiler::sample_block_buffer());
// We should have three allocation samples.
EXPECT_EQ(3, profile.sample_count());
ProfileStackWalker walker(&profile, true);
@@ -850,7 +892,7 @@
HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate->main_port(), double_class.id());
- profile.Build(thread, &filter, Profiler::sample_buffer());
+ profile.Build(thread, &filter, Profiler::sample_block_buffer());
// We should have no allocation samples.
EXPECT_EQ(0, profile.sample_count());
}
@@ -863,7 +905,7 @@
HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate->main_port(), double_class.id());
- profile.Build(thread, &filter, Profiler::sample_buffer());
+ profile.Build(thread, &filter, Profiler::sample_block_buffer());
// We should have one allocation sample.
EXPECT_EQ(1, profile.sample_count());
ProfileStackWalker walker(&profile);
@@ -885,7 +927,7 @@
HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate->main_port(), double_class.id());
- profile.Build(thread, &filter, Profiler::sample_buffer());
+ profile.Build(thread, &filter, Profiler::sample_block_buffer());
// We should still only have one allocation sample.
EXPECT_EQ(1, profile.sample_count());
}
@@ -912,7 +954,7 @@
HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate->main_port(), array_class.id());
- profile.Build(thread, &filter, Profiler::sample_buffer());
+ profile.Build(thread, &filter, Profiler::sample_block_buffer());
// We should have no allocation samples.
EXPECT_EQ(0, profile.sample_count());
}
@@ -925,7 +967,7 @@
HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate->main_port(), array_class.id());
- profile.Build(thread, &filter, Profiler::sample_buffer());
+ profile.Build(thread, &filter, Profiler::sample_block_buffer());
// We should have one allocation sample.
EXPECT_EQ(1, profile.sample_count());
ProfileStackWalker walker(&profile);
@@ -947,7 +989,7 @@
HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate->main_port(), array_class.id());
- profile.Build(thread, &filter, Profiler::sample_buffer());
+ profile.Build(thread, &filter, Profiler::sample_block_buffer());
// We should still only have one allocation sample.
EXPECT_EQ(1, profile.sample_count());
}
@@ -969,7 +1011,7 @@
HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate->main_port(), array_class.id());
- profile.Build(thread, &filter, Profiler::sample_buffer());
+ profile.Build(thread, &filter, Profiler::sample_block_buffer());
// We should have no allocation samples, since empty
// growable lists use a shared backing.
EXPECT_EQ(0, profile.sample_count());
@@ -999,7 +1041,7 @@
HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate->main_port(), context_class.id());
- profile.Build(thread, &filter, Profiler::sample_buffer());
+ profile.Build(thread, &filter, Profiler::sample_block_buffer());
// We should have no allocation samples.
EXPECT_EQ(0, profile.sample_count());
}
@@ -1012,7 +1054,7 @@
HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate->main_port(), context_class.id());
- profile.Build(thread, &filter, Profiler::sample_buffer());
+ profile.Build(thread, &filter, Profiler::sample_block_buffer());
// We should have one allocation sample.
EXPECT_EQ(1, profile.sample_count());
ProfileStackWalker walker(&profile);
@@ -1032,7 +1074,7 @@
HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate->main_port(), context_class.id());
- profile.Build(thread, &filter, Profiler::sample_buffer());
+ profile.Build(thread, &filter, Profiler::sample_block_buffer());
// We should still only have one allocation sample.
EXPECT_EQ(1, profile.sample_count());
}
@@ -1073,7 +1115,7 @@
Profile profile(isolate);
AllocationFilter filter(isolate->main_port(), closure_class.id());
filter.set_enable_vm_ticks(true);
- profile.Build(thread, &filter, Profiler::sample_buffer());
+ profile.Build(thread, &filter, Profiler::sample_block_buffer());
// We should have one allocation sample.
EXPECT_EQ(1, profile.sample_count());
ProfileStackWalker walker(&profile);
@@ -1097,7 +1139,7 @@
Profile profile(isolate);
AllocationFilter filter(isolate->main_port(), closure_class.id());
filter.set_enable_vm_ticks(true);
- profile.Build(thread, &filter, Profiler::sample_buffer());
+ profile.Build(thread, &filter, Profiler::sample_block_buffer());
// We should still only have one allocation sample.
EXPECT_EQ(1, profile.sample_count());
}
@@ -1127,7 +1169,7 @@
HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate->main_port(), float32_list_class.id());
- profile.Build(thread, &filter, Profiler::sample_buffer());
+ profile.Build(thread, &filter, Profiler::sample_block_buffer());
// We should have no allocation samples.
EXPECT_EQ(0, profile.sample_count());
}
@@ -1140,7 +1182,7 @@
HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate->main_port(), float32_list_class.id());
- profile.Build(thread, &filter, Profiler::sample_buffer());
+ profile.Build(thread, &filter, Profiler::sample_block_buffer());
// We should have one allocation sample.
EXPECT_EQ(1, profile.sample_count());
ProfileStackWalker walker(&profile);
@@ -1162,7 +1204,7 @@
HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate->main_port(), float32_list_class.id());
- profile.Build(thread, &filter, Profiler::sample_buffer());
+ profile.Build(thread, &filter, Profiler::sample_block_buffer());
// We should still only have one allocation sample.
EXPECT_EQ(1, profile.sample_count());
}
@@ -1175,7 +1217,7 @@
HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate->main_port(), float32_list_class.id());
- profile.Build(thread, &filter, Profiler::sample_buffer());
+ profile.Build(thread, &filter, Profiler::sample_block_buffer());
// We should now have two allocation samples.
EXPECT_EQ(2, profile.sample_count());
}
@@ -1207,7 +1249,7 @@
HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate->main_port(), one_byte_string_class.id());
- profile.Build(thread, &filter, Profiler::sample_buffer());
+ profile.Build(thread, &filter, Profiler::sample_block_buffer());
// We should have no allocation samples.
EXPECT_EQ(0, profile.sample_count());
}
@@ -1220,7 +1262,7 @@
HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate->main_port(), one_byte_string_class.id());
- profile.Build(thread, &filter, Profiler::sample_buffer());
+ profile.Build(thread, &filter, Profiler::sample_block_buffer());
// We should still only have one allocation sample.
EXPECT_EQ(1, profile.sample_count());
ProfileStackWalker walker(&profile);
@@ -1240,7 +1282,7 @@
HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate->main_port(), one_byte_string_class.id());
- profile.Build(thread, &filter, Profiler::sample_buffer());
+ profile.Build(thread, &filter, Profiler::sample_block_buffer());
// We should still only have one allocation sample.
EXPECT_EQ(1, profile.sample_count());
}
@@ -1253,7 +1295,7 @@
HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate->main_port(), one_byte_string_class.id());
- profile.Build(thread, &filter, Profiler::sample_buffer());
+ profile.Build(thread, &filter, Profiler::sample_block_buffer());
// We should now have two allocation samples.
EXPECT_EQ(2, profile.sample_count());
}
@@ -1285,7 +1327,7 @@
HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate->main_port(), one_byte_string_class.id());
- profile.Build(thread, &filter, Profiler::sample_buffer());
+ profile.Build(thread, &filter, Profiler::sample_block_buffer());
// We should have no allocation samples.
EXPECT_EQ(0, profile.sample_count());
}
@@ -1298,7 +1340,7 @@
HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate->main_port(), one_byte_string_class.id());
- profile.Build(thread, &filter, Profiler::sample_buffer());
+ profile.Build(thread, &filter, Profiler::sample_block_buffer());
// We should still only have one allocation sample.
EXPECT_EQ(1, profile.sample_count());
ProfileStackWalker walker(&profile);
@@ -1324,7 +1366,7 @@
HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate->main_port(), one_byte_string_class.id());
- profile.Build(thread, &filter, Profiler::sample_buffer());
+ profile.Build(thread, &filter, Profiler::sample_block_buffer());
// We should still only have one allocation sample.
EXPECT_EQ(1, profile.sample_count());
}
@@ -1337,7 +1379,7 @@
HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate->main_port(), one_byte_string_class.id());
- profile.Build(thread, &filter, Profiler::sample_buffer());
+ profile.Build(thread, &filter, Profiler::sample_block_buffer());
// We should now have two allocation samples.
EXPECT_EQ(2, profile.sample_count());
}
@@ -1393,7 +1435,7 @@
HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate->main_port(), class_a.id());
- profile.Build(thread, &filter, Profiler::sample_buffer());
+ profile.Build(thread, &filter, Profiler::sample_block_buffer());
// We should have no allocation samples.
EXPECT_EQ(0, profile.sample_count());
}
@@ -1411,7 +1453,7 @@
HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate->main_port(), class_a.id());
- profile.Build(thread, &filter, Profiler::sample_buffer());
+ profile.Build(thread, &filter, Profiler::sample_block_buffer());
// We should have 50,000 allocation samples.
EXPECT_EQ(50000, profile.sample_count());
{
@@ -1540,7 +1582,7 @@
HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate->main_port(), class_a.id());
- profile.Build(thread, &filter, Profiler::sample_buffer());
+ profile.Build(thread, &filter, Profiler::sample_block_buffer());
// We should have no allocation samples.
EXPECT_EQ(0, profile.sample_count());
}
@@ -1557,7 +1599,7 @@
HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate->main_port(), class_a.id());
- profile.Build(thread, &filter, Profiler::sample_buffer());
+ profile.Build(thread, &filter, Profiler::sample_block_buffer());
EXPECT_EQ(1, profile.sample_count());
ProfileStackWalker walker(&profile, true);
@@ -1633,7 +1675,7 @@
HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate->main_port(), class_a.id());
- profile.Build(thread, &filter, Profiler::sample_buffer());
+ profile.Build(thread, &filter, Profiler::sample_block_buffer());
// We should have 1 allocation sample.
EXPECT_EQ(1, profile.sample_count());
ProfileStackWalker walker(&profile);
@@ -1728,7 +1770,7 @@
HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate->main_port(), class_a.id());
- profile.Build(thread, &filter, Profiler::sample_buffer());
+ profile.Build(thread, &filter, Profiler::sample_block_buffer());
// We should have one allocation samples.
EXPECT_EQ(1, profile.sample_count());
ProfileStackWalker walker(&profile, true);
@@ -1810,7 +1852,7 @@
HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate->main_port(), class_a.id());
- profile.Build(thread, &filter, Profiler::sample_buffer());
+ profile.Build(thread, &filter, Profiler::sample_block_buffer());
// We should have one allocation samples.
EXPECT_EQ(1, profile.sample_count());
ProfileStackWalker walker(&profile, true);
@@ -1888,7 +1930,7 @@
HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate->main_port(), class_a.id());
- profile.Build(thread, &filter, Profiler::sample_buffer());
+ profile.Build(thread, &filter, Profiler::sample_block_buffer());
// We should have one allocation samples.
EXPECT_EQ(1, profile.sample_count());
ProfileStackWalker walker(&profile, true);
@@ -1998,7 +2040,7 @@
HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate->main_port(), class_a.id());
- profile.Build(thread, &filter, Profiler::sample_buffer());
+ profile.Build(thread, &filter, Profiler::sample_block_buffer());
// We should have one allocation samples.
EXPECT_EQ(1, profile.sample_count());
ProfileStackWalker walker(&profile, true);
@@ -2093,7 +2135,7 @@
HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate->main_port(), class_a.id());
- profile.Build(thread, &filter, Profiler::sample_buffer());
+ profile.Build(thread, &filter, Profiler::sample_block_buffer());
// We should have one allocation samples.
EXPECT_EQ(1, profile.sample_count());
ProfileStackWalker walker(&profile, true);
@@ -2211,7 +2253,7 @@
HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate->main_port(), class_a.id());
- profile.Build(thread, &filter, Profiler::sample_buffer());
+ profile.Build(thread, &filter, Profiler::sample_block_buffer());
// We should have one allocation samples.
EXPECT_EQ(1, profile.sample_count());
ProfileStackWalker walker(&profile, true);
@@ -2256,10 +2298,10 @@
}
}
-static void InsertFakeSample(SampleBuffer* sample_buffer, uword* pc_offsets) {
- ASSERT(sample_buffer != NULL);
+static void InsertFakeSample(uword* pc_offsets) {
Isolate* isolate = Isolate::Current();
- Sample* sample = sample_buffer->ReserveSample();
+ ASSERT(Profiler::sample_block_buffer() != nullptr);
+ Sample* sample = Profiler::sample_block_buffer()->ReserveCPUSample(isolate);
ASSERT(sample != NULL);
sample->Init(isolate->main_port(), OS::GetCurrentMonotonicMicros(),
OSThread::Current()->trace_id());
@@ -2319,8 +2361,8 @@
DisableBackgroundCompilationScope dbcs;
- SampleBuffer* sample_buffer = Profiler::sample_buffer();
- EXPECT(sample_buffer != NULL);
+ SampleBlockBuffer* sample_block_buffer = Profiler::sample_block_buffer();
+ ASSERT(sample_block_buffer != nullptr);
const Library& root_library = Library::Handle(LoadTestScript(kScript));
@@ -2330,7 +2372,7 @@
{
// Clear the profile for this isolate.
ClearProfileVisitor cpv(Isolate::Current());
- sample_buffer->VisitSamples(&cpv);
+ sample_block_buffer->VisitSamples(&cpv);
}
// Query the code object for main and determine the PC at some token
@@ -2390,9 +2432,9 @@
callPositionPc, // main.
0};
- InsertFakeSample(sample_buffer, &sample1[0]);
- InsertFakeSample(sample_buffer, &sample2[0]);
- InsertFakeSample(sample_buffer, &sample3[0]);
+ InsertFakeSample(&sample1[0]);
+ InsertFakeSample(&sample2[0]);
+ InsertFakeSample(&sample3[0]);
// Generate source report for main.
JSONStream js;
diff --git a/runtime/vm/program_visitor.cc b/runtime/vm/program_visitor.cc
index 3020106b..6eb0c25 100644
--- a/runtime/vm/program_visitor.cc
+++ b/runtime/vm/program_visitor.cc
@@ -1436,7 +1436,7 @@
ObjectPtr* from = object_store->from();
ObjectPtr* to = object_store->to_snapshot(Snapshot::kFullAOT);
for (ObjectPtr* p = from; p <= to; p++) {
- if ((*p)->IsCode()) {
+ if ((*p)->IsHeapObject() && (*p)->IsCode()) {
code ^= *p;
inst = code.instructions();
thread->heap()->SetLoadingUnit(inst.ptr(), LoadingUnit::kRootId);
diff --git a/runtime/vm/raw_object.cc b/runtime/vm/raw_object.cc
index d7a1beb..b79c6b9 100644
--- a/runtime/vm/raw_object.cc
+++ b/runtime/vm/raw_object.cc
@@ -562,6 +562,7 @@
COMPRESSED_VISITOR(ExternalTwoByteString)
COMPRESSED_VISITOR(GrowableObjectArray)
COMPRESSED_VISITOR(LinkedHashMap)
+COMPRESSED_VISITOR(LinkedHashSet)
COMPRESSED_VISITOR(ExternalTypedData)
TYPED_DATA_VIEW_VISITOR(TypedDataView)
COMPRESSED_VISITOR(ReceivePort)
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 4d0bfbb..3d442b2 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -18,8 +18,10 @@
#include "vm/pointer_tagging.h"
#include "vm/snapshot.h"
#include "vm/tagged_pointer.h"
+#include "vm/thread.h"
#include "vm/token.h"
#include "vm/token_position.h"
+#include "vm/visitor.h"
// Currently we have two different axes for offset generation:
//
@@ -118,17 +120,10 @@
#undef V
};
-#define SNAPSHOT_WRITER_SUPPORT() \
- void WriteTo(SnapshotWriter* writer, intptr_t object_id, \
- Snapshot::Kind kind, bool as_reference); \
- friend class SnapshotWriter;
-
#define VISITOR_SUPPORT(object) \
static intptr_t Visit##object##Pointers(object##Ptr raw_obj, \
ObjectPointerVisitor* visitor);
-#define HEAP_PROFILER_SUPPORT() friend class HeapProfiler;
-
#define RAW_OBJECT_IMPLEMENTATION(object) \
private: /* NOLINT */ \
VISITOR_SUPPORT(object) \
@@ -144,12 +139,14 @@
#define RAW_HEAP_OBJECT_IMPLEMENTATION(object) \
private: \
RAW_OBJECT_IMPLEMENTATION(object); \
- SNAPSHOT_WRITER_SUPPORT() \
- HEAP_PROFILER_SUPPORT() \
friend class object##SerializationCluster; \
friend class object##DeserializationCluster; \
+ friend class object##MessageSerializationCluster; \
+ friend class object##MessageDeserializationCluster; \
friend class Serializer; \
friend class Deserializer; \
+ template <typename Base> \
+ friend class ObjectCopy; \
friend class Pass2Visitor;
// RawObject is the base class of all raw objects; even though it carries the
@@ -540,11 +537,13 @@
void StorePointer(type const* addr, type value) {
reinterpret_cast<std::atomic<type>*>(const_cast<type*>(addr))
->store(value, order);
- if (value->IsHeapObject()) {
+ if (value.IsHeapObject()) {
CheckHeapPointerStore(value, Thread::Current());
}
}
+ friend class MessageDeserializer; // bogus
+
template <typename type,
typename compressed_type,
std::memory_order order = std::memory_order_relaxed>
@@ -552,7 +551,7 @@
reinterpret_cast<std::atomic<compressed_type>*>(
const_cast<compressed_type*>(addr))
->store(static_cast<compressed_type>(value), order);
- if (value->IsHeapObject()) {
+ if (value.IsHeapObject()) {
CheckHeapPointerStore(value, Thread::Current());
}
}
@@ -560,7 +559,7 @@
template <typename type>
void StorePointer(type const* addr, type value, Thread* thread) {
*const_cast<type*>(addr) = value;
- if (value->IsHeapObject()) {
+ if (value.IsHeapObject()) {
CheckHeapPointerStore(value, thread);
}
}
@@ -570,7 +569,7 @@
type value,
Thread* thread) {
*const_cast<compressed_type*>(addr) = value;
- if (value->IsHeapObject()) {
+ if (value.IsHeapObject()) {
CheckHeapPointerStore(value, thread);
}
}
@@ -758,9 +757,7 @@
friend class ImageWriter;
friend class AssemblyImageWriter;
friend class BlobImageWriter;
- friend class SnapshotReader;
friend class Deserializer;
- friend class SnapshotWriter;
friend class String;
friend class WeakProperty; // StorePointer
friend class Instance; // StorePointer
@@ -772,6 +769,9 @@
friend class WriteBarrierUpdateVisitor; // CheckHeapPointerStore
friend class OffsetsTable;
friend class Object;
+ friend uword TagsFromUntaggedObject(UntaggedObject*); // tags_
+ friend void SetNewSpaceTaggingWord(ObjectPtr, classid_t, uint32_t); // tags_
+ friend class ObjectCopyBase; // LoadPointer/StorePointer
friend void ReportImpossibleNullError(intptr_t cid,
StackFrame* caller_frame,
Thread* thread);
@@ -835,8 +835,8 @@
} \
template <std::memory_order order = std::memory_order_relaxed> \
void set_##name(type value) { \
- StoreArrayPointer<Compressed##type, order>(&name##_, \
- Compressed##type(value)); \
+ StoreCompressedArrayPointer<type, Compressed##type, order>(&name##_, \
+ value); \
} \
\
protected: \
@@ -1010,7 +1010,6 @@
#if !defined(DART_PRECOMPILED_RUNTIME)
return reinterpret_cast<CompressedObjectPtr*>(&dependent_code_);
#endif
- case Snapshot::kMessage:
case Snapshot::kNone:
case Snapshot::kInvalid:
break;
@@ -1057,7 +1056,7 @@
friend class UntaggedInstance;
friend class UntaggedInstructions;
friend class UntaggedTypeArguments;
- friend class SnapshotReader;
+ friend class MessageSerializer;
friend class InstanceSerializationCluster;
friend class TypeSerializationCluster;
friend class CidRewriteVisitor;
@@ -1083,7 +1082,6 @@
case Snapshot::kFullCore:
case Snapshot::kFullJIT:
return reinterpret_cast<CompressedObjectPtr*>(&library_kernel_data_);
- case Snapshot::kMessage:
case Snapshot::kNone:
case Snapshot::kInvalid:
break;
@@ -1267,7 +1265,6 @@
case Snapshot::kFullCore:
case Snapshot::kFullJIT:
return reinterpret_cast<CompressedObjectPtr*>(&data_);
- case Snapshot::kMessage:
case Snapshot::kNone:
case Snapshot::kInvalid:
break;
@@ -1412,7 +1409,6 @@
case Snapshot::kFullJIT:
case Snapshot::kFullAOT:
return reinterpret_cast<CompressedObjectPtr*>(&initializer_function_);
- case Snapshot::kMessage:
case Snapshot::kNone:
case Snapshot::kInvalid:
break;
@@ -1486,7 +1482,6 @@
case Snapshot::kFullCore:
case Snapshot::kFullJIT:
return reinterpret_cast<CompressedObjectPtr*>(&kernel_program_info_);
- case Snapshot::kMessage:
case Snapshot::kNone:
case Snapshot::kInvalid:
break;
@@ -1578,7 +1573,6 @@
case Snapshot::kFullCore:
case Snapshot::kFullJIT:
return reinterpret_cast<CompressedObjectPtr*>(&kernel_data_);
- case Snapshot::kMessage:
case Snapshot::kNone:
case Snapshot::kInvalid:
break;
@@ -1631,7 +1625,6 @@
case Snapshot::kFullCore:
case Snapshot::kFullJIT:
return reinterpret_cast<CompressedObjectPtr*>(&owner_);
- case Snapshot::kMessage:
case Snapshot::kNone:
case Snapshot::kInvalid:
break;
@@ -2186,7 +2179,6 @@
VARIABLE_POINTER_FIELDS(ObjectPtr, element, data)
friend class Object;
- friend class SnapshotReader;
};
class UntaggedContextScope : public UntaggedObject {
@@ -2262,7 +2254,6 @@
friend class Object;
friend class UntaggedClosureData;
- friend class SnapshotReader;
};
class UntaggedSentinel : public UntaggedObject {
@@ -2328,7 +2319,6 @@
case Snapshot::kFullCore:
case Snapshot::kFullJIT:
return to();
- case Snapshot::kMessage:
case Snapshot::kNone:
case Snapshot::kInvalid:
break;
@@ -2423,7 +2413,6 @@
class UntaggedInstance : public UntaggedObject {
RAW_HEAP_OBJECT_IMPLEMENTATION(Instance);
friend class Object;
- friend class SnapshotReader;
public:
#if defined(DART_COMPRESSED_POINTERS)
@@ -2452,7 +2441,6 @@
case Snapshot::kFullCore:
case Snapshot::kFullJIT:
return reinterpret_cast<CompressedObjectPtr*>(&importer_);
- case Snapshot::kMessage:
case Snapshot::kNone:
case Snapshot::kInvalid:
break;
@@ -2479,7 +2467,6 @@
COMPRESSED_VARIABLE_POINTER_FIELDS(AbstractTypePtr, element, types)
friend class Object;
- friend class SnapshotReader;
};
class UntaggedTypeParameters : public UntaggedObject {
@@ -2498,7 +2485,6 @@
CompressedObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
friend class Object;
- friend class SnapshotReader;
};
class UntaggedAbstractType : public UntaggedInstance {
@@ -2517,6 +2503,9 @@
// Accessed from generated code.
std::atomic<uword> type_test_stub_entry_point_;
+#if defined(DART_COMPRESSED_POINTERS)
+ uint32_t padding_; // Makes Windows and Posix agree on layout.
+#endif
COMPRESSED_POINTER_FIELD(CodePtr, type_test_stub)
VISIT_FROM(type_test_stub)
@@ -2707,7 +2696,6 @@
friend class Api;
friend class Class;
friend class Integer;
- friend class SnapshotReader;
};
COMPILE_ASSERT(sizeof(UntaggedMint) == 16);
@@ -2718,7 +2706,6 @@
ALIGN8 double value_;
friend class Api;
- friend class SnapshotReader;
friend class Class;
};
COMPILE_ASSERT(sizeof(UntaggedDouble) == 16);
@@ -2754,9 +2741,7 @@
uint8_t* data() { OPEN_ARRAY_START(uint8_t, uint8_t); }
const uint8_t* data() const { OPEN_ARRAY_START(uint8_t, uint8_t); }
- friend class ApiMessageReader;
friend class RODataSerializationCluster;
- friend class SnapshotReader;
friend class String;
};
@@ -2769,7 +2754,6 @@
const uint16_t* data() const { OPEN_ARRAY_START(uint16_t, uint16_t); }
friend class RODataSerializationCluster;
- friend class SnapshotReader;
friend class String;
};
@@ -2800,6 +2784,9 @@
// Abstract base class for RawTypedData/RawExternalTypedData/RawTypedDataView.
class UntaggedTypedDataBase : public UntaggedPointerBase {
protected:
+#if defined(DART_COMPRESSED_POINTERS)
+ uint32_t padding_; // Makes Windows and Posix agree on layout.
+#endif
// The length of the view in element sizes (obtainable via
// [TypedDataBase::ElementSizeInBytes]).
COMPRESSED_SMI_FIELD(SmiPtr, length);
@@ -2808,6 +2795,12 @@
private:
friend class UntaggedTypedDataView;
+ friend void UpdateLengthField(intptr_t, ObjectPtr, ObjectPtr); // length_
+ friend void InitializeExternalTypedData(
+ intptr_t,
+ ExternalTypedDataPtr,
+ ExternalTypedDataPtr); // initialize fields.
+
RAW_HEAP_OBJECT_IMPLEMENTATION(TypedDataBase);
};
@@ -2844,7 +2837,6 @@
friend class ObjectPoolDeserializationCluster;
friend class ObjectPoolSerializationCluster;
friend class UntaggedObjectPool;
- friend class SnapshotReader;
};
// All _*ArrayView/_ByteDataView classes share the same layout.
@@ -2899,6 +2891,7 @@
VISIT_TO(offset_in_bytes)
CompressedObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
+ friend void InitializeTypedDataView(TypedDataViewPtr);
friend class Api;
friend class Object;
friend class ObjectPoolDeserializationCluster;
@@ -2907,7 +2900,6 @@
friend class GCCompactor;
template <bool>
friend class ScavengerVisitorBase;
- friend class SnapshotReader;
};
class UntaggedExternalOneByteString : public UntaggedString {
@@ -2953,7 +2945,6 @@
friend class Deserializer;
friend class UntaggedCode;
friend class UntaggedImmutableArray;
- friend class SnapshotReader;
friend class GrowableObjectArray;
friend class LinkedHashMap;
friend class UntaggedLinkedHashMap;
@@ -2964,12 +2955,12 @@
template <typename Table, bool kAllCanonicalObjectsAreIncludedIntoSet>
friend class CanonicalSetDeserializationCluster;
friend class OldPage;
+ friend class FastObjectCopy; // For initializing fields.
+ friend void UpdateLengthField(intptr_t, ObjectPtr, ObjectPtr); // length_
};
class UntaggedImmutableArray : public UntaggedArray {
RAW_HEAP_OBJECT_IMPLEMENTATION(ImmutableArray);
-
- friend class SnapshotReader;
};
class UntaggedGrowableObjectArray : public UntaggedInstance {
@@ -2982,7 +2973,6 @@
VISIT_TO(data)
CompressedObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
- friend class SnapshotReader;
friend class ReversePc;
};
@@ -2991,19 +2981,25 @@
COMPRESSED_POINTER_FIELD(TypeArgumentsPtr, type_arguments)
VISIT_FROM(type_arguments)
- COMPRESSED_POINTER_FIELD(TypedDataPtr, index)
COMPRESSED_POINTER_FIELD(SmiPtr, hash_mask)
COMPRESSED_POINTER_FIELD(ArrayPtr, data)
COMPRESSED_POINTER_FIELD(SmiPtr, used_data)
COMPRESSED_POINTER_FIELD(SmiPtr, deleted_keys)
- VISIT_TO(deleted_keys)
- CompressedObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
+ COMPRESSED_POINTER_FIELD(TypedDataPtr, index)
+ VISIT_TO(index)
+
+ CompressedObjectPtr* to_snapshot(Snapshot::Kind kind) {
+ // Do not serialize index.
+ return reinterpret_cast<CompressedObjectPtr*>(&deleted_keys_);
+ }
};
class UntaggedLinkedHashMap : public UntaggedLinkedHashBase {
RAW_HEAP_OBJECT_IMPLEMENTATION(LinkedHashMap);
+};
- friend class SnapshotReader;
+class UntaggedLinkedHashSet : public UntaggedLinkedHashBase {
+ RAW_HEAP_OBJECT_IMPLEMENTATION(LinkedHashSet);
};
class UntaggedFloat32x4 : public UntaggedInstance {
@@ -3012,7 +3008,6 @@
ALIGN8 float value_[4];
- friend class SnapshotReader;
friend class Class;
public:
@@ -3029,7 +3024,6 @@
ALIGN8 int32_t value_[4];
- friend class SnapshotReader;
public:
int32_t x() const { return value_[0]; }
@@ -3045,7 +3039,6 @@
ALIGN8 double value_[2];
- friend class SnapshotReader;
friend class Class;
public:
@@ -3234,7 +3227,6 @@
// Isolate unique tag.
uword tag_;
- friend class SnapshotReader;
friend class Object;
public:
@@ -3247,8 +3239,6 @@
COMPRESSED_POINTER_FIELD(TypeArgumentsPtr, type_arguments)
VISIT_FROM(type_arguments)
VISIT_TO(type_arguments)
-
- friend class SnapshotReader;
};
#undef WSR_COMPRESSED_POINTER_FIELD
diff --git a/runtime/vm/raw_object_fields.cc b/runtime/vm/raw_object_fields.cc
index 9c0d887a..0c64af6 100644
--- a/runtime/vm/raw_object_fields.cc
+++ b/runtime/vm/raw_object_fields.cc
@@ -231,8 +231,7 @@
#define NON_HEADER_HASH_CLASSES_AND_FIELDS(F) F(String, hash_)
OffsetsTable::OffsetsTable(Zone* zone) : cached_offsets_(zone) {
- for (intptr_t i = 0; offsets_table[i].class_id != -1; ++i) {
- OffsetsTableEntry entry = offsets_table[i];
+ for (const OffsetsTableEntry& entry : OffsetsTable::offsets_table()) {
cached_offsets_.Insert({{entry.class_id, entry.offset}, entry.field_name});
}
}
@@ -242,37 +241,46 @@
return cached_offsets_.LookupValue({class_id, offset});
}
-#define DEFINE_OFFSETS_TABLE_ENTRY(class_name, field_name) \
- {class_name::kClassId, #field_name, \
- OFFSET_OF(Untagged##class_name, field_name)},
+static MallocGrowableArray<OffsetsTable::OffsetsTableEntry> field_offsets_table;
-// clang-format off
-const OffsetsTable::OffsetsTableEntry OffsetsTable::offsets_table[] = {
- COMMON_CLASSES_AND_FIELDS(DEFINE_OFFSETS_TABLE_ENTRY)
+const MallocGrowableArray<OffsetsTable::OffsetsTableEntry>&
+OffsetsTable::offsets_table() {
+ ASSERT(field_offsets_table.length() > 0); // Initialized.
+ return field_offsets_table;
+}
+
+void OffsetsTable::Init() {
+#define DEFINE_OFFSETS_TABLE_ENTRY(class_name, field_name) \
+ field_offsets_table.Add({class_name::kClassId, #field_name, \
+ OFFSET_OF(Untagged##class_name, field_name)});
+
+ COMMON_CLASSES_AND_FIELDS(DEFINE_OFFSETS_TABLE_ENTRY)
#if !defined(PRODUCT)
- NON_PRODUCT_CLASSES_AND_FIELDS(DEFINE_OFFSETS_TABLE_ENTRY)
+ NON_PRODUCT_CLASSES_AND_FIELDS(DEFINE_OFFSETS_TABLE_ENTRY)
#endif
#if !defined(HASH_IN_OBJECT_HEADER)
- NON_HEADER_HASH_CLASSES_AND_FIELDS(DEFINE_OFFSETS_TABLE_ENTRY)
+ NON_HEADER_HASH_CLASSES_AND_FIELDS(DEFINE_OFFSETS_TABLE_ENTRY)
#endif
#if defined(DART_PRECOMPILED_RUNTIME)
- AOT_CLASSES_AND_FIELDS(DEFINE_OFFSETS_TABLE_ENTRY)
+ AOT_CLASSES_AND_FIELDS(DEFINE_OFFSETS_TABLE_ENTRY)
#if !defined(PRODUCT)
- AOT_NON_PRODUCT_CLASSES_AND_FIELDS(DEFINE_OFFSETS_TABLE_ENTRY)
+ AOT_NON_PRODUCT_CLASSES_AND_FIELDS(DEFINE_OFFSETS_TABLE_ENTRY)
#endif
#else
- JIT_CLASSES_AND_FIELDS(DEFINE_OFFSETS_TABLE_ENTRY)
+ JIT_CLASSES_AND_FIELDS(DEFINE_OFFSETS_TABLE_ENTRY)
#if !defined(PRODUCT)
- JIT_NON_PRODUCT_CLASSES_AND_FIELDS(DEFINE_OFFSETS_TABLE_ENTRY)
+ JIT_NON_PRODUCT_CLASSES_AND_FIELDS(DEFINE_OFFSETS_TABLE_ENTRY)
#endif
#endif
- {-1, nullptr, -1}
-};
-// clang-format on
#undef DEFINE_OFFSETS_TABLE_ENTRY
+}
+
+void OffsetsTable::Cleanup() {
+ field_offsets_table.Clear();
+}
#endif
diff --git a/runtime/vm/raw_object_fields.h b/runtime/vm/raw_object_fields.h
index 6a4f572..be56a51 100644
--- a/runtime/vm/raw_object_fields.h
+++ b/runtime/vm/raw_object_fields.h
@@ -30,12 +30,14 @@
const char* FieldNameForOffset(intptr_t cid, intptr_t offset);
struct OffsetsTableEntry {
- const intptr_t class_id;
- const char* const field_name;
- const intptr_t offset;
+ intptr_t class_id;
+ const char* field_name;
+ intptr_t offset;
};
- static const OffsetsTableEntry offsets_table[];
+ static const MallocGrowableArray<OffsetsTableEntry>& offsets_table();
+ static void Init();
+ static void Cleanup();
private:
struct IntAndIntToStringMapTraits {
@@ -71,6 +73,9 @@
const char* FieldNameForOffset(intptr_t cid, intptr_t offset) {
return nullptr;
}
+
+ static void Init() {}
+ static void Cleanup() {}
};
#endif
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
deleted file mode 100644
index 7e6df08..0000000
--- a/runtime/vm/raw_object_snapshot.cc
+++ /dev/null
@@ -1,1833 +0,0 @@
-// Copyright (c) 2012, 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.
-
-#include "vm/dart_api_state.h"
-#include "vm/message.h"
-#include "vm/native_entry.h"
-#include "vm/object.h"
-#include "vm/object_store.h"
-#include "vm/regexp.h"
-#include "vm/snapshot.h"
-#include "vm/stub_code.h"
-#include "vm/symbols.h"
-#include "vm/type_testing_stubs.h"
-#include "vm/visitor.h"
-
-namespace dart {
-
-// TODO(dartbug.com/34796): enable or remove this optimization.
-DEFINE_FLAG(
- uint64_t,
- externalize_typed_data_threshold,
- kMaxUint64,
- "Convert TypedData to ExternalTypedData when sending through a message"
- " port after it exceeds certain size in bytes.");
-
-#define OFFSET_OF_FROM(obj) \
- obj.ptr()->from() - reinterpret_cast<ObjectPtr*>(obj.ptr()->untag())
-
-#define READ_OBJECT_FIELDS(object, from, to, as_reference) \
- intptr_t num_flds = (to) - (from); \
- for (intptr_t i = 0; i <= num_flds; i++) { \
- (*reader->PassiveObjectHandle()) = reader->ReadObjectImpl(as_reference); \
- object.StorePointer(((from) + i), reader->PassiveObjectHandle()->ptr()); \
- }
-
-#define READ_COMPRESSED_OBJECT_FIELDS(object, from, to, as_reference) \
- intptr_t num_flds = (to) - (from); \
- for (intptr_t i = 0; i <= num_flds; i++) { \
- (*reader->PassiveObjectHandle()) = reader->ReadObjectImpl(as_reference); \
- object.StoreCompressedPointer(((from) + i), \
- reader->PassiveObjectHandle()->ptr()); \
- }
-
-ClassPtr Class::ReadFrom(SnapshotReader* reader,
- intptr_t object_id,
- intptr_t tags,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(reader != NULL);
-
- Class& cls = Class::ZoneHandle(reader->zone(), Class::null());
- cls = reader->ReadClassId(object_id);
- return cls.ptr();
-}
-
-void UntaggedClass::WriteTo(SnapshotWriter* writer,
- intptr_t object_id,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(writer != NULL);
-
- // Write out the serialization header value for this object.
- writer->WriteInlinedObjectHeader(object_id);
-
- // Write out the class and tags information.
- writer->WriteVMIsolateObject(kClassCid);
- writer->WriteTags(writer->GetObjectTags(this));
-
- if (writer->can_send_any_object() ||
- writer->AllowObjectsInDartLibrary(library())) {
- writer->WriteClassId(this);
- } else {
- // We do not allow regular dart instances in isolate messages.
- writer->SetWriteException(Exceptions::kArgument,
- "Illegal argument in isolate message"
- " : (object is a regular Dart Instance)");
- }
-}
-
-TypePtr Type::ReadFrom(SnapshotReader* reader,
- intptr_t object_id,
- intptr_t tags,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(reader != NULL);
-
- // Determine if the type class of this type is in the full snapshot.
- reader->Read<bool>();
-
- // Allocate type object.
- Type& type = Type::ZoneHandle(reader->zone(), Type::New());
- bool is_canonical = UntaggedObject::IsCanonical(tags);
- reader->AddBackRef(object_id, &type, kIsDeserialized);
-
- // Set all non object fields.
- const uint8_t combined = reader->Read<uint8_t>();
- type.set_type_state(combined >> 4);
- type.set_nullability(static_cast<Nullability>(combined & 0xf));
-
- // Read the code object for the type testing stub and set its entrypoint.
- reader->EnqueueTypePostprocessing(type);
-
- // Set all the object fields.
- READ_COMPRESSED_OBJECT_FIELDS(type, type.ptr()->untag()->from(),
- type.ptr()->untag()->to(), as_reference);
-
- // Read in the type class.
- (*reader->ClassHandle()) =
- Class::RawCast(reader->ReadObjectImpl(as_reference));
- type.set_type_class(*reader->ClassHandle());
-
- // Fill in the type testing stub.
- Code& code = *reader->CodeHandle();
- code = TypeTestingStubGenerator::DefaultCodeForType(type);
- type.InitializeTypeTestingStubNonAtomic(code);
-
- if (is_canonical) {
- type ^= type.Canonicalize(Thread::Current(), nullptr);
- }
-
- return type.ptr();
-}
-
-void UntaggedType::WriteTo(SnapshotWriter* writer,
- intptr_t object_id,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(writer != NULL);
-
- // Only resolved and finalized types should be written to a snapshot.
- ASSERT((type_state_ == UntaggedType::kFinalizedInstantiated) ||
- (type_state_ == UntaggedType::kFinalizedUninstantiated));
- ASSERT(type_class_id() != Object::null());
-
- // Write out the serialization header value for this object.
- writer->WriteInlinedObjectHeader(object_id);
-
- // Write out the class and tags information.
- writer->WriteIndexedObject(kTypeCid);
- writer->WriteTags(writer->GetObjectTags(this));
-
- if (type_class_id()->IsHeapObject()) {
- // Type class is still an unresolved class.
- UNREACHABLE();
- }
-
- // Lookup the type class.
- SmiPtr raw_type_class_id = Smi::RawCast(type_class_id());
- ClassPtr type_class =
- writer->isolate_group()->class_table()->At(Smi::Value(raw_type_class_id));
-
- // Write out typeclass_is_in_fullsnapshot first as this will
- // help the reader decide on how to canonicalize the type object.
- intptr_t tags = writer->GetObjectTags(type_class);
- bool typeclass_is_in_fullsnapshot =
- (ClassIdTag::decode(tags) == kClassCid) &&
- Class::IsInFullSnapshot(static_cast<ClassPtr>(type_class));
- writer->Write<bool>(typeclass_is_in_fullsnapshot);
-
- // Write out all the non object pointer fields.
- const uint8_t combined = (type_state_ << 4) | nullability_;
- ASSERT(type_state_ == (combined >> 4));
- ASSERT(nullability_ == (combined & 0xf));
- writer->Write<uint8_t>(combined);
-
- // Write out all the object pointer fields.
- ASSERT(type_class_id() != Object::null());
- SnapshotWriterVisitor visitor(writer, as_reference);
- visitor.VisitCompressedPointers(heap_base(), from(), to());
-
- // Write out the type class.
- writer->WriteObjectImpl(type_class, as_reference);
-}
-
-TypeRefPtr TypeRef::ReadFrom(SnapshotReader* reader,
- intptr_t object_id,
- intptr_t tags,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(reader != NULL);
-
- // Allocate type ref object.
- TypeRef& type_ref = TypeRef::ZoneHandle(reader->zone(), TypeRef::New());
- reader->AddBackRef(object_id, &type_ref, kIsDeserialized);
-
- // Read the code object for the type testing stub and set its entrypoint.
- reader->EnqueueTypePostprocessing(type_ref);
-
- // Set all the object fields.
- READ_COMPRESSED_OBJECT_FIELDS(type_ref, type_ref.ptr()->untag()->from(),
- type_ref.ptr()->untag()->to(), kAsReference);
-
- // Fill in the type testing stub.
- Code& code = *reader->CodeHandle();
- code = TypeTestingStubGenerator::DefaultCodeForType(type_ref);
- type_ref.InitializeTypeTestingStubNonAtomic(code);
-
- return type_ref.ptr();
-}
-
-void UntaggedTypeRef::WriteTo(SnapshotWriter* writer,
- intptr_t object_id,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(writer != NULL);
-
- // Write out the serialization header value for this object.
- writer->WriteInlinedObjectHeader(object_id);
-
- // Write out the class and tags information.
- writer->WriteIndexedObject(kTypeRefCid);
- writer->WriteTags(writer->GetObjectTags(this));
-
- // Write out all the object pointer fields.
- SnapshotWriterVisitor visitor(writer, kAsReference);
- visitor.VisitCompressedPointers(heap_base(), from(), to());
-}
-
-TypeParameterPtr TypeParameter::ReadFrom(SnapshotReader* reader,
- intptr_t object_id,
- intptr_t tags,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(reader != NULL);
-
- // Allocate type parameter object.
- TypeParameter& type_parameter =
- TypeParameter::ZoneHandle(reader->zone(), TypeParameter::New());
- bool is_canonical = UntaggedObject::IsCanonical(tags);
- reader->AddBackRef(object_id, &type_parameter, kIsDeserialized);
-
- // Set all non object fields.
- type_parameter.set_base(reader->Read<uint8_t>());
- type_parameter.set_index(reader->Read<uint8_t>());
- const uint8_t combined = reader->Read<uint8_t>();
- type_parameter.set_flags(combined >> 4);
- type_parameter.set_nullability(static_cast<Nullability>(combined & 0xf));
-
- // Read the code object for the type testing stub and set its entrypoint.
- reader->EnqueueTypePostprocessing(type_parameter);
-
- // Set all the object fields.
- READ_COMPRESSED_OBJECT_FIELDS(
- type_parameter, type_parameter.ptr()->untag()->from(),
- type_parameter.ptr()->untag()->to(), kAsReference);
-
- // Read in the parameterized class.
- (*reader->ClassHandle()) =
- Class::RawCast(reader->ReadObjectImpl(kAsReference));
- if (reader->ClassHandle()->id() == kFunctionCid) {
- (*reader->ClassHandle()) = Class::null();
- }
- type_parameter.set_parameterized_class(*reader->ClassHandle());
-
- // Fill in the type testing stub.
- Code& code = *reader->CodeHandle();
- code = TypeTestingStubGenerator::DefaultCodeForType(type_parameter);
- type_parameter.InitializeTypeTestingStubNonAtomic(code);
-
- if (is_canonical) {
- type_parameter ^= type_parameter.Canonicalize(Thread::Current(), nullptr);
- }
-
- return type_parameter.ptr();
-}
-
-void UntaggedTypeParameter::WriteTo(SnapshotWriter* writer,
- intptr_t object_id,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(writer != NULL);
-
- // Only finalized type parameters should be written to a snapshot.
- ASSERT(FinalizedBit::decode(flags_));
-
- // Write out the serialization header value for this object.
- writer->WriteInlinedObjectHeader(object_id);
-
- // Write out the class and tags information.
- writer->WriteIndexedObject(kTypeParameterCid);
- writer->WriteTags(writer->GetObjectTags(this));
-
- // Write out all the non object pointer fields.
- writer->Write<uint8_t>(base_);
- writer->Write<uint8_t>(index_);
- const uint8_t combined = (flags_ << 4) | nullability_;
- ASSERT(flags_ == (combined >> 4));
- ASSERT(nullability_ == (combined & 0xf));
- writer->Write<uint8_t>(combined);
-
- // Write out all the object pointer fields.
- SnapshotWriterVisitor visitor(writer, kAsReference);
- visitor.VisitCompressedPointers(heap_base(), from(), to());
-
- // Write out the parameterized class (or Function if cid == kFunctionCid).
- ClassPtr param_class =
- writer->isolate_group()->class_table()->At(parameterized_class_id_);
- writer->WriteObjectImpl(param_class, kAsReference);
-}
-
-TypeParametersPtr TypeParameters::ReadFrom(SnapshotReader* reader,
- intptr_t object_id,
- intptr_t tags,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(reader != NULL);
-
- TypeParameters& type_parameters =
- TypeParameters::ZoneHandle(reader->zone(), TypeParameters::New());
- reader->AddBackRef(object_id, &type_parameters, kIsDeserialized);
-
- // Set all the object fields.
- READ_COMPRESSED_OBJECT_FIELDS(
- type_parameters, type_parameters.ptr()->untag()->from(),
- type_parameters.ptr()->untag()->to(), kAsReference);
-
- return type_parameters.ptr();
-}
-
-void UntaggedTypeParameters::WriteTo(SnapshotWriter* writer,
- intptr_t object_id,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(writer != NULL);
-
- // Write out the serialization header value for this object.
- writer->WriteInlinedObjectHeader(object_id);
-
- // Write out the class and tags information.
- writer->WriteVMIsolateObject(kTypeParametersCid);
- writer->WriteTags(writer->GetObjectTags(this));
-
- // Write out all the object pointer fields.
- SnapshotWriterVisitor visitor(writer, kAsReference);
- visitor.VisitCompressedPointers(heap_base(), from(), to());
-}
-
-TypeArgumentsPtr TypeArguments::ReadFrom(SnapshotReader* reader,
- intptr_t object_id,
- intptr_t tags,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(reader != NULL);
-
- // Read the length so that we can determine instance size to allocate.
- intptr_t len = reader->ReadSmiValue();
-
- TypeArguments& type_arguments =
- TypeArguments::ZoneHandle(reader->zone(), TypeArguments::New(len));
- bool is_canonical = UntaggedObject::IsCanonical(tags);
- reader->AddBackRef(object_id, &type_arguments, kIsDeserialized);
-
- // Set the instantiations field, which is only read from a full snapshot.
- type_arguments.set_instantiations(Object::zero_array());
-
- // Now set all the type fields.
- for (intptr_t i = 0; i < len; i++) {
- *reader->TypeHandle() ^= reader->ReadObjectImpl(as_reference);
- type_arguments.SetTypeAt(i, *reader->TypeHandle());
- }
-
- // Set the canonical bit.
- if (is_canonical) {
- type_arguments = type_arguments.Canonicalize(Thread::Current(), nullptr);
- }
-
- return type_arguments.ptr();
-}
-
-void UntaggedTypeArguments::WriteTo(SnapshotWriter* writer,
- intptr_t object_id,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(writer != NULL);
-
- // Write out the serialization header value for this object.
- writer->WriteInlinedObjectHeader(object_id);
-
- // Write out the class and tags information.
- writer->WriteVMIsolateObject(kTypeArgumentsCid);
- writer->WriteTags(writer->GetObjectTags(this));
-
- // Write out the length field.
- writer->Write<ObjectPtr>(length());
-
- // Write out the individual types.
- intptr_t len = Smi::Value(length());
- for (intptr_t i = 0; i < len; i++) {
- // The Dart VM reuses type argument lists across instances in order
- // to reduce memory footprint, this can sometimes lead to a type from
- // such a shared type argument list being sent over to another isolate.
- // In such scenarios where it is not appropriate to send the types
- // across (isolates spawned using spawnURI) we send them as dynamic.
- if (!writer->can_send_any_object()) {
- // Lookup the type class.
- TypePtr raw_type = Type::RawCast(element(i));
- SmiPtr raw_type_class_id =
- Smi::RawCast(raw_type->untag()->type_class_id());
- ClassPtr type_class = writer->isolate_group()->class_table()->At(
- Smi::Value(raw_type_class_id));
- if (!writer->AllowObjectsInDartLibrary(type_class->untag()->library())) {
- writer->WriteVMIsolateObject(kDynamicType);
- } else {
- writer->WriteObjectImpl(element(i), as_reference);
- }
- } else {
- writer->WriteObjectImpl(element(i), as_reference);
- }
- }
-}
-
-ClosurePtr Closure::ReadFrom(SnapshotReader* reader,
- intptr_t object_id,
- intptr_t tags,
- Snapshot::Kind kind,
- bool as_reference) {
- UNREACHABLE();
- return Closure::null();
-}
-
-void UntaggedClosure::WriteTo(SnapshotWriter* writer,
- intptr_t object_id,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(writer != NULL);
- ASSERT(kind == Snapshot::kMessage);
-
- // Check if closure is serializable, throw an exception otherwise.
- FunctionPtr func = writer->IsSerializableClosure(ClosurePtr(this));
- if (func != Function::null()) {
- writer->WriteStaticImplicitClosure(
- object_id, func, writer->GetObjectTags(this), delayed_type_arguments());
- return;
- }
-
- UNREACHABLE();
-}
-
-ContextPtr Context::ReadFrom(SnapshotReader* reader,
- intptr_t object_id,
- intptr_t tags,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(reader != NULL);
-
- // Allocate context object.
- int32_t num_vars = reader->Read<int32_t>();
- Context& context = Context::ZoneHandle(reader->zone());
- reader->AddBackRef(object_id, &context, kIsDeserialized);
- if (num_vars != 0) {
- context = Context::New(num_vars);
-
- // Set all the object fields.
- // TODO(5411462): Need to assert No GC can happen here, even though
- // allocations may happen.
- intptr_t num_flds =
- (context.ptr()->untag()->to(num_vars) - context.ptr()->untag()->from());
- for (intptr_t i = 0; i <= num_flds; i++) {
- (*reader->PassiveObjectHandle()) = reader->ReadObjectImpl(kAsReference);
- context.StorePointer((context.ptr()->untag()->from() + i),
- reader->PassiveObjectHandle()->ptr());
- }
- }
- return context.ptr();
-}
-
-void UntaggedContext::WriteTo(SnapshotWriter* writer,
- intptr_t object_id,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(writer != NULL);
-
- // Write out the serialization header value for this object.
- writer->WriteInlinedObjectHeader(object_id);
-
- // Write out the class and tags information.
- writer->WriteVMIsolateObject(kContextCid);
- writer->WriteTags(writer->GetObjectTags(this));
-
- // Write out num of variables in the context.
- const int32_t num_variables = num_variables_;
- writer->Write<int32_t>(num_variables);
- if (num_variables != 0) {
- // Write out all the object pointer fields.
- SnapshotWriterVisitor visitor(writer, kAsReference);
- visitor.VisitPointers(from(), to(num_variables));
- }
-}
-
-ContextScopePtr ContextScope::ReadFrom(SnapshotReader* reader,
- intptr_t object_id,
- intptr_t tags,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(reader != NULL);
-
- // Allocate context object.
- bool is_implicit = reader->Read<bool>();
- if (is_implicit) {
- ContextScope& context_scope = ContextScope::ZoneHandle(reader->zone());
- context_scope = ContextScope::New(1, true);
- reader->AddBackRef(object_id, &context_scope, kIsDeserialized);
-
- *reader->TypeHandle() ^= reader->ReadObjectImpl(kAsInlinedObject);
-
- // Create a descriptor for 'this' variable.
- context_scope.SetTokenIndexAt(0, TokenPosition::kMinSource);
- context_scope.SetDeclarationTokenIndexAt(0, TokenPosition::kMinSource);
- context_scope.SetNameAt(0, Symbols::This());
- context_scope.SetIsFinalAt(0, true);
- context_scope.SetIsConstAt(0, false);
- context_scope.SetTypeAt(0, *reader->TypeHandle());
- context_scope.SetContextIndexAt(0, 0);
- context_scope.SetContextLevelAt(0, 0);
- return context_scope.ptr();
- }
- UNREACHABLE();
- return NULL;
-}
-
-void UntaggedContextScope::WriteTo(SnapshotWriter* writer,
- intptr_t object_id,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(writer != NULL);
-
- if (is_implicit_) {
- ASSERT(num_variables_ == 1);
- const VariableDesc* var = VariableDescAddr(0);
-
- // Write out the serialization header value for this object.
- writer->WriteInlinedObjectHeader(object_id);
-
- // Write out the class and tags information.
- writer->WriteVMIsolateObject(kContextScopeCid);
- writer->WriteTags(writer->GetObjectTags(this));
-
- // Write out is_implicit flag for the context scope.
- writer->Write<bool>(true);
-
- // Write out the type of 'this' the variable.
- writer->WriteObjectImpl(var->type.Decompress(heap_base()),
- kAsInlinedObject);
-
- return;
- }
- UNREACHABLE();
-}
-
-#define MESSAGE_SNAPSHOT_UNREACHABLE(type) \
- type##Ptr type::ReadFrom(SnapshotReader* reader, intptr_t object_id, \
- intptr_t tags, Snapshot::Kind kind, \
- bool as_reference) { \
- UNREACHABLE(); \
- return type::null(); \
- } \
- void Untagged##type::WriteTo(SnapshotWriter* writer, intptr_t object_id, \
- Snapshot::Kind kind, bool as_reference) { \
- UNREACHABLE(); \
- }
-
-#define MESSAGE_SNAPSHOT_ILLEGAL(type) \
- type##Ptr type::ReadFrom(SnapshotReader* reader, intptr_t object_id, \
- intptr_t tags, Snapshot::Kind kind, \
- bool as_reference) { \
- UNREACHABLE(); \
- return type::null(); \
- } \
- void Untagged##type::WriteTo(SnapshotWriter* writer, intptr_t object_id, \
- Snapshot::Kind kind, bool as_reference) { \
- writer->SetWriteException(Exceptions::kArgument, \
- "Illegal argument in isolate message" \
- " : (object is a " #type ")"); \
- }
-
-MESSAGE_SNAPSHOT_UNREACHABLE(AbstractType);
-MESSAGE_SNAPSHOT_UNREACHABLE(Bool);
-MESSAGE_SNAPSHOT_UNREACHABLE(ClosureData);
-MESSAGE_SNAPSHOT_UNREACHABLE(Code);
-MESSAGE_SNAPSHOT_UNREACHABLE(CodeSourceMap);
-MESSAGE_SNAPSHOT_UNREACHABLE(CompressedStackMaps);
-MESSAGE_SNAPSHOT_UNREACHABLE(Error);
-MESSAGE_SNAPSHOT_UNREACHABLE(ExceptionHandlers);
-MESSAGE_SNAPSHOT_UNREACHABLE(FfiTrampolineData);
-MESSAGE_SNAPSHOT_UNREACHABLE(Field);
-MESSAGE_SNAPSHOT_UNREACHABLE(Function);
-MESSAGE_SNAPSHOT_UNREACHABLE(CallSiteData);
-MESSAGE_SNAPSHOT_UNREACHABLE(ICData);
-MESSAGE_SNAPSHOT_UNREACHABLE(Instructions);
-MESSAGE_SNAPSHOT_UNREACHABLE(InstructionsSection);
-MESSAGE_SNAPSHOT_UNREACHABLE(InstructionsTable);
-MESSAGE_SNAPSHOT_UNREACHABLE(KernelProgramInfo);
-MESSAGE_SNAPSHOT_UNREACHABLE(Library);
-MESSAGE_SNAPSHOT_UNREACHABLE(LibraryPrefix);
-MESSAGE_SNAPSHOT_UNREACHABLE(LocalVarDescriptors);
-MESSAGE_SNAPSHOT_UNREACHABLE(MegamorphicCache);
-MESSAGE_SNAPSHOT_UNREACHABLE(Namespace);
-MESSAGE_SNAPSHOT_UNREACHABLE(ObjectPool);
-MESSAGE_SNAPSHOT_UNREACHABLE(PatchClass);
-MESSAGE_SNAPSHOT_UNREACHABLE(PcDescriptors);
-MESSAGE_SNAPSHOT_UNREACHABLE(Script);
-MESSAGE_SNAPSHOT_UNREACHABLE(Sentinel);
-MESSAGE_SNAPSHOT_UNREACHABLE(SingleTargetCache);
-MESSAGE_SNAPSHOT_UNREACHABLE(String);
-MESSAGE_SNAPSHOT_UNREACHABLE(SubtypeTestCache);
-MESSAGE_SNAPSHOT_UNREACHABLE(LoadingUnit);
-MESSAGE_SNAPSHOT_UNREACHABLE(TypedDataBase);
-MESSAGE_SNAPSHOT_UNREACHABLE(UnlinkedCall);
-MESSAGE_SNAPSHOT_UNREACHABLE(MonomorphicSmiableCall);
-MESSAGE_SNAPSHOT_UNREACHABLE(UnwindError);
-MESSAGE_SNAPSHOT_UNREACHABLE(FutureOr);
-MESSAGE_SNAPSHOT_UNREACHABLE(WeakSerializationReference);
-
-MESSAGE_SNAPSHOT_ILLEGAL(FunctionType)
-MESSAGE_SNAPSHOT_ILLEGAL(DynamicLibrary);
-MESSAGE_SNAPSHOT_ILLEGAL(MirrorReference);
-MESSAGE_SNAPSHOT_ILLEGAL(Pointer);
-MESSAGE_SNAPSHOT_ILLEGAL(ReceivePort);
-MESSAGE_SNAPSHOT_ILLEGAL(StackTrace);
-MESSAGE_SNAPSHOT_ILLEGAL(UserTag);
-
-ApiErrorPtr ApiError::ReadFrom(SnapshotReader* reader,
- intptr_t object_id,
- intptr_t tags,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(reader != NULL);
-
- // Allocate ApiError object.
- ApiError& api_error = ApiError::ZoneHandle(reader->zone(), ApiError::New());
- reader->AddBackRef(object_id, &api_error, kIsDeserialized);
-
- // Set all the object fields.
- READ_COMPRESSED_OBJECT_FIELDS(api_error, api_error.ptr()->untag()->from(),
- api_error.ptr()->untag()->to(), kAsReference);
-
- return api_error.ptr();
-}
-
-void UntaggedApiError::WriteTo(SnapshotWriter* writer,
- intptr_t object_id,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(writer != NULL);
-
- // Write out the serialization header value for this object.
- writer->WriteInlinedObjectHeader(object_id);
-
- // Write out the class and tags information.
- writer->WriteVMIsolateObject(kApiErrorCid);
- writer->WriteTags(writer->GetObjectTags(this));
-
- // Write out all the object pointer fields.
- SnapshotWriterVisitor visitor(writer, kAsReference);
- visitor.VisitCompressedPointers(heap_base(), from(), to());
-}
-
-LanguageErrorPtr LanguageError::ReadFrom(SnapshotReader* reader,
- intptr_t object_id,
- intptr_t tags,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(reader != NULL);
-
- // Allocate LanguageError object.
- LanguageError& language_error =
- LanguageError::ZoneHandle(reader->zone(), LanguageError::New());
- reader->AddBackRef(object_id, &language_error, kIsDeserialized);
-
- // Set all non object fields.
- language_error.set_token_pos(
- TokenPosition::Deserialize(reader->Read<int32_t>()));
- language_error.set_report_after_token(reader->Read<bool>());
- language_error.set_kind(reader->Read<uint8_t>());
-
- // Set all the object fields.
- READ_COMPRESSED_OBJECT_FIELDS(
- language_error, language_error.ptr()->untag()->from(),
- language_error.ptr()->untag()->to(), kAsReference);
-
- return language_error.ptr();
-}
-
-void UntaggedLanguageError::WriteTo(SnapshotWriter* writer,
- intptr_t object_id,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(writer != NULL);
-
- // Write out the serialization header value for this object.
- writer->WriteInlinedObjectHeader(object_id);
-
- // Write out the class and tags information.
- writer->WriteVMIsolateObject(kLanguageErrorCid);
- writer->WriteTags(writer->GetObjectTags(this));
-
- // Write out all the non object fields.
- writer->Write<int32_t>(token_pos_.Serialize());
- writer->Write<bool>(report_after_token_);
- writer->Write<uint8_t>(kind_);
-
- // Write out all the object pointer fields.
- SnapshotWriterVisitor visitor(writer, kAsReference);
- visitor.VisitCompressedPointers(heap_base(), from(), to());
-}
-
-UnhandledExceptionPtr UnhandledException::ReadFrom(SnapshotReader* reader,
- intptr_t object_id,
- intptr_t tags,
- Snapshot::Kind kind,
- bool as_reference) {
- UnhandledException& result =
- UnhandledException::ZoneHandle(reader->zone(), UnhandledException::New());
- reader->AddBackRef(object_id, &result, kIsDeserialized);
-
- // Set all the object fields.
- READ_COMPRESSED_OBJECT_FIELDS(result, result.ptr()->untag()->from(),
- result.ptr()->untag()->to(), kAsReference);
-
- return result.ptr();
-}
-
-void UntaggedUnhandledException::WriteTo(SnapshotWriter* writer,
- intptr_t object_id,
- Snapshot::Kind kind,
- bool as_reference) {
- // Write out the serialization header value for this object.
- writer->WriteInlinedObjectHeader(object_id);
-
- // Write out the class and tags information.
- writer->WriteVMIsolateObject(kUnhandledExceptionCid);
- writer->WriteTags(writer->GetObjectTags(this));
- // Write out all the object pointer fields.
- SnapshotWriterVisitor visitor(writer, kAsReference);
- visitor.VisitCompressedPointers(heap_base(), from(), to());
-}
-
-InstancePtr Instance::ReadFrom(SnapshotReader* reader,
- intptr_t object_id,
- intptr_t tags,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(reader != NULL);
-
- // Create an Instance object or get canonical one if it is a canonical
- // constant.
- Instance& obj = Instance::ZoneHandle(reader->zone(), Instance::null());
- obj ^= Object::Allocate(kInstanceCid, Instance::InstanceSize(), Heap::kNew,
- Instance::ContainsCompressedPointers());
- if (UntaggedObject::IsCanonical(tags)) {
- obj = obj.Canonicalize(reader->thread());
- }
- reader->AddBackRef(object_id, &obj, kIsDeserialized);
-
- return obj.ptr();
-}
-
-void UntaggedInstance::WriteTo(SnapshotWriter* writer,
- intptr_t object_id,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(writer != NULL);
-
- // Write out the serialization header value for this object.
- writer->WriteInlinedObjectHeader(object_id);
-
- // Write out the class and tags information.
- writer->WriteIndexedObject(kInstanceCid);
- writer->WriteTags(writer->GetObjectTags(this));
-}
-
-IntegerPtr Mint::ReadFrom(SnapshotReader* reader,
- intptr_t object_id,
- intptr_t tags,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(reader != NULL);
-
- // Read the 64 bit value for the object.
- int64_t value = reader->Read<int64_t>();
-
- // Check if the value could potentially fit in a Smi in our current
- // architecture, if so return the object as a Smi.
- if (Smi::IsValid(value)) {
- Smi& smi =
- Smi::ZoneHandle(reader->zone(), Smi::New(static_cast<intptr_t>(value)));
- reader->AddBackRef(object_id, &smi, kIsDeserialized);
- return smi.ptr();
- }
-
- // Create a Mint object or get canonical one if it is a canonical constant.
- Mint& mint = Mint::ZoneHandle(reader->zone(), Mint::null());
- // When reading a script snapshot we need to canonicalize only those object
- // references that are objects from the core library (loaded from a
- // full snapshot). Objects that are only in the script need not be
- // canonicalized as they are already canonical.
- // When reading a message snapshot we always have to canonicalize.
- if (UntaggedObject::IsCanonical(tags)) {
- mint = Mint::NewCanonical(value);
- ASSERT(mint.IsCanonical());
- } else {
- mint = Mint::New(value);
- }
- reader->AddBackRef(object_id, &mint, kIsDeserialized);
- return mint.ptr();
-}
-
-void UntaggedMint::WriteTo(SnapshotWriter* writer,
- intptr_t object_id,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(writer != NULL);
-
- // Write out the serialization header value for this object.
- writer->WriteInlinedObjectHeader(object_id);
-
- // Write out the class and tags information.
- writer->WriteIndexedObject(kMintCid);
- writer->WriteTags(writer->GetObjectTags(this));
-
- // Write out the 64 bit value.
- writer->Write<int64_t>(value_);
-}
-
-DoublePtr Double::ReadFrom(SnapshotReader* reader,
- intptr_t object_id,
- intptr_t tags,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(reader != NULL);
- ASSERT(kind != Snapshot::kMessage);
- // Read the double value for the object.
- double value = reader->ReadDouble();
-
- // Create a Double object or get canonical one if it is a canonical constant.
- Double& dbl = Double::ZoneHandle(reader->zone(), Double::null());
- // When reading a script snapshot we need to canonicalize only those object
- // references that are objects from the core library (loaded from a
- // full snapshot). Objects that are only in the script need not be
- // canonicalized as they are already canonical.
- if (UntaggedObject::IsCanonical(tags)) {
- dbl = Double::NewCanonical(value);
- ASSERT(dbl.IsCanonical());
- } else {
- dbl = Double::New(value);
- }
- reader->AddBackRef(object_id, &dbl, kIsDeserialized);
- return dbl.ptr();
-}
-
-void UntaggedDouble::WriteTo(SnapshotWriter* writer,
- intptr_t object_id,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(writer != NULL);
-
- // Write out the serialization header value for this object.
- writer->WriteInlinedObjectHeader(object_id);
-
- // Write out the class and tags information.
- writer->WriteIndexedObject(kDoubleCid);
- writer->WriteTags(writer->GetObjectTags(this));
-
- // Write out the double value.
- writer->WriteDouble(value_);
-}
-
-template <typename StringType, typename CharacterType, typename CallbackType>
-void String::ReadFromImpl(SnapshotReader* reader,
- String* str_obj,
- intptr_t len,
- intptr_t tags,
- CallbackType new_symbol,
- Snapshot::Kind kind) {
- ASSERT(reader != NULL);
- if (UntaggedObject::IsCanonical(tags)) {
- // Set up canonical string object.
- ASSERT(reader != NULL);
- CharacterType* ptr = reader->zone()->Alloc<CharacterType>(len);
- for (intptr_t i = 0; i < len; i++) {
- ptr[i] = reader->Read<CharacterType>();
- }
- *str_obj = (*new_symbol)(reader->thread(), ptr, len);
- } else {
- // Set up the string object.
- *str_obj = StringType::New(len, Heap::kNew);
- str_obj->SetHash(0); // Will get computed when needed.
- if (len == 0) {
- return;
- }
- NoSafepointScope no_safepoint;
- CharacterType* str_addr = StringType::DataStart(*str_obj);
- for (intptr_t i = 0; i < len; i++) {
- *str_addr = reader->Read<CharacterType>();
- str_addr++;
- }
- }
-}
-
-OneByteStringPtr OneByteString::ReadFrom(SnapshotReader* reader,
- intptr_t object_id,
- intptr_t tags,
- Snapshot::Kind kind,
- bool as_reference) {
- // Read the length so that we can determine instance size to allocate.
- ASSERT(reader != NULL);
- intptr_t len = reader->ReadSmiValue();
- String& str_obj = String::ZoneHandle(reader->zone(), String::null());
-
- String::ReadFromImpl<OneByteString, uint8_t>(reader, &str_obj, len, tags,
- Symbols::FromLatin1, kind);
- reader->AddBackRef(object_id, &str_obj, kIsDeserialized);
- return raw(str_obj);
-}
-
-TwoByteStringPtr TwoByteString::ReadFrom(SnapshotReader* reader,
- intptr_t object_id,
- intptr_t tags,
- Snapshot::Kind kind,
- bool as_reference) {
- // Read the length so that we can determine instance size to allocate.
- ASSERT(reader != NULL);
- intptr_t len = reader->ReadSmiValue();
- String& str_obj = String::ZoneHandle(reader->zone(), String::null());
-
- String::ReadFromImpl<TwoByteString, uint16_t>(reader, &str_obj, len, tags,
- Symbols::FromUTF16, kind);
- reader->AddBackRef(object_id, &str_obj, kIsDeserialized);
- return raw(str_obj);
-}
-
-template <typename T>
-static void StringWriteTo(SnapshotWriter* writer,
- intptr_t object_id,
- Snapshot::Kind kind,
- intptr_t class_id,
- intptr_t tags,
- SmiPtr length,
- T* data) {
- ASSERT(writer != NULL);
- intptr_t len = Smi::Value(length);
-
- // Write out the serialization header value for this object.
- writer->WriteInlinedObjectHeader(object_id);
-
- // Write out the class and tags information.
- writer->WriteIndexedObject(class_id);
- writer->WriteTags(tags);
-
- // Write out the length field.
- writer->Write<ObjectPtr>(length);
-
- // Write out the string.
- if (len > 0) {
- if (class_id == kOneByteStringCid) {
- writer->WriteBytes(reinterpret_cast<const uint8_t*>(data), len);
- } else {
- for (intptr_t i = 0; i < len; i++) {
- writer->Write(data[i]);
- }
- }
- }
-}
-
-void UntaggedOneByteString::WriteTo(SnapshotWriter* writer,
- intptr_t object_id,
- Snapshot::Kind kind,
- bool as_reference) {
- StringWriteTo(writer, object_id, kind, kOneByteStringCid,
- writer->GetObjectTags(this), length(), data());
-}
-
-void UntaggedTwoByteString::WriteTo(SnapshotWriter* writer,
- intptr_t object_id,
- Snapshot::Kind kind,
- bool as_reference) {
- StringWriteTo(writer, object_id, kind, kTwoByteStringCid,
- writer->GetObjectTags(this), length(), data());
-}
-
-ExternalOneByteStringPtr ExternalOneByteString::ReadFrom(SnapshotReader* reader,
- intptr_t object_id,
- intptr_t tags,
- Snapshot::Kind kind,
- bool as_reference) {
- UNREACHABLE();
- return ExternalOneByteString::null();
-}
-
-ExternalTwoByteStringPtr ExternalTwoByteString::ReadFrom(SnapshotReader* reader,
- intptr_t object_id,
- intptr_t tags,
- Snapshot::Kind kind,
- bool as_reference) {
- UNREACHABLE();
- return ExternalTwoByteString::null();
-}
-
-void UntaggedExternalOneByteString::WriteTo(SnapshotWriter* writer,
- intptr_t object_id,
- Snapshot::Kind kind,
- bool as_reference) {
- // Serialize as a non-external one byte string.
- StringWriteTo(writer, object_id, kind, kOneByteStringCid,
- writer->GetObjectTags(this), length(), external_data_);
-}
-
-void UntaggedExternalTwoByteString::WriteTo(SnapshotWriter* writer,
- intptr_t object_id,
- Snapshot::Kind kind,
- bool as_reference) {
- // Serialize as a non-external two byte string.
- StringWriteTo(writer, object_id, kind, kTwoByteStringCid,
- writer->GetObjectTags(this), length(), external_data_);
-}
-
-ArrayPtr Array::ReadFrom(SnapshotReader* reader,
- intptr_t object_id,
- intptr_t tags,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(reader != NULL);
-
- // Read the length so that we can determine instance size to allocate.
- intptr_t len = reader->ReadSmiValue();
- Array* array = NULL;
- DeserializeState state;
- if (!as_reference) {
- array = reinterpret_cast<Array*>(reader->GetBackRef(object_id));
- state = kIsDeserialized;
- } else {
- state = kIsNotDeserialized;
- }
- if (array == NULL) {
- array = &(Array::ZoneHandle(reader->zone(), Array::New(len)));
- reader->AddBackRef(object_id, array, state);
- }
- if (!as_reference) {
- // Read all the individual elements for inlined objects.
- ASSERT(!UntaggedObject::IsCanonical(tags));
- reader->ArrayReadFrom(object_id, *array, len, tags);
- }
- return array->ptr();
-}
-
-ImmutableArrayPtr ImmutableArray::ReadFrom(SnapshotReader* reader,
- intptr_t object_id,
- intptr_t tags,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(reader != NULL);
-
- // Read the length so that we can determine instance size to allocate.
- intptr_t len = reader->ReadSmiValue();
- Array* array = NULL;
- DeserializeState state;
- if (!as_reference) {
- array = reinterpret_cast<Array*>(reader->GetBackRef(object_id));
- state = kIsDeserialized;
- } else {
- state = kIsNotDeserialized;
- }
- if (array == NULL) {
- array = &(Array::ZoneHandle(reader->zone(), ImmutableArray::New(len)));
- reader->AddBackRef(object_id, array, state);
- }
- if (!as_reference) {
- // Read all the individual elements for inlined objects.
- reader->ArrayReadFrom(object_id, *array, len, tags);
- if (UntaggedObject::IsCanonical(tags)) {
- *array ^= array->Canonicalize(reader->thread());
- }
- }
- return raw(*array);
-}
-
-void UntaggedArray::WriteTo(SnapshotWriter* writer,
- intptr_t object_id,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(!this->IsCanonical());
- writer->ArrayWriteTo(object_id, kArrayCid, writer->GetObjectTags(this),
- length(), type_arguments(), data(), as_reference);
-}
-
-void UntaggedImmutableArray::WriteTo(SnapshotWriter* writer,
- intptr_t object_id,
- Snapshot::Kind kind,
- bool as_reference) {
- writer->ArrayWriteTo(object_id, kImmutableArrayCid,
- writer->GetObjectTags(this), length(), type_arguments(),
- data(), as_reference);
-}
-
-GrowableObjectArrayPtr GrowableObjectArray::ReadFrom(SnapshotReader* reader,
- intptr_t object_id,
- intptr_t tags,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(reader != NULL);
-
- // Read the length so that we can determine instance size to allocate.
- GrowableObjectArray& array = GrowableObjectArray::ZoneHandle(
- reader->zone(), GrowableObjectArray::null());
- array = GrowableObjectArray::New(0);
- reader->AddBackRef(object_id, &array, kIsDeserialized);
-
- // Read type arguments of growable array object.
- *reader->TypeArgumentsHandle() ^= reader->ReadObjectImpl(kAsInlinedObject);
- array.StoreCompressedPointer(&array.untag()->type_arguments_,
- reader->TypeArgumentsHandle()->ptr());
-
- // Read length of growable array object.
- array.SetLength(reader->ReadSmiValue());
-
- // Read the backing array of growable array object.
- *(reader->ArrayHandle()) ^= reader->ReadObjectImpl(kAsReference);
- array.SetData(*(reader->ArrayHandle()));
-
- return array.ptr();
-}
-
-void UntaggedGrowableObjectArray::WriteTo(SnapshotWriter* writer,
- intptr_t object_id,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(writer != NULL);
-
- // Write out the serialization header value for this object.
- writer->WriteInlinedObjectHeader(object_id);
-
- // Write out the class and tags information.
- writer->WriteIndexedObject(kGrowableObjectArrayCid);
- writer->WriteTags(writer->GetObjectTags(this));
-
- // Write out the type arguments field.
- writer->WriteObjectImpl(type_arguments(), kAsInlinedObject);
-
- // Write out the used length field.
- writer->Write<ObjectPtr>(length());
-
- // Write out the Array object.
- writer->WriteObjectImpl(data(), kAsReference);
-}
-
-LinkedHashMapPtr LinkedHashMap::ReadFrom(SnapshotReader* reader,
- intptr_t object_id,
- intptr_t tags,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(reader != NULL);
-
- LinkedHashMap& map =
- LinkedHashMap::ZoneHandle(reader->zone(), LinkedHashMap::null());
- // Since the map might contain itself as a key or value, allocate first.
- map = LinkedHashMap::NewUninitialized();
- reader->AddBackRef(object_id, &map, kIsDeserialized);
-
- // Read the type arguments.
- *reader->TypeArgumentsHandle() ^= reader->ReadObjectImpl(kAsInlinedObject);
- map.SetTypeArguments(*reader->TypeArgumentsHandle());
-
- // Read the number of key/value pairs.
- intptr_t len = reader->ReadSmiValue();
- intptr_t used_data = (len << 1);
- map.SetUsedData(used_data);
-
- // Allocate the data array.
- intptr_t data_size =
- Utils::Maximum(Utils::RoundUpToPowerOfTwo(used_data),
- static_cast<uintptr_t>(LinkedHashMap::kInitialIndexSize));
- Array& data = Array::ZoneHandle(reader->zone(), Array::New(data_size));
- map.SetData(data);
- map.SetDeletedKeys(0);
-
- // The index and hashMask is regenerated by the maps themselves on demand.
- // Thus, the index will probably be allocated in new space (unless it's huge).
- // TODO(koda): Eagerly rehash here when no keys have user-defined '==', and
- // in particular, if/when (const) maps are needed in the VM isolate snapshot.
- ASSERT(reader->isolate_group() != Dart::vm_isolate_group());
- map.SetHashMask(0); // Prefer sentinel 0 over null for better type feedback.
-
- reader->EnqueueRehashingOfMap(map);
-
- // Read the keys and values.
- bool read_as_reference = UntaggedObject::IsCanonical(tags) ? false : true;
- for (intptr_t i = 0; i < used_data; i++) {
- *reader->PassiveObjectHandle() = reader->ReadObjectImpl(read_as_reference);
- data.SetAt(i, *reader->PassiveObjectHandle());
- }
- return map.ptr();
-}
-
-void UntaggedLinkedHashMap::WriteTo(SnapshotWriter* writer,
- intptr_t object_id,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(writer != NULL);
-
- // Write out the serialization header value for this object.
- writer->WriteInlinedObjectHeader(object_id);
-
- // Write out the class and tags information.
- writer->WriteIndexedObject(kLinkedHashMapCid);
- writer->WriteTags(writer->GetObjectTags(this));
-
- // Write out the type arguments.
- writer->WriteObjectImpl(type_arguments(), kAsInlinedObject);
-
- const intptr_t num_used_data = Smi::Value(used_data());
- ASSERT((num_used_data & 1) == 0); // Keys + values, so must be even.
- const intptr_t num_deleted_keys = Smi::Value(deleted_keys());
-
- // Write out the number of (not deleted) key/value pairs that will follow.
- writer->Write<ObjectPtr>(Smi::New((num_used_data >> 1) - num_deleted_keys));
-
- // Write out the keys and values.
- const bool write_as_reference = this->IsCanonical() ? false : true;
- ArrayPtr data_array = data();
- ASSERT(num_used_data <= Smi::Value(data_array->untag()->length()));
-#if defined(DEBUG)
- intptr_t deleted_keys_found = 0;
-#endif // DEBUG
- for (intptr_t i = 0; i < num_used_data; i += 2) {
- ObjectPtr key = data_array->untag()->element(i);
- if (key == data_array) {
-#if defined(DEBUG)
- ++deleted_keys_found;
-#endif // DEBUG
- continue;
- }
- ObjectPtr value = data_array->untag()->element(i + 1);
- writer->WriteObjectImpl(key, write_as_reference);
- writer->WriteObjectImpl(value, write_as_reference);
- }
- DEBUG_ASSERT(deleted_keys_found == num_deleted_keys);
-}
-
-Float32x4Ptr Float32x4::ReadFrom(SnapshotReader* reader,
- intptr_t object_id,
- intptr_t tags,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(reader != NULL);
- // Read the values.
- float value0 = reader->Read<float>();
- float value1 = reader->Read<float>();
- float value2 = reader->Read<float>();
- float value3 = reader->Read<float>();
-
- // Create a Float32x4 object.
- Float32x4& simd = Float32x4::ZoneHandle(reader->zone(), Float32x4::null());
- simd = Float32x4::New(value0, value1, value2, value3);
- reader->AddBackRef(object_id, &simd, kIsDeserialized);
- return simd.ptr();
-}
-
-void UntaggedFloat32x4::WriteTo(SnapshotWriter* writer,
- intptr_t object_id,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(writer != NULL);
-
- // Write out the serialization header value for this object.
- writer->WriteInlinedObjectHeader(object_id);
-
- // Write out the class and tags information.
- writer->WriteIndexedObject(kFloat32x4Cid);
- writer->WriteTags(writer->GetObjectTags(this));
-
- // Write out the float values.
- writer->Write<float>(value_[0]);
- writer->Write<float>(value_[1]);
- writer->Write<float>(value_[2]);
- writer->Write<float>(value_[3]);
-}
-
-Int32x4Ptr Int32x4::ReadFrom(SnapshotReader* reader,
- intptr_t object_id,
- intptr_t tags,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(reader != NULL);
- // Read the values.
- uint32_t value0 = reader->Read<uint32_t>();
- uint32_t value1 = reader->Read<uint32_t>();
- uint32_t value2 = reader->Read<uint32_t>();
- uint32_t value3 = reader->Read<uint32_t>();
-
- // Create a Float32x4 object.
- Int32x4& simd = Int32x4::ZoneHandle(reader->zone(), Int32x4::null());
- simd = Int32x4::New(value0, value1, value2, value3);
- reader->AddBackRef(object_id, &simd, kIsDeserialized);
- return simd.ptr();
-}
-
-void UntaggedInt32x4::WriteTo(SnapshotWriter* writer,
- intptr_t object_id,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(writer != NULL);
-
- // Write out the serialization header value for this object.
- writer->WriteInlinedObjectHeader(object_id);
-
- // Write out the class and tags information.
- writer->WriteIndexedObject(kInt32x4Cid);
- writer->WriteTags(writer->GetObjectTags(this));
-
- // Write out the mask values.
- writer->Write<uint32_t>(value_[0]);
- writer->Write<uint32_t>(value_[1]);
- writer->Write<uint32_t>(value_[2]);
- writer->Write<uint32_t>(value_[3]);
-}
-
-Float64x2Ptr Float64x2::ReadFrom(SnapshotReader* reader,
- intptr_t object_id,
- intptr_t tags,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(reader != NULL);
- // Read the values.
- double value0 = reader->Read<double>();
- double value1 = reader->Read<double>();
-
- // Create a Float64x2 object.
- Float64x2& simd = Float64x2::ZoneHandle(reader->zone(), Float64x2::null());
- simd = Float64x2::New(value0, value1);
- reader->AddBackRef(object_id, &simd, kIsDeserialized);
- return simd.ptr();
-}
-
-void UntaggedFloat64x2::WriteTo(SnapshotWriter* writer,
- intptr_t object_id,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(writer != NULL);
-
- // Write out the serialization header value for this object.
- writer->WriteInlinedObjectHeader(object_id);
-
- // Write out the class and tags information.
- writer->WriteIndexedObject(kFloat64x2Cid);
- writer->WriteTags(writer->GetObjectTags(this));
-
- // Write out the float values.
- writer->Write<double>(value_[0]);
- writer->Write<double>(value_[1]);
-}
-
-TypedDataPtr TypedData::ReadFrom(SnapshotReader* reader,
- intptr_t object_id,
- intptr_t tags,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(reader != NULL);
-
- intptr_t cid = UntaggedObject::ClassIdTag::decode(tags);
- intptr_t len = reader->ReadSmiValue();
- TypedData& result =
- TypedData::ZoneHandle(reader->zone(), TypedData::New(cid, len));
- reader->AddBackRef(object_id, &result, kIsDeserialized);
-
- // Setup the array elements.
- intptr_t element_size = ElementSizeInBytes(cid);
- intptr_t length_in_bytes = len * element_size;
- NoSafepointScope no_safepoint;
- uint8_t* data = reinterpret_cast<uint8_t*>(result.DataAddr(0));
- reader->Align(Zone::kAlignment);
- reader->ReadBytes(data, length_in_bytes);
-
- // If it is a canonical constant make it one.
- // When reading a full snapshot we don't need to canonicalize the object
- // as it would already be a canonical object.
- // When reading a script snapshot or a message snapshot we always have
- // to canonicalize the object.
- if (UntaggedObject::IsCanonical(tags)) {
- result ^= result.Canonicalize(reader->thread());
- ASSERT(!result.IsNull());
- ASSERT(result.IsCanonical());
- }
- return result.ptr();
-}
-
-ExternalTypedDataPtr ExternalTypedData::ReadFrom(SnapshotReader* reader,
- intptr_t object_id,
- intptr_t tags,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(!Snapshot::IsFull(kind));
- intptr_t cid = UntaggedObject::ClassIdTag::decode(tags);
- intptr_t length = reader->ReadSmiValue();
-
- FinalizableData finalizable_data =
- static_cast<MessageSnapshotReader*>(reader)->finalizable_data()->Take();
- uint8_t* data = reinterpret_cast<uint8_t*>(finalizable_data.data);
- ExternalTypedData& obj =
- ExternalTypedData::ZoneHandle(ExternalTypedData::New(cid, data, length));
- reader->AddBackRef(object_id, &obj, kIsDeserialized);
- intptr_t external_size = obj.LengthInBytes();
- obj.AddFinalizer(finalizable_data.peer, finalizable_data.callback,
- external_size);
- return obj.ptr();
-}
-
-// This function's name can appear in Observatory.
-static void IsolateMessageTypedDataFinalizer(void* isolate_callback_data,
- void* buffer) {
- free(buffer);
-}
-
-void UntaggedTypedData::WriteTo(SnapshotWriter* writer,
- intptr_t object_id,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(writer != NULL);
- intptr_t cid = this->GetClassId();
- intptr_t length = Smi::Value(this->length()); // In elements.
- intptr_t external_cid;
- intptr_t bytes;
- switch (cid) {
- case kTypedDataInt8ArrayCid:
- external_cid = kExternalTypedDataInt8ArrayCid;
- bytes = length * sizeof(int8_t);
- break;
- case kTypedDataUint8ArrayCid:
- external_cid = kExternalTypedDataUint8ArrayCid;
- bytes = length * sizeof(uint8_t);
- break;
- case kTypedDataUint8ClampedArrayCid:
- external_cid = kExternalTypedDataUint8ClampedArrayCid;
- bytes = length * sizeof(uint8_t);
- break;
- case kTypedDataInt16ArrayCid:
- external_cid = kExternalTypedDataInt16ArrayCid;
- bytes = length * sizeof(int16_t);
- break;
- case kTypedDataUint16ArrayCid:
- external_cid = kExternalTypedDataUint16ArrayCid;
- bytes = length * sizeof(uint16_t);
- break;
- case kTypedDataInt32ArrayCid:
- external_cid = kExternalTypedDataInt32ArrayCid;
- bytes = length * sizeof(int32_t);
- break;
- case kTypedDataUint32ArrayCid:
- external_cid = kExternalTypedDataUint32ArrayCid;
- bytes = length * sizeof(uint32_t);
- break;
- case kTypedDataInt64ArrayCid:
- external_cid = kExternalTypedDataInt64ArrayCid;
- bytes = length * sizeof(int64_t);
- break;
- case kTypedDataUint64ArrayCid:
- external_cid = kExternalTypedDataUint64ArrayCid;
- bytes = length * sizeof(uint64_t);
- break;
- case kTypedDataFloat32ArrayCid:
- external_cid = kExternalTypedDataFloat32ArrayCid;
- bytes = length * sizeof(float);
- break;
- case kTypedDataFloat64ArrayCid:
- external_cid = kExternalTypedDataFloat64ArrayCid;
- bytes = length * sizeof(double);
- break;
- case kTypedDataInt32x4ArrayCid:
- external_cid = kExternalTypedDataInt32x4ArrayCid;
- bytes = length * sizeof(int32_t) * 4;
- break;
- case kTypedDataFloat32x4ArrayCid:
- external_cid = kExternalTypedDataFloat32x4ArrayCid;
- bytes = length * sizeof(float) * 4;
- break;
- case kTypedDataFloat64x2ArrayCid:
- external_cid = kExternalTypedDataFloat64x2ArrayCid;
- bytes = length * sizeof(double) * 2;
- break;
- default:
- external_cid = kIllegalCid;
- bytes = 0;
- UNREACHABLE();
- }
-
- // Write out the serialization header value for this object.
- writer->WriteInlinedObjectHeader(object_id);
-
- if ((kind == Snapshot::kMessage) &&
- (static_cast<uint64_t>(bytes) >= FLAG_externalize_typed_data_threshold)) {
- // Write as external.
- writer->WriteIndexedObject(external_cid);
- writer->WriteTags(writer->GetObjectTags(this));
- writer->Write<ObjectPtr>(this->length());
- uint8_t* data = reinterpret_cast<uint8_t*>(this->data());
- void* passed_data = malloc(bytes);
- memmove(passed_data, data, bytes);
- static_cast<MessageWriter*>(writer)->finalizable_data()->Put(
- bytes,
- passed_data, // data
- passed_data, // peer,
- IsolateMessageTypedDataFinalizer);
- } else {
- // Write as internal.
- writer->WriteIndexedObject(cid);
- writer->WriteTags(writer->GetObjectTags(this));
- writer->Write<ObjectPtr>(this->length());
- uint8_t* data = reinterpret_cast<uint8_t*>(this->data());
- writer->Align(Zone::kAlignment);
- writer->WriteBytes(data, bytes);
- }
-}
-
-void UntaggedExternalTypedData::WriteTo(SnapshotWriter* writer,
- intptr_t object_id,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(writer != NULL);
- intptr_t cid = this->GetClassId();
- intptr_t length = Smi::Value(this->length()); // In elements.
- intptr_t bytes;
- switch (cid) {
- case kExternalTypedDataInt8ArrayCid:
- bytes = length * sizeof(int8_t);
- break;
- case kExternalTypedDataUint8ArrayCid:
- bytes = length * sizeof(uint8_t);
- break;
- case kExternalTypedDataUint8ClampedArrayCid:
- bytes = length * sizeof(uint8_t);
- break;
- case kExternalTypedDataInt16ArrayCid:
- bytes = length * sizeof(int16_t);
- break;
- case kExternalTypedDataUint16ArrayCid:
- bytes = length * sizeof(uint16_t);
- break;
- case kExternalTypedDataInt32ArrayCid:
- bytes = length * sizeof(int32_t);
- break;
- case kExternalTypedDataUint32ArrayCid:
- bytes = length * sizeof(uint32_t);
- break;
- case kExternalTypedDataInt64ArrayCid:
- bytes = length * sizeof(int64_t);
- break;
- case kExternalTypedDataUint64ArrayCid:
- bytes = length * sizeof(uint64_t);
- break;
- case kExternalTypedDataFloat32ArrayCid:
- bytes = length * sizeof(float); // NOLINT.
- break;
- case kExternalTypedDataFloat64ArrayCid:
- bytes = length * sizeof(double); // NOLINT.
- break;
- case kExternalTypedDataInt32x4ArrayCid:
- bytes = length * sizeof(int32_t) * 4;
- break;
- case kExternalTypedDataFloat32x4ArrayCid:
- bytes = length * sizeof(float) * 4;
- break;
- case kExternalTypedDataFloat64x2ArrayCid:
- bytes = length * sizeof(double) * 2;
- break;
- default:
- bytes = 0;
- UNREACHABLE();
- }
-
- // Write out the serialization header value for this object.
- writer->WriteInlinedObjectHeader(object_id);
-
- // Write as external.
- writer->WriteIndexedObject(cid);
- writer->WriteTags(writer->GetObjectTags(this));
- writer->Write<ObjectPtr>(this->length());
- uint8_t* data = reinterpret_cast<uint8_t*>(data_);
- void* passed_data = malloc(bytes);
- memmove(passed_data, data, bytes);
- static_cast<MessageWriter*>(writer)->finalizable_data()->Put(
- bytes,
- passed_data, // data
- passed_data, // peer,
- IsolateMessageTypedDataFinalizer);
-}
-
-void UntaggedTypedDataView::WriteTo(SnapshotWriter* writer,
- intptr_t object_id,
- Snapshot::Kind kind,
- bool as_reference) {
- // Views have always a backing store.
- ASSERT(typed_data() != Object::null());
-
- // Write out the serialization header value for this object.
- writer->WriteInlinedObjectHeader(object_id);
-
- // Write out the class and tags information.
- writer->WriteIndexedObject(GetClassId());
- writer->WriteTags(writer->GetObjectTags(this));
-
- // Write members.
- writer->Write<ObjectPtr>(offset_in_bytes());
- writer->Write<ObjectPtr>(length());
- writer->WriteObjectImpl(typed_data(), as_reference);
-}
-
-TypedDataViewPtr TypedDataView::ReadFrom(SnapshotReader* reader,
- intptr_t object_id,
- intptr_t tags,
- Snapshot::Kind kind,
- bool as_reference) {
- auto& typed_data = *reader->TypedDataBaseHandle();
- const classid_t cid = UntaggedObject::ClassIdTag::decode(tags);
-
- auto& view = *reader->TypedDataViewHandle();
- view = TypedDataView::New(cid);
- reader->AddBackRef(object_id, &view, kIsDeserialized);
-
- const intptr_t offset_in_bytes = reader->ReadSmiValue();
- const intptr_t length = reader->ReadSmiValue();
- typed_data ^= reader->ReadObjectImpl(as_reference);
- view.InitializeWith(typed_data, offset_in_bytes, length);
-
- return view.ptr();
-}
-
-CapabilityPtr Capability::ReadFrom(SnapshotReader* reader,
- intptr_t object_id,
- intptr_t tags,
- Snapshot::Kind kind,
- bool as_reference) {
- uint64_t id = reader->Read<uint64_t>();
-
- Capability& result =
- Capability::ZoneHandle(reader->zone(), Capability::New(id));
- reader->AddBackRef(object_id, &result, kIsDeserialized);
- return result.ptr();
-}
-
-void UntaggedCapability::WriteTo(SnapshotWriter* writer,
- intptr_t object_id,
- Snapshot::Kind kind,
- bool as_reference) {
- // Write out the serialization header value for this object.
- writer->WriteInlinedObjectHeader(object_id);
-
- // Write out the class and tags information.
- writer->WriteIndexedObject(kCapabilityCid);
- writer->WriteTags(writer->GetObjectTags(this));
-
- writer->Write<uint64_t>(id_);
-}
-
-SendPortPtr SendPort::ReadFrom(SnapshotReader* reader,
- intptr_t object_id,
- intptr_t tags,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(kind == Snapshot::kMessage);
-
- uint64_t id = reader->Read<uint64_t>();
- uint64_t origin_id = reader->Read<uint64_t>();
-
- SendPort& result =
- SendPort::ZoneHandle(reader->zone(), SendPort::New(id, origin_id));
- reader->AddBackRef(object_id, &result, kIsDeserialized);
- return result.ptr();
-}
-
-void UntaggedSendPort::WriteTo(SnapshotWriter* writer,
- intptr_t object_id,
- Snapshot::Kind kind,
- bool as_reference) {
- // Write out the serialization header value for this object.
- writer->WriteInlinedObjectHeader(object_id);
-
- // Write out the class and tags information.
- writer->WriteIndexedObject(kSendPortCid);
- writer->WriteTags(writer->GetObjectTags(this));
-
- writer->Write<uint64_t>(id_);
- writer->Write<uint64_t>(origin_id_);
-}
-
-TransferableTypedDataPtr TransferableTypedData::ReadFrom(SnapshotReader* reader,
- intptr_t object_id,
- intptr_t tags,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(reader != nullptr);
-
- ASSERT(!Snapshot::IsFull(kind));
- const intptr_t length = reader->Read<int64_t>();
-
- const FinalizableData finalizable_data =
- static_cast<MessageSnapshotReader*>(reader)->finalizable_data()->Take();
- uint8_t* data = reinterpret_cast<uint8_t*>(finalizable_data.data);
- auto& transferableTypedData = TransferableTypedData::ZoneHandle(
- reader->zone(), TransferableTypedData::New(data, length));
- reader->AddBackRef(object_id, &transferableTypedData, kIsDeserialized);
- return transferableTypedData.ptr();
-}
-
-void UntaggedTransferableTypedData::WriteTo(SnapshotWriter* writer,
- intptr_t object_id,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(writer != nullptr);
- ASSERT(GetClassId() == kTransferableTypedDataCid);
- void* peer = writer->thread()->heap()->GetPeer(ObjectPtr(this));
- // Assume that object's Peer is only used to track transferrability state.
- ASSERT(peer != nullptr);
- TransferableTypedDataPeer* tpeer =
- reinterpret_cast<TransferableTypedDataPeer*>(peer);
- intptr_t length = tpeer->length(); // In bytes.
- void* data = tpeer->data();
- if (data == nullptr) {
- writer->SetWriteException(
- Exceptions::kArgument,
- "Illegal argument in isolate message"
- " : (TransferableTypedData has been transferred already)");
- return;
- }
-
- // Write out the serialization header value for this object.
- writer->WriteInlinedObjectHeader(object_id);
-
- writer->WriteIndexedObject(GetClassId());
- writer->WriteTags(writer->GetObjectTags(this));
- writer->Write<int64_t>(length);
-
- static_cast<MessageWriter*>(writer)->finalizable_data()->Put(
- length, data, tpeer,
- // Finalizer does nothing - in case of failure to serialize,
- // [data] remains wrapped in sender's [TransferableTypedData].
- [](void* data, void* peer) {},
- // This is invoked on successful serialization of the message
- [](void* data, void* peer) {
- TransferableTypedDataPeer* tpeer =
- reinterpret_cast<TransferableTypedDataPeer*>(peer);
- tpeer->handle()->EnsureFreedExternal(IsolateGroup::Current());
- tpeer->ClearData();
- });
-}
-
-RegExpPtr RegExp::ReadFrom(SnapshotReader* reader,
- intptr_t object_id,
- intptr_t tags,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(reader != NULL);
- // Allocate RegExp object.
- RegExp& regex =
- RegExp::ZoneHandle(reader->zone(), RegExp::New(reader->zone()));
- reader->AddBackRef(object_id, ®ex, kIsDeserialized);
-
- // Read and Set all the other fields.
- *reader->ArrayHandle() ^= reader->ReadObjectImpl(kAsInlinedObject);
- regex.set_capture_name_map(*reader->ArrayHandle());
- *reader->StringHandle() ^= reader->ReadObjectImpl(kAsInlinedObject);
- regex.set_pattern(*reader->StringHandle());
-
- regex.StoreNonPointer(®ex.untag()->num_bracket_expressions_,
- reader->Read<int32_t>());
- regex.StoreNonPointer(®ex.untag()->num_one_byte_registers_,
- reader->Read<int32_t>());
- regex.StoreNonPointer(®ex.untag()->num_two_byte_registers_,
- reader->Read<int32_t>());
- regex.StoreNonPointer(®ex.untag()->type_flags_, reader->Read<int8_t>());
- return regex.ptr();
-}
-
-void UntaggedRegExp::WriteTo(SnapshotWriter* writer,
- intptr_t object_id,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(writer != NULL);
-
- // Write out the serialization header value for this object.
- writer->WriteInlinedObjectHeader(object_id);
-
- // Write out the class and tags information.
- writer->WriteIndexedObject(kRegExpCid);
- writer->WriteTags(writer->GetObjectTags(this));
-
- // Write out all the other fields.
- writer->WriteObjectImpl(capture_name_map(), kAsInlinedObject);
- writer->WriteObjectImpl(pattern(), kAsInlinedObject);
- writer->Write<int32_t>(num_bracket_expressions_);
- writer->Write<int32_t>(num_one_byte_registers_);
- writer->Write<int32_t>(num_two_byte_registers_);
- writer->Write<int8_t>(type_flags_);
-}
-
-WeakPropertyPtr WeakProperty::ReadFrom(SnapshotReader* reader,
- intptr_t object_id,
- intptr_t tags,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(reader != NULL);
-
- // Allocate the weak property object.
- WeakProperty& weak_property =
- WeakProperty::ZoneHandle(reader->zone(), WeakProperty::New());
- reader->AddBackRef(object_id, &weak_property, kIsDeserialized);
-
- // Set all the object fields.
- READ_COMPRESSED_OBJECT_FIELDS(
- weak_property, weak_property.ptr()->untag()->from(),
- weak_property.ptr()->untag()->to(), kAsReference);
-
- return weak_property.ptr();
-}
-
-void UntaggedWeakProperty::WriteTo(SnapshotWriter* writer,
- intptr_t object_id,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(writer != NULL);
-
- // Write out the serialization header value for this object.
- writer->WriteInlinedObjectHeader(object_id);
-
- // Write out the class and tags information.
- writer->WriteIndexedObject(kWeakPropertyCid);
- writer->WriteTags(writer->GetObjectTags(this));
-
- // Write out all the object pointer fields.
- SnapshotWriterVisitor visitor(writer, kAsReference);
- visitor.VisitCompressedPointers(heap_base(), from(), to());
-}
-
-} // namespace dart
diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc
index 856d43f..b23182e 100644
--- a/runtime/vm/runtime_entry.cc
+++ b/runtime/vm/runtime_entry.cc
@@ -4,6 +4,7 @@
#include "vm/runtime_entry.h"
+#include "platform/thread_sanitizer.h"
#include "vm/code_descriptors.h"
#include "vm/code_patcher.h"
#include "vm/compiler/api/deopt_id.h"
@@ -757,8 +758,9 @@
auto& instance_delayed_type_arguments = TypeArguments::Handle(zone);
if (instance_class.IsClosureClass()) {
const auto& closure = Closure::Cast(instance);
- const auto& closure_function = Function::Handle(zone, closure.function());
- instance_class_id_or_signature = closure_function.signature();
+ const auto& function = Function::Handle(zone, closure.function());
+ instance_class_id_or_signature = function.signature();
+ ASSERT(instance_class_id_or_signature.IsFunctionType());
instance_type_arguments = closure.instantiator_type_arguments();
instance_parent_function_type_arguments = closure.function_type_arguments();
instance_delayed_type_arguments = closure.delayed_type_arguments();
@@ -827,7 +829,7 @@
new_cache.WriteEntryToBuffer(zone, &buffer, colliding_index, " ");
OS::PrintErr("%s\n", buffer.buffer());
}
- if (!IsolateGroup::AreIsolateGroupsEnabled()) {
+ if (!FLAG_enable_isolate_groups) {
FATAL("Duplicate subtype test cache entry");
}
if (old_result.ptr() != result.ptr()) {
@@ -1190,7 +1192,7 @@
const Code& target_code = Code::Handle(zone, target_function.EnsureHasCode());
// Before patching verify that we are not repeatedly patching to the same
// target.
- ASSERT(IsolateGroup::AreIsolateGroupsEnabled() ||
+ ASSERT(FLAG_enable_isolate_groups ||
target_code.ptr() != CodePatcher::GetStaticCallTargetAt(
caller_frame->pc(), caller_code));
if (target_code.ptr() !=
@@ -1613,6 +1615,7 @@
enum class MissHandler {
kInlineCacheMiss,
kSwitchableCallMiss,
+ kFixCallersTargetMonomorphic,
};
// Handles updating of type feedback and possible patching of instance calls.
@@ -2132,12 +2135,21 @@
const Function& target) {
// In JIT we can have two different miss handlers to which we return slightly
// differently.
- if (miss_handler_ == MissHandler::kSwitchableCallMiss) {
- arguments_.SetArgAt(0, stub); // Second return value.
- arguments_.SetReturn(data);
- } else {
- ASSERT(miss_handler_ == MissHandler::kInlineCacheMiss);
- arguments_.SetReturn(target);
+ switch (miss_handler_) {
+ case MissHandler::kSwitchableCallMiss: {
+ arguments_.SetArgAt(0, stub); // Second return value.
+ arguments_.SetReturn(data);
+ break;
+ }
+ case MissHandler::kFixCallersTargetMonomorphic: {
+ arguments_.SetArgAt(1, data); // Second return value.
+ arguments_.SetReturn(stub);
+ break;
+ }
+ case MissHandler::kInlineCacheMiss: {
+ arguments_.SetReturn(target);
+ break;
+ }
}
}
@@ -2954,8 +2966,7 @@
// With isolate groups enabled, it is possible that the target code
// has been deactivated just now(as a result of re-optimizatin for example),
// which will result in another run through FixCallersTarget.
- ASSERT(!current_target_code.IsDisabled() ||
- IsolateGroup::AreIsolateGroupsEnabled());
+ ASSERT(!current_target_code.IsDisabled() || FLAG_enable_isolate_groups);
arguments.SetReturn(current_target_code);
#else
UNREACHABLE();
@@ -2964,49 +2975,25 @@
// The caller must be a monomorphic call from unoptimized code.
// Patch call to point to new target.
-DEFINE_RUNTIME_ENTRY(FixCallersTargetMonomorphic, 0) {
+DEFINE_RUNTIME_ENTRY(FixCallersTargetMonomorphic, 2) {
#if !defined(DART_PRECOMPILED_RUNTIME)
- StackFrameIterator iterator(ValidationPolicy::kDontValidateFrames, thread,
- StackFrameIterator::kNoCrossThreadIteration);
- StackFrame* frame = iterator.NextFrame();
- ASSERT(frame != NULL);
- while (frame->IsStubFrame() || frame->IsExitFrame()) {
- frame = iterator.NextFrame();
- ASSERT(frame != NULL);
- }
- if (frame->IsEntryFrame()) {
- // Since function's current code is always unpatched, the entry frame always
- // calls to unpatched code.
- UNREACHABLE();
- }
- ASSERT(frame->IsDartFrame());
- const Code& caller_code = Code::Handle(zone, frame->LookupDartCode());
- RELEASE_ASSERT(!caller_code.is_optimized());
+ const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(0));
+ const Array& switchable_call_data =
+ Array::CheckedHandle(zone, arguments.ArgAt(1));
- Object& cache = Object::Handle(zone);
- const Code& old_target_code = Code::Handle(
- zone, CodePatcher::GetInstanceCallAt(frame->pc(), caller_code, &cache));
- const Function& target_function =
- Function::Handle(zone, old_target_code.function());
- const Code& current_target_code =
- Code::Handle(zone, target_function.EnsureHasCode());
- CodePatcher::PatchInstanceCallAt(frame->pc(), caller_code, cache,
- current_target_code);
- if (FLAG_trace_patching) {
- OS::PrintErr(
- "FixCallersTargetMonomorphic: caller %#" Px
- " "
- "target '%s' -> %#" Px " (%s)\n",
- frame->pc(), target_function.ToFullyQualifiedCString(),
- current_target_code.EntryPoint(),
- current_target_code.is_optimized() ? "optimized" : "unoptimized");
- }
- // With isolate groups enabled, it is possible that the target code
- // has been deactivated just now(as a result of re-optimizatin for example),
- // which will result in another run through FixCallersTarget.
- ASSERT(!current_target_code.IsDisabled() ||
- IsolateGroup::AreIsolateGroupsEnabled());
- arguments.SetReturn(current_target_code);
+ DartFrameIterator iterator(thread,
+ StackFrameIterator::kNoCrossThreadIteration);
+ StackFrame* caller_frame = iterator.NextFrame();
+ const auto& caller_code = Code::Handle(zone, caller_frame->LookupDartCode());
+ const auto& caller_function =
+ Function::Handle(zone, caller_frame->LookupDartFunction());
+
+ GrowableArray<const Instance*> caller_arguments(1);
+ caller_arguments.Add(&receiver);
+ PatchableCallHandler handler(
+ thread, caller_arguments, MissHandler::kFixCallersTargetMonomorphic,
+ arguments, caller_frame, caller_code, caller_function);
+ handler.ResolveSwitchAndReturn(switchable_call_data);
#else
UNREACHABLE();
#endif
@@ -3679,10 +3666,29 @@
TRACE_RUNTIME_CALL("AllocateHandle returning %p", return_value);
return return_value;
}
+
DEFINE_RAW_LEAF_RUNTIME_ENTRY(
AllocateHandle,
1,
false /* is_float */,
reinterpret_cast<RuntimeFunction>(&DLRT_AllocateHandle));
+#if defined(USING_THREAD_SANITIZER)
+#define TSAN_ACQUIRE reinterpret_cast<RuntimeFunction>(&__tsan_acquire)
+#define TSAN_RELEASE reinterpret_cast<RuntimeFunction>(&__tsan_release)
+#else
+#define TSAN_ACQUIRE nullptr
+#define TSAN_RELEASE nullptr
+#endif
+
+DEFINE_RAW_LEAF_RUNTIME_ENTRY(TsanLoadAcquire,
+ /*argument_count=*/1,
+ /*is_float=*/false,
+ TSAN_ACQUIRE);
+
+DEFINE_RAW_LEAF_RUNTIME_ENTRY(TsanStoreRelease,
+ /*argument_count=*/1,
+ /*is_float=*/false,
+ TSAN_RELEASE);
+
} // namespace dart
diff --git a/runtime/vm/runtime_entry_list.h b/runtime/vm/runtime_entry_list.h
index 69b2872..f22572c 100644
--- a/runtime/vm/runtime_entry_list.h
+++ b/runtime/vm/runtime_entry_list.h
@@ -96,7 +96,9 @@
V(void, ExitSafepoint) \
V(ApiLocalScope*, EnterHandleScope, Thread*) \
V(void, ExitHandleScope, Thread*) \
- V(LocalHandle*, AllocateHandle, ApiLocalScope*)
+ V(LocalHandle*, AllocateHandle, ApiLocalScope*) \
+ V(void, TsanLoadAcquire, uword /* address */) \
+ V(void, TsanStoreRelease, uword /* address */)
} // namespace dart
diff --git a/runtime/vm/scopes.cc b/runtime/vm/scopes.cc
index c643b46..b2545cf 100644
--- a/runtime/vm/scopes.cc
+++ b/runtime/vm/scopes.cc
@@ -7,6 +7,7 @@
#include "vm/compiler/backend/slot.h"
#include "vm/object.h"
+#include "vm/object_store.h"
#include "vm/stack_frame.h"
#include "vm/symbols.h"
@@ -194,7 +195,8 @@
&Slot::GetContextVariableSlotFor(Thread::Current(), *variable));
}
-VariableIndex LocalScope::AllocateVariables(VariableIndex first_parameter_index,
+VariableIndex LocalScope::AllocateVariables(const Function& function,
+ VariableIndex first_parameter_index,
int num_parameters,
VariableIndex first_local_index,
LocalScope* context_owner,
@@ -252,8 +254,30 @@
if (chained_future != nullptr) {
AllocateContextVariable(chained_future, &context_owner);
*found_captured_variables = true;
- ASSERT(chained_future->index().value() ==
- chained_future->expected_context_index());
+ // Remember context indices of _future variables in _Future.timeout and
+ // Future.wait. They are used while collecting async stack traces.
+ if (function.recognized_kind() == MethodRecognizer::kFutureTimeout) {
+#ifdef DEBUG
+ auto old_value = IsolateGroup::Current()
+ ->object_store()
+ ->future_timeout_future_index();
+ ASSERT(old_value == Object::null() ||
+ Smi::Value(old_value) == chained_future->index().value());
+#endif // DEBUG
+ IsolateGroup::Current()->object_store()->set_future_timeout_future_index(
+ Smi::Handle(Smi::New(chained_future->index().value())));
+ } else if (function.recognized_kind() == MethodRecognizer::kFutureWait) {
+#ifdef DEBUG
+ auto old_value =
+ IsolateGroup::Current()->object_store()->future_wait_future_index();
+ ASSERT(old_value == Object::null() ||
+ Smi::Value(old_value) == chained_future->index().value());
+#endif // DEBUG
+ IsolateGroup::Current()->object_store()->set_future_wait_future_index(
+ Smi::Handle(Smi::New(chained_future->index().value())));
+ } else {
+ UNREACHABLE();
+ }
}
if (is_sync != nullptr) {
AllocateContextVariable(is_sync, &context_owner);
@@ -312,7 +336,7 @@
// No parameters in children scopes.
const int num_parameters_in_child = 0;
VariableIndex child_next_index = child->AllocateVariables(
- dummy_parameter_index, num_parameters_in_child, next_index,
+ function, dummy_parameter_index, num_parameters_in_child, next_index,
context_owner, found_captured_variables);
if (child_next_index.value() < min_index.value()) {
min_index = child_next_index;
diff --git a/runtime/vm/scopes.h b/runtime/vm/scopes.h
index 593e186..ff80167 100644
--- a/runtime/vm/scopes.h
+++ b/runtime/vm/scopes.h
@@ -94,7 +94,6 @@
covariance_mode_(kNotCovariant),
is_late_(false),
is_chained_future_(false),
- expected_context_index_(-1),
late_init_offset_(0),
type_check_mode_(kDoTypeCheck),
index_() {
@@ -136,11 +135,6 @@
bool is_chained_future() const { return is_chained_future_; }
void set_is_chained_future() { is_chained_future_ = true; }
- intptr_t expected_context_index() const { return expected_context_index_; }
- void set_expected_context_index(int index) {
- expected_context_index_ = index;
- }
-
intptr_t late_init_offset() const { return late_init_offset_; }
void set_late_init_offset(intptr_t late_init_offset) {
late_init_offset_ = late_init_offset;
@@ -244,7 +238,6 @@
CovarianceMode covariance_mode_;
bool is_late_;
bool is_chained_future_;
- intptr_t expected_context_index_;
intptr_t late_init_offset_;
TypeCheckMode type_check_mode_;
VariableIndex index_;
@@ -476,7 +469,8 @@
// Two locals in different sibling scopes may share the same frame slot.
//
// Return the index of the next available frame slot.
- VariableIndex AllocateVariables(VariableIndex first_parameter_index,
+ VariableIndex AllocateVariables(const Function& function,
+ VariableIndex first_parameter_index,
int num_parameters,
VariableIndex first_local_index,
LocalScope* context_owner,
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index 238bc27..b9552b5 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -30,6 +30,7 @@
#include "vm/malloc_hooks.h"
#include "vm/message.h"
#include "vm/message_handler.h"
+#include "vm/message_snapshot.h"
#include "vm/native_arguments.h"
#include "vm/native_entry.h"
#include "vm/native_symbol.h"
@@ -1018,9 +1019,9 @@
message.value.as_array.length = 2;
message.value.as_array.values = elements;
- ApiMessageWriter writer;
- std::unique_ptr<Message> msg = writer.WriteCMessage(
- &message, ServiceIsolate::Port(), Message::kNormalPriority);
+ std::unique_ptr<Message> msg =
+ WriteApiMessage(thread->zone(), &message, ServiceIsolate::Port(),
+ Message::kNormalPriority);
if (msg == nullptr) {
result = false;
} else {
@@ -1188,9 +1189,10 @@
json_cobj.value.as_string = const_cast<char*>(event->ToCString());
list_values[1] = &json_cobj;
- ApiMessageWriter writer;
- std::unique_ptr<Message> msg = writer.WriteCMessage(
- &list_cobj, ServiceIsolate::Port(), Message::kNormalPriority);
+ AllocOnlyStackZone zone;
+ std::unique_ptr<Message> msg =
+ WriteApiMessage(zone.GetZone(), &list_cobj, ServiceIsolate::Port(),
+ Message::kNormalPriority);
if (msg != nullptr) {
PortMap::PostMessage(std::move(msg));
}
@@ -2017,8 +2019,7 @@
if (message->IsRaw()) {
return message->raw_obj();
} else {
- MessageSnapshotReader reader(message, thread);
- return reader.ReadObject();
+ return ReadMessage(thread, message);
}
}
@@ -5211,7 +5212,12 @@
}
{
JSONArray internals(&map, "Map");
- DEFINE_ADD_VALUE_F_CID(LinkedHashMap)
+ CLASS_LIST_MAPS(DEFINE_ADD_VALUE_F_CID)
+ }
+
+ {
+ JSONArray internals(&map, "Set");
+ CLASS_LIST_SETS(DEFINE_ADD_VALUE_F_CID)
}
#define DEFINE_ADD_MAP_KEY(clazz) \
{ \
diff --git a/runtime/vm/service.h b/runtime/vm/service.h
index e178c6a..4c87d36 100644
--- a/runtime/vm/service.h
+++ b/runtime/vm/service.h
@@ -15,7 +15,7 @@
namespace dart {
#define SERVICE_PROTOCOL_MAJOR_VERSION 3
-#define SERVICE_PROTOCOL_MINOR_VERSION 48
+#define SERVICE_PROTOCOL_MINOR_VERSION 50
class Array;
class EmbedderServiceHandler;
diff --git a/runtime/vm/service/service.md b/runtime/vm/service/service.md
index 708f581..6e29e0f 100644
--- a/runtime/vm/service/service.md
+++ b/runtime/vm/service/service.md
@@ -1,8 +1,8 @@
-# Dart VM Service Protocol 3.48
+# Dart VM Service Protocol 3.49
> Please post feedback to the [observatory-discuss group][discuss-list]
-This document describes of _version 3.48_ of the Dart VM Service Protocol. This
+This document describes of _version 3.49_ of the Dart VM Service Protocol. This
protocol is used to communicate with a running Dart Virtual Machine.
To use the Service Protocol, start the VM with the *--observe* flag.
@@ -117,6 +117,7 @@
- [NativeFunction](#nativefunction)
- [Null](#null)
- [Object](#object)
+ - [Parameter](#parameter)[
- [PortList](#portlist)
- [ReloadReport](#reloadreport)
- [Response](#response)
@@ -139,6 +140,7 @@
- [TimelineFlags](#timelineflags)
- [Timestamp](#timestamp)
- [TypeArguments](#typearguments)
+ - [TypeParameters](#typeparameters)[
- [UresolvedSourceLocation](#unresolvedsourcelocation)
- [Version](#version)
- [VM](#vm)
@@ -1477,7 +1479,7 @@
VM | VMUpdate, VMFlagUpdate
Isolate | IsolateStart, IsolateRunnable, IsolateExit, IsolateUpdate, IsolateReload, ServiceExtensionAdded
Debug | PauseStart, PauseExit, PauseBreakpoint, PauseInterrupted, PauseException, PausePostRequest, Resume, BreakpointAdded, BreakpointResolved, BreakpointRemoved, BreakpointUpdated, Inspect, None
-Profiler | UserTagChanged
+Profiler | CpuSamples, UserTagChanged
GC | GC
Extension | Extension
Timeline | TimelineEvents, TimelineStreamsSubscriptionUpdate
@@ -1694,6 +1696,11 @@
// The library which contains this class.
@Library library;
+
+ // The type parameters for the class.
+ //
+ // Provided if the class is generic.
+ @Instance[] typeParameters [optional];
}
```
@@ -1710,6 +1717,11 @@
// The library which contains this class.
@Library library;
+ // The type parameters for the class.
+ //
+ // Provided if the class is generic.
+ @Instance[] typeParameters [optional];
+
// The error which occurred during class finalization, if it exists.
@Error error [optional];
@@ -2161,6 +2173,9 @@
// The previous UserTag label.
string previousTag [optional];
+
+ // A CPU profile containing recent samples.
+ CpuSamples cpuSamples [optional];
}
```
@@ -2274,6 +2289,9 @@
// Notification that the UserTag for an isolate has been changed.
UserTagChanged,
+
+ // A block of recently collected CPU samples.
+ CpuSamples,
}
```
@@ -2421,6 +2439,9 @@
// Is this function const?
bool const;
+ // Is this function implicitly defined (e.g., implicit getter/setter)?
+ bool implicit;
+
// The location of this function in the source code.
SourceLocation location [optional];
}
@@ -2443,9 +2464,15 @@
// Is this function const?
bool const;
+ // Is this function implicitly defined (e.g., implicit getter/setter)?
+ bool implicit;
+
// The location of this function in the source code.
SourceLocation location [optional];
+ // The signature of the function.
+ @Instance signature;
+
// The compiled code associated with this function.
@Code code [optional];
}
@@ -2523,12 +2550,29 @@
// Type
@Class typeClass [optional];
- // The parameterized class of a type parameter:
+ // The parameterized class of a type parameter.
//
// Provided for instance kinds:
// TypeParameter
@Class parameterizedClass [optional];
+ // The return type of a function.
+ //
+ // Provided for instance kinds:
+ // FunctionType
+ @Instance returnType [optional];
+
+ // The list of parameter types for a function.
+ //
+ // Provided for instance kinds:
+ // FunctionType
+ Parameter[] parameters [optional];
+
+ // The type parameters for a function.
+ //
+ // Provided for instance kinds:
+ // FunctionType
+ @Instance[] typeParameters [optional];
// The pattern of a RegExp instance.
//
@@ -2688,6 +2732,24 @@
// TypeParameter
@Class parameterizedClass [optional];
+ // The return type of a function.
+ //
+ // Provided for instance kinds:
+ // FunctionType
+ @Instance returnType [optional];
+
+ // The list of parameter types for a function.
+ //
+ // Provided for instance kinds:
+ // FunctionType
+ Parameter[] parameters [optional];
+
+ // The type parameters for a function.
+ //
+ // Provided for instance kinds:
+ // FunctionType
+ @Instance[] typeParameters [optional];
+
// The fields of this Instance.
BoundField[] fields [optional];
@@ -2905,6 +2967,9 @@
// An instance of the Dart class TypeRef.
TypeRef,
+ // An instance of the Dart class FunctionType.
+ FunctionType,
+
// An instance of the Dart class BoundedType.
BoundedType,
@@ -3356,7 +3421,29 @@
}
```
-An _Object_ is a persistent object that is owned by some isolate.
+An _Object_ is a persistent object that is owned by some isolate.
+
+### Parameter
+
+```
+class Parameter {
+ // The type of the parameter.
+ @Instance parameterType;
+
+ // Represents whether or not this parameter is fixed or optional.
+ bool fixed;
+
+ // The name of a named optional parameter.
+ string name [optional];
+
+ // Whether or not this named optional parameter is marked as required.
+ bool required [optional];
+}
+```
+
+A _Parameter_ is a representation of a function parameter.
+
+See [Instance](#instance).
### PortList
@@ -3908,6 +3995,24 @@
A _TypeArguments_ object represents the type argument vector for some
instantiated generic type.
+### TypeParameters
+
+```
+class TypeParameters {
+ // The names of the type parameters.
+ string[] names;
+
+ // The bounds set on each type parameter.
+ @TypeArguments bounds;
+
+ // The default types for each type parameter.
+ @TypeArguments defaults;
+}
+```
+
+A _TypeParameters_ object represents the type argument vector for some
+uninstantiated generic type.
+
### UnresolvedSourceLocation
```
@@ -4069,5 +4174,7 @@
3.46 | Moved `sourceLocation` property into reference types for `Class`, `Field`, and `Function`.
3.47 | Added `shows` and `hides` properties to `LibraryDependency`.
3.48 | Added `Profiler` stream, `UserTagChanged` event kind, and `updatedTag` and `previousTag` properties to `Event`.
+3.49 | Added `CpuSamples` event kind, and `cpuSamples` property to `Event`.
+3.50 | Added `returnType`, `parameters`, and `typeParameters` to `@Instance`, and `implicit` to `@Function`. Added `Parameter` type.
[discuss-list]: https://groups.google.com/a/dartlang.org/forum/#!forum/observatory-discuss
diff --git a/runtime/vm/service_event.cc b/runtime/vm/service_event.cc
index f8ab174..85740cf 100644
--- a/runtime/vm/service_event.cc
+++ b/runtime/vm/service_event.cc
@@ -64,7 +64,8 @@
event_kind == ServiceEvent::kNone ||
// VM service can print Observatory information to Stdout or Stderr
// which are embedder streams.
- event_kind == ServiceEvent::kEmbedder)));
+ event_kind == ServiceEvent::kEmbedder ||
+ event_kind == ServiceEvent::kCpuSamples)));
if ((event_kind == ServiceEvent::kPauseStart) ||
(event_kind == ServiceEvent::kPauseExit)) {
@@ -141,6 +142,8 @@
return "TimelineStreamSubscriptionsUpdate";
case kUserTagChanged:
return "UserTagChanged";
+ case kCpuSamples:
+ return "CpuSamples";
default:
UNREACHABLE();
return "Unknown";
@@ -193,6 +196,7 @@
case kEmbedder:
return nullptr;
+ case kCpuSamples:
case kUserTagChanged:
return &Service::profiler_stream;
@@ -300,6 +304,11 @@
js->AppendSerializedObject("extensionData",
extension_event_.event_data->ToCString());
}
+
+ if (kind() == kCpuSamples) {
+ JSONObject cpu_profile(&jsobj, "cpuSamples");
+ cpu_profile_->PrintProfileJSON(&cpu_profile, false);
+ }
}
void ServiceEvent::PrintJSONHeader(JSONObject* jsobj) const {
diff --git a/runtime/vm/service_event.h b/runtime/vm/service_event.h
index 3b8de0e..4c0efdd 100644
--- a/runtime/vm/service_event.h
+++ b/runtime/vm/service_event.h
@@ -7,6 +7,7 @@
#include "vm/globals.h"
#include "vm/heap/heap.h"
+#include "vm/profiler_service.h"
namespace dart {
@@ -62,6 +63,8 @@
kUserTagChanged,
+ kCpuSamples,
+
kIllegal,
};
@@ -213,6 +216,9 @@
timeline_event_block_ = block;
}
+ Profile* cpu_profile() const { return cpu_profile_; }
+ void set_cpu_profile(Profile* profile) { cpu_profile_ = profile; }
+
void PrintJSON(JSONStream* js) const;
void PrintJSONHeader(JSONObject* jsobj) const;
@@ -246,6 +252,7 @@
intptr_t bytes_length_;
LogRecord log_record_;
ExtensionEvent extension_event_;
+ Profile* cpu_profile_;
int64_t timestamp_;
};
diff --git a/runtime/vm/service_isolate.cc b/runtime/vm/service_isolate.cc
index c243b02b..d840e7b 100644
--- a/runtime/vm/service_isolate.cc
+++ b/runtime/vm/service_isolate.cc
@@ -12,6 +12,7 @@
#include "vm/lockers.h"
#include "vm/message.h"
#include "vm/message_handler.h"
+#include "vm/message_snapshot.h"
#include "vm/native_arguments.h"
#include "vm/native_entry.h"
#include "vm/object.h"
@@ -91,9 +92,8 @@
sp, VM_SERVICE_SERVER_INFO_MESSAGE_ID, false /* ignored */,
Bool::Handle() /* ignored */));
ASSERT(!message.IsNull());
- MessageWriter writer(false);
- PortMap::PostMessage(
- writer.WriteMessage(message, port_, Message::kNormalPriority));
+ PortMap::PostMessage(WriteMessage(/* can_send_any_object */ false, message,
+ port_, Message::kNormalPriority));
}
void ServiceIsolate::ControlWebServer(const SendPort& sp,
@@ -102,9 +102,8 @@
const Array& message = Array::Handle(MakeServerControlMessage(
sp, VM_SERVICE_WEB_SERVER_CONTROL_MESSAGE_ID, enable, silenceOutput));
ASSERT(!message.IsNull());
- MessageWriter writer(false);
- PortMap::PostMessage(
- writer.WriteMessage(message, port_, Message::kNormalPriority));
+ PortMap::PostMessage(WriteMessage(/* can_send_any_object */ false, message,
+ port_, Message::kNormalPriority));
}
void ServiceIsolate::SetServerAddress(const char* address) {
@@ -223,14 +222,13 @@
const Array& list = Array::Handle(MakeServiceControlMessage(
Dart_GetMainPortId(), VM_SERVICE_ISOLATE_STARTUP_MESSAGE_ID, name));
ASSERT(!list.IsNull());
- MessageWriter writer(false);
if (FLAG_trace_service) {
OS::PrintErr(DART_VM_SERVICE_ISOLATE_NAME ": Isolate %s %" Pd64
" registered.\n",
name.ToCString(), Dart_GetMainPortId());
}
- return PortMap::PostMessage(
- writer.WriteMessage(list, port_, Message::kNormalPriority));
+ return PortMap::PostMessage(WriteMessage(
+ /* can_send_any_object */ false, list, port_, Message::kNormalPriority));
}
bool ServiceIsolate::SendIsolateShutdownMessage() {
@@ -249,14 +247,13 @@
const Array& list = Array::Handle(MakeServiceControlMessage(
Dart_GetMainPortId(), VM_SERVICE_ISOLATE_SHUTDOWN_MESSAGE_ID, name));
ASSERT(!list.IsNull());
- MessageWriter writer(false);
if (FLAG_trace_service) {
OS::PrintErr(DART_VM_SERVICE_ISOLATE_NAME ": Isolate %s %" Pd64
" deregistered.\n",
name.ToCString(), Dart_GetMainPortId());
}
- return PortMap::PostMessage(
- writer.WriteMessage(list, port_, Message::kNormalPriority));
+ return PortMap::PostMessage(WriteMessage(
+ /* can_send_any_object */ false, list, port_, Message::kNormalPriority));
}
void ServiceIsolate::SendServiceExitMessage() {
@@ -278,9 +275,9 @@
message.value.as_array.length = 1;
message.value.as_array.values = values;
- ApiMessageWriter writer;
- PortMap::PostMessage(
- writer.WriteCMessage(&message, port_, Message::kNormalPriority));
+ AllocOnlyStackZone zone;
+ PortMap::PostMessage(WriteApiMessage(zone.GetZone(), &message, port_,
+ Message::kNormalPriority));
}
void ServiceIsolate::SetServicePort(Dart_Port port) {
diff --git a/runtime/vm/service_test.cc b/runtime/vm/service_test.cc
index 7dec0a8..2800565 100644
--- a/runtime/vm/service_test.cc
+++ b/runtime/vm/service_test.cc
@@ -14,6 +14,7 @@
#include "vm/globals.h"
#include "vm/heap/safepoint.h"
#include "vm/message_handler.h"
+#include "vm/message_snapshot.h"
#include "vm/object_id_ring.h"
#include "vm/os.h"
#include "vm/port.h"
@@ -50,8 +51,7 @@
response_obj = message->raw_obj();
} else {
Thread* thread = Thread::Current();
- MessageSnapshotReader reader(message.get(), thread);
- response_obj = reader.ReadObject();
+ response_obj = ReadMessage(thread, message.get());
}
if (response_obj.IsString()) {
String& response = String::Handle();
diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc
index f849156..f9b3cdc 100644
--- a/runtime/vm/snapshot.cc
+++ b/runtime/vm/snapshot.cc
@@ -5,228 +5,10 @@
#include "vm/snapshot.h"
#include "platform/assert.h"
-#include "vm/bootstrap.h"
-#include "vm/class_finalizer.h"
#include "vm/dart.h"
-#include "vm/exceptions.h"
-#include "vm/heap/heap.h"
-#include "vm/longjump.h"
-#include "vm/message.h"
-#include "vm/object.h"
-#include "vm/object_store.h"
-#include "vm/snapshot_ids.h"
-#include "vm/stub_code.h"
-#include "vm/symbols.h"
-#include "vm/timeline.h"
-#include "vm/type_testing_stubs.h"
-#include "vm/version.h"
-
-// We currently only expect the Dart mutator to read snapshots.
-#define ASSERT_NO_SAFEPOINT_SCOPE() \
- isolate()->AssertCurrentThreadIsMutator(); \
- ASSERT(thread()->no_safepoint_scope_depth() != 0)
namespace dart {
-static const int kNumInitialReferences = 32;
-
-static bool IsSingletonClassId(intptr_t class_id) {
- // Check if this is a singleton object class which is shared by all isolates.
- return ((class_id >= kClassCid && class_id <= kUnwindErrorCid) ||
- (class_id == kTypeArgumentsCid) ||
- (class_id >= kNullCid && class_id <= kVoidCid));
-}
-
-static bool IsBootstrapedClassId(intptr_t class_id) {
- // Check if this is a class which is created during bootstrapping.
- return (class_id == kObjectCid ||
- (class_id >= kInstanceCid && class_id <= kUserTagCid) ||
- class_id == kArrayCid || class_id == kImmutableArrayCid ||
- IsStringClassId(class_id) || IsTypedDataClassId(class_id) ||
- IsExternalTypedDataClassId(class_id) ||
- IsTypedDataViewClassId(class_id) || class_id == kNullCid ||
- class_id == kNeverCid || class_id == kTransferableTypedDataCid);
-}
-
-static bool IsObjectStoreTypeId(intptr_t index) {
- // Check if this is a type which is stored in the object store.
- static_assert(kFirstTypeArgumentsSnapshotId == kLastTypeSnapshotId + 1,
- "Type and type arguments snapshot ids should be adjacent");
- return index >= kFirstTypeSnapshotId && index <= kLastTypeArgumentsSnapshotId;
-}
-
-static bool IsSplitClassId(intptr_t class_id) {
- // Return whether this class is serialized in two steps: first a reference,
- // with sufficient information to allocate a correctly sized object, and then
- // later inline with complete contents.
- return class_id >= kNumPredefinedCids || class_id == kArrayCid ||
- class_id == kImmutableArrayCid || class_id == kObjectPoolCid ||
- IsImplicitFieldClassId(class_id);
-}
-
-static intptr_t ClassIdFromObjectId(intptr_t object_id) {
- ASSERT(object_id > kClassIdsOffset);
- intptr_t class_id = (object_id - kClassIdsOffset);
- return class_id;
-}
-
-static intptr_t ObjectIdFromClassId(intptr_t class_id) {
- ASSERT((class_id > kIllegalCid) && (class_id < kNumPredefinedCids));
- return (class_id + kClassIdsOffset);
-}
-
-static ObjectPtr GetType(ObjectStore* object_store, intptr_t index) {
- switch (index) {
- case kLegacyObjectType:
- return object_store->legacy_object_type();
- case kNullableObjectType:
- return object_store->nullable_object_type();
- case kNullType:
- return object_store->null_type();
- case kNeverType:
- return object_store->never_type();
- case kLegacyFunctionType:
- return object_store->legacy_function_type();
- case kLegacyNumberType:
- return object_store->legacy_number_type();
- case kLegacySmiType:
- return object_store->legacy_smi_type();
- case kLegacyMintType:
- return object_store->legacy_mint_type();
- case kLegacyDoubleType:
- return object_store->legacy_double_type();
- case kLegacyIntType:
- return object_store->legacy_int_type();
- case kLegacyBoolType:
- return object_store->legacy_bool_type();
- case kLegacyStringType:
- return object_store->legacy_string_type();
- case kLegacyArrayType:
- return object_store->legacy_array_type();
- case kLegacyIntTypeArguments:
- return object_store->type_argument_legacy_int();
- case kLegacyDoubleTypeArguments:
- return object_store->type_argument_legacy_double();
- case kLegacyStringTypeArguments:
- return object_store->type_argument_legacy_string();
- case kLegacyStringDynamicTypeArguments:
- return object_store->type_argument_legacy_string_dynamic();
- case kLegacyStringLegacyStringTypeArguments:
- return object_store->type_argument_legacy_string_legacy_string();
- case kNonNullableObjectType:
- return object_store->non_nullable_object_type();
- case kNonNullableFunctionType:
- return object_store->non_nullable_function_type();
- case kNonNullableNumberType:
- return object_store->non_nullable_number_type();
- case kNonNullableSmiType:
- return object_store->non_nullable_smi_type();
- case kNonNullableMintType:
- return object_store->non_nullable_mint_type();
- case kNonNullableDoubleType:
- return object_store->non_nullable_double_type();
- case kNonNullableIntType:
- return object_store->non_nullable_int_type();
- case kNonNullableBoolType:
- return object_store->non_nullable_bool_type();
- case kNonNullableStringType:
- return object_store->non_nullable_string_type();
- case kNonNullableArrayType:
- return object_store->non_nullable_array_type();
- case kNonNullableIntTypeArguments:
- return object_store->type_argument_non_nullable_int();
- case kNonNullableDoubleTypeArguments:
- return object_store->type_argument_non_nullable_double();
- case kNonNullableStringTypeArguments:
- return object_store->type_argument_non_nullable_string();
- case kNonNullableStringDynamicTypeArguments:
- return object_store->type_argument_non_nullable_string_dynamic();
- case kNonNullableStringNonNullableStringTypeArguments:
- return object_store
- ->type_argument_non_nullable_string_non_nullable_string();
- default:
- break;
- }
- UNREACHABLE();
- return Type::null();
-}
-
-static intptr_t GetTypeIndex(ObjectStore* object_store,
- const ObjectPtr raw_type) {
- if (raw_type == object_store->legacy_object_type()) {
- return kLegacyObjectType;
- } else if (raw_type == object_store->nullable_object_type()) {
- return kNullableObjectType;
- } else if (raw_type == object_store->null_type()) {
- return kNullType;
- } else if (raw_type == object_store->never_type()) {
- return kNeverType;
- } else if (raw_type == object_store->legacy_function_type()) {
- return kLegacyFunctionType;
- } else if (raw_type == object_store->legacy_number_type()) {
- return kLegacyNumberType;
- } else if (raw_type == object_store->legacy_smi_type()) {
- return kLegacySmiType;
- } else if (raw_type == object_store->legacy_mint_type()) {
- return kLegacyMintType;
- } else if (raw_type == object_store->legacy_double_type()) {
- return kLegacyDoubleType;
- } else if (raw_type == object_store->legacy_int_type()) {
- return kLegacyIntType;
- } else if (raw_type == object_store->legacy_bool_type()) {
- return kLegacyBoolType;
- } else if (raw_type == object_store->legacy_string_type()) {
- return kLegacyStringType;
- } else if (raw_type == object_store->legacy_array_type()) {
- return kLegacyArrayType;
- } else if (raw_type == object_store->type_argument_legacy_int()) {
- return kLegacyIntTypeArguments;
- } else if (raw_type == object_store->type_argument_legacy_double()) {
- return kLegacyDoubleTypeArguments;
- } else if (raw_type == object_store->type_argument_legacy_string()) {
- return kLegacyStringTypeArguments;
- } else if (raw_type == object_store->type_argument_legacy_string_dynamic()) {
- return kLegacyStringDynamicTypeArguments;
- } else if (raw_type ==
- object_store->type_argument_legacy_string_legacy_string()) {
- return kLegacyStringLegacyStringTypeArguments;
- } else if (raw_type == object_store->non_nullable_object_type()) {
- return kNonNullableObjectType;
- } else if (raw_type == object_store->non_nullable_function_type()) {
- return kNonNullableFunctionType;
- } else if (raw_type == object_store->non_nullable_number_type()) {
- return kNonNullableNumberType;
- } else if (raw_type == object_store->non_nullable_smi_type()) {
- return kNonNullableSmiType;
- } else if (raw_type == object_store->non_nullable_mint_type()) {
- return kNonNullableMintType;
- } else if (raw_type == object_store->non_nullable_double_type()) {
- return kNonNullableDoubleType;
- } else if (raw_type == object_store->non_nullable_int_type()) {
- return kNonNullableIntType;
- } else if (raw_type == object_store->non_nullable_bool_type()) {
- return kNonNullableBoolType;
- } else if (raw_type == object_store->non_nullable_string_type()) {
- return kNonNullableStringType;
- } else if (raw_type == object_store->non_nullable_array_type()) {
- return kNonNullableArrayType;
- } else if (raw_type == object_store->type_argument_non_nullable_int()) {
- return kNonNullableIntTypeArguments;
- } else if (raw_type == object_store->type_argument_non_nullable_double()) {
- return kNonNullableDoubleTypeArguments;
- } else if (raw_type == object_store->type_argument_non_nullable_string()) {
- return kNonNullableStringTypeArguments;
- } else if (raw_type ==
- object_store->type_argument_non_nullable_string_dynamic()) {
- return kNonNullableStringDynamicTypeArguments;
- } else if (raw_type ==
- object_store
- ->type_argument_non_nullable_string_non_nullable_string()) {
- return kNonNullableStringNonNullableStringTypeArguments;
- }
- return kInvalidIndex;
-}
-
const char* Snapshot::KindToCString(Kind kind) {
switch (kind) {
case kFull:
@@ -237,8 +19,6 @@
return "full-jit";
case kFullAOT:
return "full-aot";
- case kMessage:
- return "message";
case kNone:
return "none";
case kInvalid:
@@ -262,96 +42,7 @@
return snapshot;
}
-SmiPtr BaseReader::ReadAsSmi() {
- SmiPtr value = static_cast<SmiPtr>(Read<intptr_t>());
- ASSERT((static_cast<uword>(value) & kSmiTagMask) == kSmiTag);
- return value;
-}
-
-intptr_t BaseReader::ReadSmiValue() {
- return Smi::Value(ReadAsSmi());
-}
-
-SnapshotReader::SnapshotReader(const uint8_t* buffer,
- intptr_t size,
- Snapshot::Kind kind,
- ZoneGrowableArray<BackRefNode>* backward_refs,
- Thread* thread)
- : BaseReader(buffer, size),
- kind_(kind),
- thread_(thread),
- zone_(thread->zone()),
- heap_(isolate_group()->heap()),
- old_space_(isolate_group()->heap()->old_space()),
- cls_(Class::Handle(zone_)),
- code_(Code::Handle(zone_)),
- instance_(Instance::Handle(zone_)),
- instructions_(Instructions::Handle(zone_)),
- obj_(Object::Handle(zone_)),
- pobj_(PassiveObject::Handle(zone_)),
- array_(Array::Handle(zone_)),
- field_(Field::Handle(zone_)),
- str_(String::Handle(zone_)),
- library_(Library::Handle(zone_)),
- type_(AbstractType::Handle(zone_)),
- type_arguments_(TypeArguments::Handle(zone_)),
- tokens_(GrowableObjectArray::Handle(zone_)),
- data_(ExternalTypedData::Handle(zone_)),
- typed_data_base_(TypedDataBase::Handle(zone_)),
- typed_data_(TypedData::Handle(zone_)),
- typed_data_view_(TypedDataView::Handle(zone_)),
- function_(Function::Handle(zone_)),
- smi_(Smi::Handle(zone_)),
- error_(UnhandledException::Handle(zone_)),
- set_class_(Class::ZoneHandle(
- zone_,
- thread_->isolate_group()->object_store()->linked_hash_set_class())),
- max_vm_isolate_object_id_(
- (Snapshot::IsFull(kind))
- ? Object::vm_isolate_snapshot_object_table().Length()
- : 0),
- backward_references_(backward_refs),
- types_to_postprocess_(GrowableObjectArray::Handle(zone_)),
- objects_to_rehash_(GrowableObjectArray::Handle(zone_)) {}
-
-ObjectPtr SnapshotReader::ReadObject() {
- // Setup for long jump in case there is an exception while reading.
- LongJumpScope jump;
- if (setjmp(*jump.Set()) == 0) {
- PassiveObject& obj =
- PassiveObject::Handle(zone(), ReadObjectImpl(kAsInlinedObject));
- for (intptr_t i = 0; i < backward_references_->length(); i++) {
- if (!(*backward_references_)[i].is_deserialized()) {
- ReadObjectImpl(kAsInlinedObject);
- (*backward_references_)[i].set_state(kIsDeserialized);
- }
- }
- Object& result = Object::Handle(zone_);
- if (backward_references_->length() > 0) {
- result = (*backward_references_)[0].reference()->ptr();
- } else {
- result = obj.ptr();
- }
- RunDelayedTypePostprocessing();
- const Object& ok = Object::Handle(zone_, RunDelayedRehashingOfMaps());
- objects_to_rehash_ = GrowableObjectArray::null();
- if (!ok.IsNull()) {
- return ok.ptr();
- }
- return result.ptr();
- } else {
- // An error occurred while reading, return the error object.
- return Thread::Current()->StealStickyError();
- }
-}
-
-void SnapshotReader::EnqueueTypePostprocessing(const AbstractType& type) {
- if (types_to_postprocess_.IsNull()) {
- types_to_postprocess_ = GrowableObjectArray::New();
- }
- types_to_postprocess_.Add(type);
-}
-
+#if 0
void SnapshotReader::RunDelayedTypePostprocessing() {
if (types_to_postprocess_.IsNull()) {
return;
@@ -365,1283 +56,6 @@
type.InitializeTypeTestingStubNonAtomic(code);
}
}
-
-void SnapshotReader::EnqueueRehashingOfMap(const LinkedHashMap& map) {
- if (objects_to_rehash_.IsNull()) {
- objects_to_rehash_ = GrowableObjectArray::New();
- }
- objects_to_rehash_.Add(map);
-}
-
-ObjectPtr SnapshotReader::RunDelayedRehashingOfMaps() {
- if (!objects_to_rehash_.IsNull()) {
- return DartLibraryCalls::RehashObjects(thread(), objects_to_rehash_);
- }
- return Object::null();
-}
-
-ClassPtr SnapshotReader::ReadClassId(intptr_t object_id) {
- ASSERT(!Snapshot::IsFull(kind_));
- // Read the class header information and lookup the class.
- intptr_t class_header = Read<int32_t>();
- ASSERT((class_header & kSmiTagMask) != kSmiTag);
- ASSERT(!IsVMIsolateObject(class_header) ||
- !IsSingletonClassId(GetVMIsolateObjectId(class_header)));
- ASSERT((SerializedHeaderTag::decode(class_header) != kObjectId) ||
- !IsBootstrapedClassId(SerializedHeaderData::decode(class_header)));
- Class& cls = Class::ZoneHandle(zone(), Class::null());
- AddBackRef(object_id, &cls, kIsDeserialized);
- // Read the library/class information and lookup the class.
- str_ ^= ReadObjectImpl(class_header, kAsInlinedObject);
- library_ = Library::LookupLibrary(thread(), str_);
- if (library_.IsNull() || !library_.Loaded()) {
- SetReadException(
- "Invalid object found in message: library is not found or loaded.");
- }
- str_ ^= ReadObjectImpl(kAsInlinedObject);
- if (str_.ptr() == Symbols::TopLevel().ptr()) {
- cls = library_.toplevel_class();
- } else {
- str_ = String::New(String::ScrubName(str_));
- cls = library_.LookupClassAllowPrivate(str_);
- }
- if (cls.IsNull()) {
- SetReadException("Invalid object found in message: class not found");
- }
- cls.EnsureIsFinalized(thread());
- return cls.ptr();
-}
-
-ObjectPtr SnapshotReader::ReadStaticImplicitClosure(intptr_t object_id,
- intptr_t class_header) {
- ASSERT(!Snapshot::IsFull(kind_));
-
- // First create a function object and associate it with the specified
- // 'object_id'.
- Function& func = Function::Handle(zone(), Function::null());
- Instance& obj = Instance::ZoneHandle(zone(), Instance::null());
- AddBackRef(object_id, &obj, kIsDeserialized);
-
- // Read the library/class/function information and lookup the function.
- // Note: WriteStaticImplicitClosure is *not* scrubbing the names before
- // writing them into the snapshot, because scrubbing requires allocation.
- // This means that names we read here might be mangled with private
- // keys. These keys need to be scrubbed before performing lookups
- // otherwise lookups might fail.
- str_ ^= ReadObjectImpl(kAsInlinedObject);
- library_ = Library::LookupLibrary(thread(), str_);
- if (library_.IsNull() || !library_.Loaded()) {
- SetReadException("Invalid Library object found in message.");
- }
- str_ ^= ReadObjectImpl(kAsInlinedObject);
- if (str_.Equals(Symbols::TopLevel())) {
- str_ ^= ReadObjectImpl(kAsInlinedObject);
- str_ = String::New(String::ScrubName(str_));
- func = library_.LookupFunctionAllowPrivate(str_);
- } else {
- str_ = String::New(String::ScrubName(str_));
- cls_ = library_.LookupClassAllowPrivate(str_);
- if (cls_.IsNull()) {
- OS::PrintErr("Name of class not found %s\n", str_.ToCString());
- SetReadException("Invalid Class object found in message.");
- }
- cls_.EnsureIsFinalized(thread());
- str_ ^= ReadObjectImpl(kAsInlinedObject);
- str_ = String::New(String::ScrubName(str_));
- func = cls_.LookupFunctionAllowPrivate(str_);
- }
- if (func.IsNull()) {
- SetReadException("Invalid function object found in message.");
- }
- TypeArguments& delayed_type_arguments = TypeArguments::Handle(zone());
- delayed_type_arguments ^= ReadObjectImpl(kAsInlinedObject);
-
- func = func.ImplicitClosureFunction();
- ASSERT(!func.IsNull());
-
- // If delayedtype arguments were provided, create and return new closure with
- // those, otherwise return associated implicit static closure.
- // Note that static closures can't have instantiator or function types since
- // statics can't refer to class type arguments, don't have outer functions.
- if (!delayed_type_arguments.IsNull()) {
- const Context& context = Context::Handle(zone());
- obj = Closure::New(
- /*instantiator_type_arguments=*/Object::null_type_arguments(),
- /*function_type_arguments=*/Object::null_type_arguments(),
- delayed_type_arguments, func, context, Heap::kOld);
- } else {
- obj = func.ImplicitStaticClosure();
- }
- return obj.ptr();
-}
-
-intptr_t SnapshotReader::NextAvailableObjectId() const {
- return backward_references_->length() + kMaxPredefinedObjectIds +
- max_vm_isolate_object_id_;
-}
-
-void SnapshotReader::SetReadException(const char* msg) {
- const String& error_str = String::Handle(zone(), String::New(msg));
- const Array& args = Array::Handle(zone(), Array::New(1));
- args.SetAt(0, error_str);
- Object& result = Object::Handle(zone());
- const Library& library = Library::Handle(zone(), Library::CoreLibrary());
- result = DartLibraryCalls::InstanceCreate(library, Symbols::ArgumentError(),
- Symbols::Dot(), args);
- const StackTrace& stacktrace = StackTrace::Handle(zone());
- const UnhandledException& error = UnhandledException::Handle(
- zone(), UnhandledException::New(Instance::Cast(result), stacktrace));
- thread()->long_jump_base()->Jump(1, error);
-}
-
-ObjectPtr SnapshotReader::VmIsolateSnapshotObject(intptr_t index) const {
- return Object::vm_isolate_snapshot_object_table().At(index);
-}
-
-bool SnapshotReader::is_vm_isolate() const {
- return isolate_group() == Dart::vm_isolate_group();
-}
-
-ObjectPtr SnapshotReader::ReadObjectImpl(bool as_reference) {
- int64_t header_value = Read<int64_t>();
- if ((header_value & kSmiTagMask) == kSmiTag) {
- return NewInteger(header_value);
- }
- ASSERT((header_value <= kIntptrMax) && (header_value >= kIntptrMin));
- return ReadObjectImpl(static_cast<intptr_t>(header_value), as_reference);
-}
-
-ObjectPtr SnapshotReader::ReadObjectImpl(intptr_t header_value,
- bool as_reference) {
- if (IsVMIsolateObject(header_value)) {
- return ReadVMIsolateObject(header_value);
- }
- if (SerializedHeaderTag::decode(header_value) == kObjectId) {
- return ReadIndexedObject(SerializedHeaderData::decode(header_value));
- }
- ASSERT(SerializedHeaderTag::decode(header_value) == kInlined);
- intptr_t object_id = SerializedHeaderData::decode(header_value);
- if (object_id == kOmittedObjectId) {
- object_id = NextAvailableObjectId();
- }
-
- // Read the class header information.
- intptr_t class_header = Read<int32_t>();
- intptr_t tags = ReadTags();
- bool read_as_reference = as_reference && !UntaggedObject::IsCanonical(tags);
- intptr_t header_id = SerializedHeaderData::decode(class_header);
- if (header_id == kInstanceObjectId) {
- return ReadInstance(object_id, tags, read_as_reference);
- } else if (header_id == kStaticImplicitClosureObjectId) {
- // We skip the tags that have been written as the implicit static
- // closure is going to be created in this isolate or the canonical
- // version already created in the isolate will be used.
- return ReadStaticImplicitClosure(object_id, class_header);
- }
- ASSERT((class_header & kSmiTagMask) != kSmiTag);
-
- intptr_t class_id = LookupInternalClass(class_header);
- switch (class_id) {
-#define SNAPSHOT_READ(clazz) \
- case clazz::kClassId: { \
- pobj_ = clazz::ReadFrom(this, object_id, tags, kind_, read_as_reference); \
- break; \
- }
- CLASS_LIST_NO_OBJECT(SNAPSHOT_READ)
-#undef SNAPSHOT_READ
-#define SNAPSHOT_READ(clazz) case kTypedData##clazz##Cid:
-
- CLASS_LIST_TYPED_DATA(SNAPSHOT_READ) {
- tags = UntaggedObject::ClassIdTag::update(class_id, tags);
- pobj_ =
- TypedData::ReadFrom(this, object_id, tags, kind_, read_as_reference);
- break;
- }
-#undef SNAPSHOT_READ
-#define SNAPSHOT_READ(clazz) case kExternalTypedData##clazz##Cid:
-
- CLASS_LIST_TYPED_DATA(SNAPSHOT_READ) {
- tags = UntaggedObject::ClassIdTag::update(class_id, tags);
- pobj_ = ExternalTypedData::ReadFrom(this, object_id, tags, kind_, true);
- break;
- }
-#undef SNAPSHOT_READ
-#define SNAPSHOT_READ(clazz) case kTypedData##clazz##ViewCid:
-
- case kByteDataViewCid:
- CLASS_LIST_TYPED_DATA(SNAPSHOT_READ) {
- tags = UntaggedObject::ClassIdTag::update(class_id, tags);
- pobj_ = TypedDataView::ReadFrom(this, object_id, tags, kind_, true);
- break;
- }
-#undef SNAPSHOT_READ
-#define SNAPSHOT_READ(clazz) case kFfi##clazz##Cid:
-
- CLASS_LIST_FFI(SNAPSHOT_READ) { UNREACHABLE(); }
-#undef SNAPSHOT_READ
- default:
- UNREACHABLE();
- break;
- }
- return pobj_.ptr();
-}
-
-void SnapshotReader::EnqueueRehashingOfSet(const Object& set) {
- if (objects_to_rehash_.IsNull()) {
- objects_to_rehash_ = GrowableObjectArray::New();
- }
- objects_to_rehash_.Add(set);
-}
-
-ObjectPtr SnapshotReader::ReadInstance(intptr_t object_id,
- intptr_t tags,
- bool as_reference) {
- // Object is regular dart instance.
- intptr_t instance_size = 0;
- Instance* result = NULL;
- DeserializeState state;
- if (!as_reference) {
- result = reinterpret_cast<Instance*>(GetBackRef(object_id));
- state = kIsDeserialized;
- } else {
- state = kIsNotDeserialized;
- }
- if (result == NULL) {
- result = &(Instance::ZoneHandle(zone(), Instance::null()));
- AddBackRef(object_id, result, state);
- cls_ ^= ReadObjectImpl(kAsInlinedObject);
- ASSERT(!cls_.IsNull());
- // Closure instances are handled by Closure::ReadFrom().
- ASSERT(!cls_.IsClosureClass());
- instance_size = cls_.host_instance_size();
- ASSERT(instance_size > 0);
- // Allocate the instance and read in all the fields for the object.
- *result ^= Object::Allocate(cls_.id(), instance_size, Heap::kNew,
- Instance::ContainsCompressedPointers());
- } else {
- cls_ ^= ReadObjectImpl(kAsInlinedObject);
- ASSERT(!cls_.IsNull());
- instance_size = cls_.host_instance_size();
- }
- if (cls_.id() == set_class_.id()) {
- EnqueueRehashingOfSet(*result);
- }
- if (!as_reference) {
- // Read all the individual fields for inlined objects.
- intptr_t next_field_offset = cls_.host_next_field_offset();
-
- intptr_t type_argument_field_offset =
- cls_.host_type_arguments_field_offset();
- ASSERT(next_field_offset > 0);
- // Instance::NextFieldOffset() returns the offset of the first field in
- // a Dart object.
- bool read_as_reference = UntaggedObject::IsCanonical(tags) ? false : true;
- intptr_t offset = Instance::NextFieldOffset();
- intptr_t result_cid = result->GetClassId();
-
- const auto unboxed_fields =
- isolate_group()->shared_class_table()->GetUnboxedFieldsMapAt(
- result_cid);
-
- while (offset < next_field_offset) {
- if (unboxed_fields.Get(offset / kCompressedWordSize)) {
- uword* p = reinterpret_cast<uword*>(result->raw_value() -
- kHeapObjectTag + offset);
- // Reads 32 bits of the unboxed value at a time
- *p = ReadWordWith32BitReads();
- } else {
- pobj_ = ReadObjectImpl(read_as_reference);
- result->SetFieldAtOffset(offset, pobj_);
- if ((offset != type_argument_field_offset) &&
- (kind_ == Snapshot::kMessage) &&
- isolate_group()->use_field_guards() &&
- (pobj_.ptr() != Object::sentinel().ptr())) {
- // TODO(fschneider): Consider hoisting these lookups out of the loop.
- // This would involve creating a handle, since cls_ can't be reused
- // across the call to ReadObjectImpl.
- cls_ = isolate_group()->class_table()->At(result_cid);
- array_ = cls_.OffsetToFieldMap();
- field_ ^= array_.At(offset >> kCompressedWordSizeLog2);
- ASSERT(!field_.IsNull());
- ASSERT(field_.HostOffset() == offset);
- obj_ = pobj_.ptr();
- field_.RecordStore(obj_);
- }
- // TODO(fschneider): Verify the guarded cid and length for other kinds
- // of snapshot (kFull, kScript) with asserts.
- }
- offset += kCompressedWordSize;
- }
- if (UntaggedObject::IsCanonical(tags)) {
- *result = result->Canonicalize(thread());
- ASSERT(!result->IsNull());
- }
- }
- return result->ptr();
-}
-
-void SnapshotReader::AddBackRef(intptr_t id,
- Object* obj,
- DeserializeState state) {
- intptr_t index = (id - kMaxPredefinedObjectIds);
- ASSERT(index >= max_vm_isolate_object_id_);
- index -= max_vm_isolate_object_id_;
- ASSERT(index == backward_references_->length());
- BackRefNode node(obj, state);
- backward_references_->Add(node);
-}
-
-Object* SnapshotReader::GetBackRef(intptr_t id) {
- ASSERT(id >= kMaxPredefinedObjectIds);
- intptr_t index = (id - kMaxPredefinedObjectIds);
- ASSERT(index >= max_vm_isolate_object_id_);
- index -= max_vm_isolate_object_id_;
- if (index < backward_references_->length()) {
- return (*backward_references_)[index].reference();
- }
- return NULL;
-}
-
-ApiErrorPtr SnapshotReader::VerifyVersionAndFeatures(
- IsolateGroup* isolate_group) {
- // If the version string doesn't match, return an error.
- // Note: New things are allocated only if we're going to return an error.
-
- const char* expected_version = Version::SnapshotString();
- ASSERT(expected_version != NULL);
- const intptr_t version_len = strlen(expected_version);
- if (PendingBytes() < version_len) {
- const intptr_t kMessageBufferSize = 128;
- char message_buffer[kMessageBufferSize];
- Utils::SNPrint(message_buffer, kMessageBufferSize,
- "No full snapshot version found, expected '%s'",
- expected_version);
- // This can also fail while bringing up the VM isolate, so make sure to
- // allocate the error message in old space.
- const String& msg = String::Handle(String::New(message_buffer, Heap::kOld));
- return ApiError::New(msg, Heap::kOld);
- }
-
- const char* version = reinterpret_cast<const char*>(CurrentBufferAddress());
- ASSERT(version != NULL);
- if (strncmp(version, expected_version, version_len) != 0) {
- const intptr_t kMessageBufferSize = 256;
- char message_buffer[kMessageBufferSize];
- char* actual_version = Utils::StrNDup(version, version_len);
- Utils::SNPrint(message_buffer, kMessageBufferSize,
- "Wrong %s snapshot version, expected '%s' found '%s'",
- (Snapshot::IsFull(kind_)) ? "full" : "script",
- expected_version, actual_version);
- free(actual_version);
- // This can also fail while bringing up the VM isolate, so make sure to
- // allocate the error message in old space.
- const String& msg = String::Handle(String::New(message_buffer, Heap::kOld));
- return ApiError::New(msg, Heap::kOld);
- }
- Advance(version_len);
-
- const char* expected_features =
- Dart::FeaturesString(isolate_group, false, kind_);
- ASSERT(expected_features != NULL);
- const intptr_t expected_len = strlen(expected_features);
-
- const char* features = reinterpret_cast<const char*>(CurrentBufferAddress());
- ASSERT(features != NULL);
- intptr_t buffer_len = Utils::StrNLen(features, PendingBytes());
- if ((buffer_len != expected_len) ||
- (strncmp(features, expected_features, expected_len) != 0)) {
- const intptr_t kMessageBufferSize = 256;
- char message_buffer[kMessageBufferSize];
- char* actual_features =
- Utils::StrNDup(features, buffer_len < 128 ? buffer_len : 128);
- Utils::SNPrint(message_buffer, kMessageBufferSize,
- "Snapshot not compatible with the current VM configuration: "
- "the snapshot requires '%s' but the VM has '%s'",
- actual_features, expected_features);
- free(const_cast<char*>(expected_features));
- free(actual_features);
- // This can also fail while bringing up the VM isolate, so make sure to
- // allocate the error message in old space.
- const String& msg = String::Handle(String::New(message_buffer, Heap::kOld));
- return ApiError::New(msg, Heap::kOld);
- }
- free(const_cast<char*>(expected_features));
- Advance(expected_len + 1);
- return ApiError::null();
-}
-
-ObjectPtr SnapshotReader::NewInteger(int64_t value) {
- ASSERT((value & kSmiTagMask) == kSmiTag);
- value = value >> kSmiTagShift;
- if (Smi::IsValid(value)) {
- return Smi::New(static_cast<intptr_t>(value));
- }
- return Mint::NewCanonical(value);
-}
-
-intptr_t SnapshotReader::LookupInternalClass(intptr_t class_header) {
- // If the header is an object Id, lookup singleton VM classes or classes
- // stored in the object store.
- if (IsVMIsolateObject(class_header)) {
- intptr_t class_id = GetVMIsolateObjectId(class_header);
- ASSERT(IsSingletonClassId(class_id));
- return class_id;
- }
- ASSERT(SerializedHeaderTag::decode(class_header) == kObjectId);
- intptr_t class_id = SerializedHeaderData::decode(class_header);
- ASSERT(IsBootstrapedClassId(class_id) || IsSingletonClassId(class_id));
- return class_id;
-}
-
-#define READ_VM_SINGLETON_OBJ(id, obj) \
- if (object_id == id) { \
- return obj; \
- }
-
-ObjectPtr SnapshotReader::ReadVMIsolateObject(intptr_t header_value) {
- intptr_t object_id = GetVMIsolateObjectId(header_value);
-
- // First check if it is one of the singleton objects.
- READ_VM_SINGLETON_OBJ(kNullObject, Object::null());
- READ_VM_SINGLETON_OBJ(kSentinelObject, Object::sentinel().ptr());
- READ_VM_SINGLETON_OBJ(kTransitionSentinelObject,
- Object::transition_sentinel().ptr());
- READ_VM_SINGLETON_OBJ(kEmptyArrayObject, Object::empty_array().ptr());
- READ_VM_SINGLETON_OBJ(kZeroArrayObject, Object::zero_array().ptr());
- READ_VM_SINGLETON_OBJ(kDynamicType, Object::dynamic_type().ptr());
- READ_VM_SINGLETON_OBJ(kVoidType, Object::void_type().ptr());
- READ_VM_SINGLETON_OBJ(kEmptyTypeArguments,
- Object::empty_type_arguments().ptr());
- READ_VM_SINGLETON_OBJ(kTrueValue, Bool::True().ptr());
- READ_VM_SINGLETON_OBJ(kFalseValue, Bool::False().ptr());
- READ_VM_SINGLETON_OBJ(kExtractorParameterTypes,
- Object::extractor_parameter_types().ptr());
- READ_VM_SINGLETON_OBJ(kExtractorParameterNames,
- Object::extractor_parameter_names().ptr());
- READ_VM_SINGLETON_OBJ(kEmptyContextScopeObject,
- Object::empty_context_scope().ptr());
- READ_VM_SINGLETON_OBJ(kEmptyObjectPool, Object::empty_object_pool().ptr());
- READ_VM_SINGLETON_OBJ(kEmptyDescriptors, Object::empty_descriptors().ptr());
- READ_VM_SINGLETON_OBJ(kEmptyVarDescriptors,
- Object::empty_var_descriptors().ptr());
- READ_VM_SINGLETON_OBJ(kEmptyExceptionHandlers,
- Object::empty_exception_handlers().ptr());
-
- // Check if it is a double.
- if (object_id == kDoubleObject) {
- ASSERT(kind_ == Snapshot::kMessage);
- return Double::New(ReadDouble());
- }
-
- // Check it is a singleton class object.
- intptr_t class_id = ClassIdFromObjectId(object_id);
- if (IsSingletonClassId(class_id)) {
- return isolate_group()->class_table()->At(
- class_id); // get singleton class.
- }
-
- // Check if it is a singleton Argument descriptor object.
- for (intptr_t i = 0; i < ArgumentsDescriptor::kCachedDescriptorCount; i++) {
- if (object_id == (kCachedArgumentsDescriptor0 + i)) {
- return ArgumentsDescriptor::cached_args_descriptors_[i];
- }
- }
-
- // Check if it is a singleton ICData array object.
- for (intptr_t i = 0; i < ICData::kCachedICDataArrayCount; i++) {
- if (object_id == (kCachedICDataArray0 + i)) {
- return ICData::cached_icdata_arrays_[i];
- }
- }
-
- ASSERT(Symbols::IsPredefinedSymbolId(object_id));
- return Symbols::GetPredefinedSymbol(object_id); // return VM symbol.
-}
-
-ObjectPtr SnapshotReader::ReadIndexedObject(intptr_t object_id) {
- intptr_t class_id = ClassIdFromObjectId(object_id);
- if (IsBootstrapedClassId(class_id)) {
- return isolate_group()->class_table()->At(
- class_id); // get singleton class.
- }
- if (IsObjectStoreTypeId(object_id)) {
- return GetType(object_store(), object_id); // return type obj.
- }
- ASSERT(object_id >= kMaxPredefinedObjectIds);
- intptr_t index = (object_id - kMaxPredefinedObjectIds);
- if (index < max_vm_isolate_object_id_) {
- return VmIsolateSnapshotObject(index);
- }
- return GetBackRef(object_id)->ptr();
-}
-
-void SnapshotReader::ArrayReadFrom(intptr_t object_id,
- const Array& result,
- intptr_t len,
- intptr_t tags) {
- // Setup the object fields.
- *TypeArgumentsHandle() ^= ReadObjectImpl(kAsInlinedObject);
- result.SetTypeArguments(*TypeArgumentsHandle());
-
- bool as_reference = UntaggedObject::IsCanonical(tags) ? false : true;
- for (intptr_t i = 0; i < len; i++) {
- *PassiveObjectHandle() = ReadObjectImpl(as_reference);
- result.SetAt(i, *PassiveObjectHandle());
- }
-}
-
-MessageSnapshotReader::MessageSnapshotReader(Message* message, Thread* thread)
- : SnapshotReader(message->snapshot(),
- message->snapshot_length(),
- Snapshot::kMessage,
- new ZoneGrowableArray<BackRefNode>(kNumInitialReferences),
- thread),
- finalizable_data_(message->finalizable_data()) {}
-
-MessageSnapshotReader::~MessageSnapshotReader() {
- ResetBackwardReferenceTable();
-}
-
-SnapshotWriter::SnapshotWriter(Thread* thread,
- Snapshot::Kind kind,
- intptr_t initial_size,
- ForwardList* forward_list,
- bool can_send_any_object)
- : BaseWriter(initial_size),
- thread_(thread),
- kind_(kind),
- object_store_(isolate_group()->object_store()),
- class_table_(isolate_group()->class_table()),
- forward_list_(forward_list),
- exception_type_(Exceptions::kNone),
- exception_msg_(NULL),
- can_send_any_object_(can_send_any_object) {
- ASSERT(forward_list_ != NULL);
-}
-
-void SnapshotWriter::WriteObject(ObjectPtr rawobj) {
- WriteObjectImpl(rawobj, kAsInlinedObject);
- WriteForwardedObjects();
-}
-
-uint32_t SnapshotWriter::GetObjectTags(ObjectPtr raw) {
- uword tags = raw->untag()->tags_;
-#if defined(HASH_IN_OBJECT_HEADER)
- // Clear hash to make the narrowing cast safe / appease UBSAN.
- tags = UntaggedObject::HashTag::update(0, tags);
#endif
- return tags;
-}
-
-uint32_t SnapshotWriter::GetObjectTags(UntaggedObject* raw) {
- uword tags = raw->tags_;
-#if defined(HASH_IN_OBJECT_HEADER)
- // Clear hash to make the narrowing cast safe / appease UBSAN.
- tags = UntaggedObject::HashTag::update(0, tags);
-#endif
- return tags;
-}
-
-uword SnapshotWriter::GetObjectTagsAndHash(ObjectPtr raw) {
- return raw->untag()->tags_;
-}
-
-#define VM_OBJECT_CLASS_LIST(V) \
- V(OneByteString) \
- V(TwoByteString) \
- V(Mint) \
- V(Double) \
- V(ImmutableArray)
-
-#define VM_OBJECT_WRITE(clazz) \
- case clazz::kClassId: { \
- object_id = forward_list_->AddObject(zone(), rawobj, kIsSerialized); \
- clazz##Ptr raw_obj = static_cast<clazz##Ptr>(rawobj); \
- raw_obj->untag()->WriteTo(this, object_id, kind(), false); \
- return true; \
- }
-
-#define WRITE_VM_SINGLETON_OBJ(obj, id) \
- if (rawobj == obj) { \
- WriteVMIsolateObject(id); \
- return true; \
- }
-
-bool SnapshotWriter::HandleVMIsolateObject(ObjectPtr rawobj) {
- // Check if it is one of the singleton VM objects.
- WRITE_VM_SINGLETON_OBJ(Object::null(), kNullObject);
- WRITE_VM_SINGLETON_OBJ(Object::sentinel().ptr(), kSentinelObject);
- WRITE_VM_SINGLETON_OBJ(Object::transition_sentinel().ptr(),
- kTransitionSentinelObject);
- WRITE_VM_SINGLETON_OBJ(Object::empty_array().ptr(), kEmptyArrayObject);
- WRITE_VM_SINGLETON_OBJ(Object::zero_array().ptr(), kZeroArrayObject);
- WRITE_VM_SINGLETON_OBJ(Object::dynamic_type().ptr(), kDynamicType);
- WRITE_VM_SINGLETON_OBJ(Object::void_type().ptr(), kVoidType);
- WRITE_VM_SINGLETON_OBJ(Object::empty_type_arguments().ptr(),
- kEmptyTypeArguments);
- WRITE_VM_SINGLETON_OBJ(Bool::True().ptr(), kTrueValue);
- WRITE_VM_SINGLETON_OBJ(Bool::False().ptr(), kFalseValue);
- WRITE_VM_SINGLETON_OBJ(Object::extractor_parameter_types().ptr(),
- kExtractorParameterTypes);
- WRITE_VM_SINGLETON_OBJ(Object::extractor_parameter_names().ptr(),
- kExtractorParameterNames);
- WRITE_VM_SINGLETON_OBJ(Object::empty_context_scope().ptr(),
- kEmptyContextScopeObject);
- WRITE_VM_SINGLETON_OBJ(Object::empty_object_pool().ptr(), kEmptyObjectPool);
- WRITE_VM_SINGLETON_OBJ(Object::empty_descriptors().ptr(), kEmptyDescriptors);
- WRITE_VM_SINGLETON_OBJ(Object::empty_var_descriptors().ptr(),
- kEmptyVarDescriptors);
- WRITE_VM_SINGLETON_OBJ(Object::empty_exception_handlers().ptr(),
- kEmptyExceptionHandlers);
-
- // Check if it is a singleton class object which is shared by
- // all isolates.
- intptr_t id = rawobj->GetClassId();
- if (id == kClassCid) {
- ClassPtr raw_class = static_cast<ClassPtr>(rawobj);
- intptr_t class_id = raw_class->untag()->id_;
- if (IsSingletonClassId(class_id)) {
- intptr_t object_id = ObjectIdFromClassId(class_id);
- WriteVMIsolateObject(object_id);
- return true;
- }
- }
-
- // Check if it is a singleton Argument descriptor object.
- for (intptr_t i = 0; i < ArgumentsDescriptor::kCachedDescriptorCount; i++) {
- if (rawobj == ArgumentsDescriptor::cached_args_descriptors_[i]) {
- WriteVMIsolateObject(kCachedArgumentsDescriptor0 + i);
- return true;
- }
- }
-
- // Check if it is a singleton ICData array object.
- for (intptr_t i = 0; i < ICData::kCachedICDataArrayCount; i++) {
- if (rawobj == ICData::cached_icdata_arrays_[i]) {
- WriteVMIsolateObject(kCachedICDataArray0 + i);
- return true;
- }
- }
-
- // In the case of script snapshots or for messages we do not use
- // the index into the vm isolate snapshot object table, instead we
- // explicitly write the object out.
- intptr_t object_id = forward_list_->FindObject(rawobj);
- if (object_id != -1) {
- WriteIndexedObject(object_id);
- return true;
- } else {
- // We do this check down here, because it's quite expensive.
- if (!rawobj->untag()->InVMIsolateHeap()) {
- return false;
- }
-
- switch (id) {
- VM_OBJECT_CLASS_LIST(VM_OBJECT_WRITE)
- case kTypedDataUint32ArrayCid: {
- object_id = forward_list_->AddObject(zone(), rawobj, kIsSerialized);
- TypedDataPtr raw_obj = static_cast<TypedDataPtr>(rawobj);
- raw_obj->untag()->WriteTo(this, object_id, kind(), false);
- return true;
- }
- default:
- OS::PrintErr("class id = %" Pd "\n", id);
- break;
- }
- }
-
- const Object& obj = Object::Handle(rawobj);
- FATAL1("Unexpected reference to object in VM isolate: %s\n", obj.ToCString());
- return false;
-}
-
-#undef VM_OBJECT_WRITE
-
-ForwardList::ForwardList(Thread* thread, intptr_t first_object_id)
- : thread_(thread),
- first_object_id_(first_object_id),
- nodes_(),
- first_unprocessed_object_id_(first_object_id) {
- ASSERT(first_object_id > 0);
- isolate()->set_forward_table_new(new WeakTable());
- isolate()->set_forward_table_old(new WeakTable());
-}
-
-ForwardList::~ForwardList() {
- isolate()->set_forward_table_new(nullptr);
- isolate()->set_forward_table_old(nullptr);
-}
-
-intptr_t ForwardList::AddObject(Zone* zone,
- ObjectPtr raw,
- SerializeState state) {
- NoSafepointScope no_safepoint;
- intptr_t object_id = next_object_id();
- ASSERT(object_id > 0 && object_id <= kMaxObjectId);
- const Object& obj = Object::ZoneHandle(zone, raw);
- Node* node = new Node(&obj, state);
- ASSERT(node != NULL);
- nodes_.Add(node);
- ASSERT(object_id != 0);
- SetObjectId(raw, object_id);
- return object_id;
-}
-
-intptr_t ForwardList::FindObject(ObjectPtr raw) {
- NoSafepointScope no_safepoint;
- intptr_t id = GetObjectId(raw);
- ASSERT(id == 0 || NodeForObjectId(id)->obj()->ptr() == raw);
- return (id == 0) ? static_cast<intptr_t>(kInvalidIndex) : id;
-}
-
-void ForwardList::SetObjectId(ObjectPtr object, intptr_t id) {
- if (object->IsNewObject()) {
- isolate()->forward_table_new()->SetValueExclusive(object, id);
- } else {
- isolate()->forward_table_old()->SetValueExclusive(object, id);
- }
-}
-
-intptr_t ForwardList::GetObjectId(ObjectPtr object) {
- if (object->IsNewObject()) {
- return isolate()->forward_table_new()->GetValueExclusive(object);
- } else {
- return isolate()->forward_table_old()->GetValueExclusive(object);
- }
-}
-
-bool SnapshotWriter::CheckAndWritePredefinedObject(ObjectPtr rawobj) {
- // Check if object can be written in one of the following ways:
- // - Smi: the Smi value is written as is (last bit is not tagged).
- // - VM internal class (from VM isolate): (index of class in vm isolate | 0x3)
- // - Object that has already been written: (negative id in stream | 0x3)
-
- NoSafepointScope no_safepoint;
-
- // First check if it is a Smi (i.e not a heap object).
- if (!rawobj->IsHeapObject()) {
-#if !defined(DART_COMPRESSED_POINTERS)
- Write<int64_t>(static_cast<intptr_t>(rawobj));
-#else
- // One might expect this to be unnecessary because the reader will just
- // ignore the upper bits, but the upper bits affect the variable-length
- // encoding and can change lower bits in the variable-length reader.
- Write<int64_t>(static_cast<intptr_t>(rawobj) << 32 >> 32);
-#endif
- return true;
- }
-
- intptr_t cid = rawobj->GetClassId();
-
- if ((kind_ == Snapshot::kMessage) && (cid == kDoubleCid)) {
- WriteVMIsolateObject(kDoubleObject);
- DoublePtr rd = static_cast<DoublePtr>(rawobj);
- WriteDouble(rd->untag()->value_);
- return true;
- }
-
- // Check if object has already been serialized, in that case just write
- // the object id out.
- intptr_t object_id = forward_list_->FindObject(rawobj);
- if (object_id != kInvalidIndex) {
- WriteIndexedObject(object_id);
- return true;
- }
-
- // Check if it is a code object in that case just write a Null object
- // as we do not want code objects in the snapshot.
- if (cid == kCodeCid) {
- WriteVMIsolateObject(kNullObject);
- return true;
- }
-
- // Now check if it is an object from the VM isolate. These objects are shared
- // by all isolates.
- if (HandleVMIsolateObject(rawobj)) {
- return true;
- }
-
- // Check if classes are not being serialized and it is preinitialized type
- // or a predefined internal VM class in the object store.
- // Check if it is an internal VM class which is in the object store.
- if (cid == kClassCid) {
- ClassPtr raw_class = static_cast<ClassPtr>(rawobj);
- intptr_t class_id = raw_class->untag()->id_;
- if (IsBootstrapedClassId(class_id)) {
- intptr_t object_id = ObjectIdFromClassId(class_id);
- WriteIndexedObject(object_id);
- return true;
- }
- }
-
- // Now check it is a preinitialized type object.
- intptr_t index = GetTypeIndex(object_store(), rawobj);
- if (index != kInvalidIndex) {
- WriteIndexedObject(index);
- return true;
- }
-
- return false;
-}
-
-void SnapshotWriter::WriteObjectImpl(ObjectPtr raw, bool as_reference) {
- // First check if object can be written as a simple predefined type.
- if (CheckAndWritePredefinedObject(raw)) {
- return;
- }
-
- // When we know that we are dealing with leaf or shallow objects we write
- // these objects inline even when 'as_reference' is true.
- const bool write_as_reference = as_reference && !raw->untag()->IsCanonical();
- uintptr_t tags = GetObjectTagsAndHash(raw);
-
- // Add object to the forward ref list and mark it so that future references
- // to this object in the snapshot will use this object id. Mark the
- // serialization state so that we do the right thing when we go through
- // the forward list.
- intptr_t class_id = raw->GetClassId();
- intptr_t object_id;
- if (write_as_reference && IsSplitClassId(class_id)) {
- object_id = forward_list_->AddObject(zone(), raw, kIsNotSerialized);
- } else {
- object_id = forward_list_->AddObject(zone(), raw, kIsSerialized);
- }
- if (write_as_reference || !IsSplitClassId(class_id)) {
- object_id = kOmittedObjectId;
- }
- WriteMarkedObjectImpl(raw, tags, object_id, write_as_reference);
-}
-
-void SnapshotWriter::WriteMarkedObjectImpl(ObjectPtr raw,
- intptr_t tags,
- intptr_t object_id,
- bool as_reference) {
- NoSafepointScope no_safepoint;
- ClassPtr cls = class_table_->At(UntaggedObject::ClassIdTag::decode(tags));
- intptr_t class_id = cls->untag()->id_;
- ASSERT(class_id == UntaggedObject::ClassIdTag::decode(tags));
- if (class_id >= kNumPredefinedCids || IsImplicitFieldClassId(class_id)) {
- WriteInstance(raw, cls, tags, object_id, as_reference);
- return;
- }
- switch (class_id) {
-#define SNAPSHOT_WRITE(clazz) \
- case clazz::kClassId: { \
- clazz##Ptr raw_obj = static_cast<clazz##Ptr>(raw); \
- raw_obj->untag()->WriteTo(this, object_id, kind_, as_reference); \
- return; \
- }
-
- CLASS_LIST_NO_OBJECT(SNAPSHOT_WRITE)
-#undef SNAPSHOT_WRITE
-#define SNAPSHOT_WRITE(clazz) case kTypedData##clazz##Cid:
-
- CLASS_LIST_TYPED_DATA(SNAPSHOT_WRITE) {
- TypedDataPtr raw_obj = static_cast<TypedDataPtr>(raw);
- raw_obj->untag()->WriteTo(this, object_id, kind_, as_reference);
- return;
- }
-#undef SNAPSHOT_WRITE
-#define SNAPSHOT_WRITE(clazz) case kExternalTypedData##clazz##Cid:
-
- CLASS_LIST_TYPED_DATA(SNAPSHOT_WRITE) {
- ExternalTypedDataPtr raw_obj = static_cast<ExternalTypedDataPtr>(raw);
- raw_obj->untag()->WriteTo(this, object_id, kind_, as_reference);
- return;
- }
-#undef SNAPSHOT_WRITE
-#define SNAPSHOT_WRITE(clazz) case kTypedData##clazz##ViewCid:
-
- case kByteDataViewCid:
- CLASS_LIST_TYPED_DATA(SNAPSHOT_WRITE) {
- auto raw_obj = static_cast<TypedDataViewPtr>(raw);
- raw_obj->untag()->WriteTo(this, object_id, kind_, as_reference);
- return;
- }
-#undef SNAPSHOT_WRITE
-
-#define SNAPSHOT_WRITE(clazz) case kFfi##clazz##Cid:
-
- CLASS_LIST_FFI(SNAPSHOT_WRITE) {
- SetWriteException(Exceptions::kArgument,
- "Native objects (from dart:ffi) such as Pointers and "
- "Structs cannot be passed between isolates.");
- UNREACHABLE();
- }
-#undef SNAPSHOT_WRITE
- default:
- break;
- }
-
- const Object& obj = Object::Handle(raw);
- FATAL1("Unexpected object: %s\n", obj.ToCString());
-}
-
-class WriteInlinedObjectVisitor : public ObjectVisitor {
- public:
- explicit WriteInlinedObjectVisitor(SnapshotWriter* writer)
- : writer_(writer) {}
-
- virtual void VisitObject(ObjectPtr obj) {
- intptr_t object_id = writer_->forward_list_->FindObject(obj);
- ASSERT(object_id != kInvalidIndex);
- intptr_t tags = MessageWriter::GetObjectTagsAndHash(ObjectPtr(obj));
- writer_->WriteMarkedObjectImpl(obj, tags, object_id, kAsInlinedObject);
- }
-
- private:
- SnapshotWriter* writer_;
-};
-
-void SnapshotWriter::WriteForwardedObjects() {
- WriteInlinedObjectVisitor visitor(this);
- forward_list_->SerializeAll(&visitor);
-}
-
-void ForwardList::SerializeAll(ObjectVisitor* writer) {
-// Write out all objects that were added to the forward list and have
-// not been serialized yet. These would typically be fields of instance
-// objects, arrays or immutable arrays (this is done in order to avoid
-// deep recursive calls to WriteObjectImpl).
-// NOTE: The forward list might grow as we process the list.
-#ifdef DEBUG
- for (intptr_t i = first_object_id(); i < first_unprocessed_object_id_; ++i) {
- ASSERT(NodeForObjectId(i)->is_serialized());
- }
-#endif // DEBUG
- for (intptr_t id = first_unprocessed_object_id_; id < next_object_id();
- ++id) {
- if (!NodeForObjectId(id)->is_serialized()) {
- // Write the object out in the stream.
- ObjectPtr raw = NodeForObjectId(id)->obj()->ptr();
- writer->VisitObject(raw);
-
- // Mark object as serialized.
- NodeForObjectId(id)->set_state(kIsSerialized);
- }
- }
- first_unprocessed_object_id_ = next_object_id();
-}
-
-void SnapshotWriter::WriteClassId(UntaggedClass* cls) {
- ASSERT(!Snapshot::IsFull(kind_));
- int class_id = cls->id_;
- ASSERT(!IsSingletonClassId(class_id) && !IsBootstrapedClassId(class_id));
-
- // Write out the library url and class name.
- LibraryPtr library = cls->library();
- ASSERT(library != Library::null());
- WriteObjectImpl(library->untag()->url(), kAsInlinedObject);
- WriteObjectImpl(cls->name(), kAsInlinedObject);
-}
-
-void SnapshotWriter::WriteStaticImplicitClosure(
- intptr_t object_id,
- FunctionPtr func,
- intptr_t tags,
- TypeArgumentsPtr delayed_type_arguments) {
- // Write out the serialization header value for this object.
- WriteInlinedObjectHeader(object_id);
-
- // Indicate this is a static implicit closure object.
- Write<int32_t>(SerializedHeaderData::encode(kStaticImplicitClosureObjectId));
-
- // Write out the tags.
- WriteTags(tags);
-
- // Write out the library url, class name and signature function name.
- ClassPtr cls = GetFunctionOwner(func);
- ASSERT(cls != Class::null());
- LibraryPtr library = cls->untag()->library();
- ASSERT(library != Library::null());
- WriteObjectImpl(library->untag()->url(), kAsInlinedObject);
- WriteObjectImpl(cls->untag()->name(), kAsInlinedObject);
- WriteObjectImpl(func->untag()->name(), kAsInlinedObject);
- WriteObjectImpl(delayed_type_arguments, kAsInlinedObject);
-}
-
-void SnapshotWriter::ArrayWriteTo(intptr_t object_id,
- intptr_t array_kind,
- intptr_t tags,
- SmiPtr length,
- TypeArgumentsPtr type_arguments,
- CompressedObjectPtr data[],
- bool as_reference) {
- if (as_reference) {
- // Write out the serialization header value for this object.
- WriteInlinedObjectHeader(kOmittedObjectId);
-
- // Write out the class information.
- WriteIndexedObject(array_kind);
- WriteTags(tags);
-
- // Write out the length field.
- Write<ObjectPtr>(length);
- } else {
- intptr_t len = Smi::Value(length);
-
- // Write out the serialization header value for this object.
- WriteInlinedObjectHeader(object_id);
-
- // Write out the class and tags information.
- WriteIndexedObject(array_kind);
- WriteTags(tags);
-
- // Write out the length field.
- Write<ObjectPtr>(length);
-
- // Write out the type arguments.
- WriteObjectImpl(type_arguments, kAsInlinedObject);
-
- // Write out the individual object ids.
- bool write_as_reference = UntaggedObject::IsCanonical(tags) ? false : true;
- uword heap_base = type_arguments.heap_base();
- for (intptr_t i = 0; i < len; i++) {
- WriteObjectImpl(data[i].Decompress(heap_base), write_as_reference);
- }
- }
-}
-
-FunctionPtr SnapshotWriter::IsSerializableClosure(ClosurePtr closure) {
- // Extract the function object to check if this closure
- // can be sent in an isolate message.
- FunctionPtr func = closure->untag()->function();
- // We only allow closure of top level methods or static functions in a
- // class to be sent in isolate messages.
- if (can_send_any_object() &&
- Function::IsImplicitStaticClosureFunction(func)) {
- return func;
- }
- // Not a closure of a top level method or static function, throw an
- // exception as we do not allow these objects to be serialized.
- HANDLESCOPE(thread());
-
- const Function& errorFunc = Function::Handle(zone(), func);
- ASSERT(!errorFunc.IsNull());
-
- // All other closures are errors.
- char* chars = OS::SCreate(
- thread()->zone(),
- "Illegal argument in isolate message : (object is a closure - %s)",
- errorFunc.ToCString());
- SetWriteException(Exceptions::kArgument, chars);
- return Function::null();
-}
-
-ClassPtr SnapshotWriter::GetFunctionOwner(FunctionPtr func) {
- ObjectPtr owner = func->untag()->owner();
- uword tags = GetObjectTags(owner);
- intptr_t class_id = UntaggedObject::ClassIdTag::decode(tags);
- if (class_id == kClassCid) {
- return static_cast<ClassPtr>(owner);
- }
- ASSERT(class_id == kPatchClassCid);
- return static_cast<PatchClassPtr>(owner)->untag()->patched_class();
-}
-
-void SnapshotWriter::CheckForNativeFields(ClassPtr cls) {
- if (cls->untag()->num_native_fields_ != 0) {
- // We do not allow objects with native fields in an isolate message.
- HANDLESCOPE(thread());
- const Class& clazz = Class::Handle(zone(), cls);
- char* chars = OS::SCreate(thread()->zone(),
- "Illegal argument in isolate message"
- " : (object extends NativeWrapper - %s)",
- clazz.ToCString());
- SetWriteException(Exceptions::kArgument, chars);
- }
-}
-
-void SnapshotWriter::SetWriteException(Exceptions::ExceptionType type,
- const char* msg) {
- set_exception_type(type);
- set_exception_msg(msg);
- // The more specific error is set up in SnapshotWriter::ThrowException().
- thread()->long_jump_base()->Jump(1, Object::snapshot_writer_error());
-}
-
-void SnapshotWriter::WriteInstance(ObjectPtr raw,
- ClassPtr cls,
- intptr_t tags,
- intptr_t object_id,
- bool as_reference) {
- // Closure instances are handled by UntaggedClosure::WriteTo().
- ASSERT(!Class::IsClosureClass(cls));
-
- // Check if the instance has native fields and throw an exception if it does.
- CheckForNativeFields(cls);
-
- // Object is regular dart instance.
- if (as_reference) {
- // Write out the serialization header value for this object.
- WriteInlinedObjectHeader(kOmittedObjectId);
-
- // Indicate this is an instance object.
- Write<int32_t>(SerializedHeaderData::encode(kInstanceObjectId));
- WriteTags(tags);
-
- // Write out the class information for this object.
- WriteObjectImpl(cls, kAsInlinedObject);
- } else {
- intptr_t next_field_offset = Class::host_next_field_offset_in_words(cls)
- << kCompressedWordSizeLog2;
- ASSERT(next_field_offset > 0);
-
- // Write out the serialization header value for this object.
- WriteInlinedObjectHeader(object_id);
-
- // Indicate this is an instance object.
- Write<int32_t>(SerializedHeaderData::encode(kInstanceObjectId));
-
- // Write out the tags.
- WriteTags(tags);
-
- // Write out the class information for this object.
- WriteObjectImpl(cls, kAsInlinedObject);
-
- const auto unboxed_fields =
- isolate_group()->shared_class_table()->GetUnboxedFieldsMapAt(
- cls->untag()->id_);
-
- // Write out all the fields for the object.
- // Instance::NextFieldOffset() returns the offset of the first field in
- // a Dart object.
- bool write_as_reference = UntaggedObject::IsCanonical(tags) ? false : true;
-
- intptr_t offset = Instance::NextFieldOffset();
- uword heap_base = raw->heap_base();
- while (offset < next_field_offset) {
- if (unboxed_fields.Get(offset / kCompressedWordSize)) {
- // Writes 32 bits of the unboxed value at a time
- const uword value = *reinterpret_cast<compressed_uword*>(
- reinterpret_cast<uword>(raw->untag()) + offset);
- WriteWordWith32BitWrites(value);
- } else {
- ObjectPtr raw_obj = reinterpret_cast<CompressedObjectPtr*>(
- reinterpret_cast<uword>(raw->untag()) + offset)
- ->Decompress(heap_base);
- WriteObjectImpl(raw_obj, write_as_reference);
- }
- offset += kCompressedWordSize;
- }
- }
- return;
-}
-
-bool SnapshotWriter::AllowObjectsInDartLibrary(LibraryPtr library) {
- return (library == object_store()->collection_library() ||
- library == object_store()->core_library() ||
- library == object_store()->typed_data_library());
-}
-
-intptr_t SnapshotWriter::FindVmSnapshotObject(ObjectPtr rawobj) {
- intptr_t length = Object::vm_isolate_snapshot_object_table().Length();
- for (intptr_t i = 0; i < length; i++) {
- if (Object::vm_isolate_snapshot_object_table().At(i) == rawobj) {
- return (i + kMaxPredefinedObjectIds);
- }
- }
- return kInvalidIndex;
-}
-
-void SnapshotWriter::ThrowException(Exceptions::ExceptionType type,
- const char* msg) {
- {
- NoSafepointScope no_safepoint;
- ErrorPtr error = thread()->StealStickyError();
- ASSERT(error == Object::snapshot_writer_error().ptr());
- }
-
- if (msg != NULL) {
- const String& msg_obj = String::Handle(String::New(msg));
- const Array& args = Array::Handle(Array::New(1));
- args.SetAt(0, msg_obj);
- Exceptions::ThrowByType(type, args);
- } else {
- Exceptions::ThrowByType(type, Object::empty_array());
- }
- UNREACHABLE();
-}
-
-void SnapshotWriter::WriteVersionAndFeatures() {
- const char* expected_version = Version::SnapshotString();
- ASSERT(expected_version != NULL);
- const intptr_t version_len = strlen(expected_version);
- WriteBytes(reinterpret_cast<const uint8_t*>(expected_version), version_len);
-
- const char* expected_features =
- Dart::FeaturesString(IsolateGroup::Current(), false, kind_);
- ASSERT(expected_features != NULL);
- const intptr_t features_len = strlen(expected_features);
- WriteBytes(reinterpret_cast<const uint8_t*>(expected_features),
- features_len + 1);
- free(const_cast<char*>(expected_features));
-}
-
-void SnapshotWriterVisitor::VisitPointers(ObjectPtr* first, ObjectPtr* last) {
- ASSERT(Utils::IsAligned(first, sizeof(*first)));
- ASSERT(Utils::IsAligned(last, sizeof(*last)));
- for (ObjectPtr* current = first; current <= last; current++) {
- ObjectPtr raw_obj = *current;
- writer_->WriteObjectImpl(raw_obj, as_references_);
- }
-}
-
-void SnapshotWriterVisitor::VisitCompressedPointers(uword heap_base,
- CompressedObjectPtr* first,
- CompressedObjectPtr* last) {
- ASSERT(Utils::IsAligned(first, sizeof(*first)));
- ASSERT(Utils::IsAligned(last, sizeof(*last)));
- for (CompressedObjectPtr* current = first; current <= last; current++) {
- ObjectPtr raw_obj = current->Decompress(heap_base);
- writer_->WriteObjectImpl(raw_obj, as_references_);
- }
-}
-
-MessageWriter::MessageWriter(bool can_send_any_object)
- : SnapshotWriter(Thread::Current(),
- Snapshot::kMessage,
- kInitialSize,
- &forward_list_,
- can_send_any_object),
- forward_list_(thread(), kMaxPredefinedObjectIds),
- finalizable_data_(new MessageFinalizableData()) {}
-
-MessageWriter::~MessageWriter() {
- delete finalizable_data_;
-}
-
-std::unique_ptr<Message> MessageWriter::WriteMessage(
- const Object& obj,
- Dart_Port dest_port,
- Message::Priority priority) {
- ASSERT(kind() == Snapshot::kMessage);
- ASSERT(isolate() != NULL);
-
- // Setup for long jump in case there is an exception while writing
- // the message.
- volatile bool has_exception = false;
- {
- LongJumpScope jump;
- if (setjmp(*jump.Set()) == 0) {
- NoSafepointScope no_safepoint;
- WriteObject(obj.ptr());
- } else {
- FreeBuffer();
- has_exception = true;
- }
- }
- if (has_exception) {
- ThrowException(exception_type(), exception_msg());
- } else {
- finalizable_data_->SerializationSucceeded();
- }
-
- MessageFinalizableData* finalizable_data = finalizable_data_;
- finalizable_data_ = nullptr;
- intptr_t size;
- uint8_t* buffer = Steal(&size);
- return Message::New(dest_port, buffer, size, finalizable_data, priority);
-}
} // namespace dart
diff --git a/runtime/vm/snapshot.h b/runtime/vm/snapshot.h
index 60da2b3..63d61a8 100644
--- a/runtime/vm/snapshot.h
+++ b/runtime/vm/snapshot.h
@@ -9,83 +9,14 @@
#include <utility>
#include "platform/assert.h"
+#include "platform/unaligned.h"
#include "vm/allocation.h"
-#include "vm/bitfield.h"
-#include "vm/datastream.h"
-#include "vm/finalizable_data.h"
#include "vm/globals.h"
-#include "vm/growable_array.h"
-#include "vm/isolate.h"
#include "vm/message.h"
-#include "vm/visitor.h"
+#include "vm/thread.h"
namespace dart {
-// Forward declarations.
-class AbstractType;
-class Array;
-class Class;
-class ClassTable;
-class Closure;
-class Code;
-class ExternalTypedData;
-class TypedDataBase;
-class GrowableObjectArray;
-class Heap;
-class Instance;
-class Instructions;
-class LanguageError;
-class Library;
-class LinkedHashMap;
-class Object;
-class PassiveObject;
-class ObjectStore;
-class MegamorphicCache;
-class PageSpace;
-class TypedDataView;
-class String;
-class TypeArguments;
-class TypedData;
-class UnhandledException;
-
-// Serialized object header encoding is as follows:
-// - Smi: the Smi value is written as is (last bit is not tagged).
-// - VM object (from VM isolate): (object id in vm isolate | 0x3)
-// This value is serialized as a negative number.
-// (note VM objects are never serialized, they are expected to be found
-// using ths unique ID assigned to them).
-// - Reference to object that has already been written: (object id | 0x3)
-// This valus is serialized as a positive number.
-// - Object that is seen for the first time (inlined in the stream):
-// (a unique id for this object | 0x1)
-enum SerializedHeaderType {
- kInlined = 0x1,
- kObjectId = 0x3,
-};
-static const int8_t kHeaderTagBits = 2;
-static const int8_t kObjectIdBits = (kBitsPerInt32 - (kHeaderTagBits + 1));
-static const intptr_t kMaxObjectId = (kMaxUint32 >> (kHeaderTagBits + 1));
-static const bool kAsReference = true;
-static const bool kAsInlinedObject = false;
-static const intptr_t kInvalidPatchIndex = -1;
-
-class SerializedHeaderTag
- : public BitField<intptr_t, enum SerializedHeaderType, 0, kHeaderTagBits> {
-};
-
-class SerializedHeaderData
- : public BitField<intptr_t, intptr_t, kHeaderTagBits, kObjectIdBits> {};
-
-enum DeserializeState {
- kIsDeserialized = 0,
- kIsNotDeserialized = 1,
-};
-
-enum SerializeState {
- kIsSerialized = 0,
- kIsNotSerialized = 1,
-};
-
// Structure capturing the raw snapshot.
//
class Snapshot {
@@ -95,7 +26,6 @@
kFullCore, // Full snapshot of core libraries. Agnostic to null safety.
kFullJIT, // Full + JIT code
kFullAOT, // Full + AOT code
- kMessage, // A partial snapshot used only for isolate messaging.
kNone, // gen_snapshot
kInvalid
};
@@ -185,529 +115,6 @@
return Snapshot::IsFull(isolate_kind);
}
-class BaseReader {
- public:
- BaseReader(const uint8_t* buffer, intptr_t size) : stream_(buffer, size) {}
- // Reads raw data (for basic types).
- // sizeof(T) must be in {1,2,4,8}.
- template <typename T>
- T Read() {
- return ReadStream::Raw<sizeof(T), T>::Read(&stream_);
- }
-
- classid_t ReadClassIDValue() {
- uint32_t value = Read<uint32_t>();
- return static_cast<classid_t>(value);
- }
- COMPILE_ASSERT(sizeof(uint32_t) >= sizeof(classid_t));
-
- void ReadBytes(uint8_t* addr, intptr_t len) { stream_.ReadBytes(addr, len); }
-
- double ReadDouble() {
- double result;
- stream_.ReadBytes(reinterpret_cast<uint8_t*>(&result), sizeof(result));
- return result;
- }
-
- intptr_t ReadTags() {
- const intptr_t tags = static_cast<intptr_t>(Read<int8_t>()) & 0xff;
- return tags;
- }
-
- const uint8_t* CurrentBufferAddress() const {
- return stream_.AddressOfCurrentPosition();
- }
-
- void Align(intptr_t value) { stream_.Align(value); }
- void Advance(intptr_t value) { stream_.Advance(value); }
-
- intptr_t PendingBytes() const { return stream_.PendingBytes(); }
-
- SmiPtr ReadAsSmi();
- intptr_t ReadSmiValue();
-
- // Negative header value indicates VM isolate object id.
- bool IsVMIsolateObject(intptr_t header_value) { return (header_value < 0); }
- intptr_t GetVMIsolateObjectId(intptr_t header_val) {
- ASSERT(IsVMIsolateObject(header_val));
- intptr_t value = -header_val; // Header is negative for VM isolate objects.
- ASSERT(SerializedHeaderTag::decode(value) == kObjectId);
- return SerializedHeaderData::decode(value);
- }
-
- uword ReadWordWith32BitReads() { return stream_.ReadWordWith32BitReads(); }
-
- private:
- ReadStream stream_; // input stream.
-};
-
-class BackRefNode : public ValueObject {
- public:
- BackRefNode(Object* reference, DeserializeState state)
- : reference_(reference), state_(state) {}
- Object* reference() const { return reference_; }
- bool is_deserialized() const { return state_ == kIsDeserialized; }
- void set_state(DeserializeState state) { state_ = state; }
-
- BackRefNode& operator=(const BackRefNode& other) {
- reference_ = other.reference_;
- state_ = other.state_;
- return *this;
- }
-
- private:
- Object* reference_;
- DeserializeState state_;
-};
-
-// Reads a snapshot into objects.
-class SnapshotReader : public BaseReader {
- public:
- Thread* thread() const { return thread_; }
- Zone* zone() const { return zone_; }
- Isolate* isolate() const { return thread_->isolate(); }
- IsolateGroup* isolate_group() const { return thread_->isolate_group(); }
- Heap* heap() const { return heap_; }
- ObjectStore* object_store() const { return isolate_group()->object_store(); }
- ClassTable* class_table() const { return isolate_group()->class_table(); }
- PassiveObject* PassiveObjectHandle() { return &pobj_; }
- Array* ArrayHandle() { return &array_; }
- Class* ClassHandle() { return &cls_; }
- Code* CodeHandle() { return &code_; }
- Instance* InstanceHandle() { return &instance_; }
- Instructions* InstructionsHandle() { return &instructions_; }
- String* StringHandle() { return &str_; }
- AbstractType* TypeHandle() { return &type_; }
- TypeArguments* TypeArgumentsHandle() { return &type_arguments_; }
- GrowableObjectArray* TokensHandle() { return &tokens_; }
- ExternalTypedData* DataHandle() { return &data_; }
- TypedDataBase* TypedDataBaseHandle() { return &typed_data_base_; }
- TypedData* TypedDataHandle() { return &typed_data_; }
- TypedDataView* TypedDataViewHandle() { return &typed_data_view_; }
- Function* FunctionHandle() { return &function_; }
- Smi* SmiHandle() { return &smi_; }
- Snapshot::Kind kind() const { return kind_; }
-
- // Reads an object.
- ObjectPtr ReadObject();
-
- // Add object to backward references.
- void AddBackRef(intptr_t id, Object* obj, DeserializeState state);
-
- // Get an object from the backward references list.
- Object* GetBackRef(intptr_t id);
-
- // Read version number of snapshot and verify.
- ApiErrorPtr VerifyVersionAndFeatures(IsolateGroup* isolate_group);
-
- ObjectPtr NewInteger(int64_t value);
-
- protected:
- SnapshotReader(const uint8_t* buffer,
- intptr_t size,
- Snapshot::Kind kind,
- ZoneGrowableArray<BackRefNode>* backward_references,
- Thread* thread);
- ~SnapshotReader() {}
-
- ZoneGrowableArray<BackRefNode>* GetBackwardReferenceTable() const {
- return backward_references_;
- }
- void ResetBackwardReferenceTable() { backward_references_ = NULL; }
- PageSpace* old_space() const { return old_space_; }
-
- private:
- void EnqueueTypePostprocessing(const AbstractType& type);
- void RunDelayedTypePostprocessing();
-
- void EnqueueRehashingOfMap(const LinkedHashMap& map);
- void EnqueueRehashingOfSet(const Object& set);
- ObjectPtr RunDelayedRehashingOfMaps();
-
- ClassPtr ReadClassId(intptr_t object_id);
- ObjectPtr ReadStaticImplicitClosure(intptr_t object_id, intptr_t cls_header);
-
- // Implementation to read an object.
- ObjectPtr ReadObjectImpl(bool as_reference);
- ObjectPtr ReadObjectImpl(intptr_t header, bool as_reference);
-
- // Read a Dart Instance object.
- ObjectPtr ReadInstance(intptr_t object_id, intptr_t tags, bool as_reference);
-
- // Read a VM isolate object that was serialized as an Id.
- ObjectPtr ReadVMIsolateObject(intptr_t object_id);
-
- // Read an object that was serialized as an Id (singleton in object store,
- // or an object that was already serialized before).
- ObjectPtr ReadIndexedObject(intptr_t object_id);
-
- // Decode class id from the header field.
- intptr_t LookupInternalClass(intptr_t class_header);
-
- void ArrayReadFrom(intptr_t object_id,
- const Array& result,
- intptr_t len,
- intptr_t tags);
-
- intptr_t NextAvailableObjectId() const;
-
- void SetReadException(const char* msg);
-
- ObjectPtr VmIsolateSnapshotObject(intptr_t index) const;
-
- bool is_vm_isolate() const;
-
- Snapshot::Kind kind_; // Indicates type of the snapshot.
- Thread* thread_; // Current thread.
- Zone* zone_; // Zone for allocations while reading.
- Heap* heap_; // Heap of the current isolate.
- PageSpace* old_space_; // Old space of the current isolate.
- Class& cls_; // Temporary Class handle.
- Code& code_; // Temporary Code handle.
- Instance& instance_; // Temporary Instance handle
- Instructions& instructions_; // Temporary Instructions handle
- Object& obj_; // Temporary Object handle.
- PassiveObject& pobj_; // Temporary PassiveObject handle.
- Array& array_; // Temporary Array handle.
- Field& field_; // Temporary Field handle.
- String& str_; // Temporary String handle.
- Library& library_; // Temporary library handle.
- AbstractType& type_; // Temporary type handle.
- TypeArguments& type_arguments_; // Temporary type argument handle.
- GrowableObjectArray& tokens_; // Temporary tokens handle.
- ExternalTypedData& data_; // Temporary stream data handle.
- TypedDataBase& typed_data_base_; // Temporary typed data base handle.
- TypedData& typed_data_; // Temporary typed data handle.
- TypedDataView& typed_data_view_; // Temporary typed data view handle.
- Function& function_; // Temporary function handle.
- Smi& smi_; // Temporary Smi handle.
- UnhandledException& error_; // Error handle.
- const Class& set_class_; // The LinkedHashSet class.
- intptr_t max_vm_isolate_object_id_;
- ZoneGrowableArray<BackRefNode>* backward_references_;
- GrowableObjectArray& types_to_postprocess_;
- GrowableObjectArray& objects_to_rehash_;
-
- friend class ApiError;
- friend class Array;
- friend class Class;
- friend class Closure;
- friend class ClosureData;
- friend class Context;
- friend class ContextScope;
- friend class ExceptionHandlers;
- friend class Field;
- friend class Function;
- friend class GrowableObjectArray;
- friend class ICData;
- friend class ImmutableArray;
- friend class KernelProgramInfo;
- friend class LanguageError;
- friend class Library;
- friend class LibraryPrefix;
- friend class LinkedHashMap;
- friend class MirrorReference;
- friend class Namespace;
- friend class PatchClass;
- friend class RegExp;
- friend class Script;
- friend class SubtypeTestCache;
- friend class TransferableTypedData;
- friend class Type;
- friend class FunctionType;
- friend class TypedDataView;
- friend class TypeParameters;
- friend class TypeArguments;
- friend class TypeParameter;
- friend class TypeRef;
- friend class UnhandledException;
- friend class WeakProperty;
- friend class WeakSerializationReference;
- DISALLOW_COPY_AND_ASSIGN(SnapshotReader);
-};
-
-class MessageSnapshotReader : public SnapshotReader {
- public:
- MessageSnapshotReader(Message* message, Thread* thread);
- ~MessageSnapshotReader();
-
- MessageFinalizableData* finalizable_data() const { return finalizable_data_; }
-
- private:
- MessageFinalizableData* finalizable_data_;
-
- DISALLOW_COPY_AND_ASSIGN(MessageSnapshotReader);
-};
-
-class BaseWriter : public StackResource {
- public:
- uint8_t* Steal(intptr_t* length) { return stream_.Steal(length); }
- intptr_t BytesWritten() const { return stream_.bytes_written(); }
-
- // Writes raw data to the stream (basic type).
- // sizeof(T) must be in {1,2,4,8}.
- template <typename T>
- void Write(T value) {
- MallocWriteStream::Raw<sizeof(T), T>::Write(&stream_, value);
- }
-
- void WriteClassIDValue(classid_t value) { Write<uint32_t>(value); }
- COMPILE_ASSERT(sizeof(uint32_t) >= sizeof(classid_t));
-
- // Write an object that is serialized as an Id (singleton in object store,
- // or an object that was already serialized before).
- void WriteIndexedObject(intptr_t object_id) {
- ASSERT(object_id <= kMaxObjectId);
- intptr_t value = 0;
- value = SerializedHeaderTag::update(kObjectId, value);
- value = SerializedHeaderData::update(object_id, value);
- Write<int32_t>(value);
- }
-
- // Write a VM Isolateobject that is serialized as an Id.
- void WriteVMIsolateObject(intptr_t object_id) {
- ASSERT(object_id <= kMaxObjectId);
- intptr_t value = 0;
- value = SerializedHeaderTag::update(kObjectId, value);
- value = SerializedHeaderData::update(object_id, value);
- Write<int32_t>(-value); // Write as a negative value.
- }
-
- // Write serialization header information for an object.
- void WriteInlinedObjectHeader(intptr_t id) {
- ASSERT(id <= kMaxObjectId);
- intptr_t value = 0;
- value = SerializedHeaderTag::update(kInlined, value);
- value = SerializedHeaderData::update(id, value);
- Write<int32_t>(value);
- }
-
- void WriteTags(intptr_t tags) {
- const intptr_t flags = tags & 0xff;
- Write<int8_t>(static_cast<int8_t>(flags));
- }
-
- void Align(intptr_t value) { stream_.Align(value); }
-
- // Write out a buffer of bytes.
- void WriteBytes(const uint8_t* addr, intptr_t len) {
- stream_.WriteBytes(addr, len);
- }
-
- void WriteDouble(double value) {
- stream_.WriteBytes(reinterpret_cast<const uint8_t*>(&value), sizeof(value));
- }
-
- void WriteWordWith32BitWrites(uword value) {
- stream_.WriteWordWith32BitWrites(value);
- }
-
- protected:
- explicit BaseWriter(intptr_t initial_size)
- : StackResource(Thread::Current()), stream_(initial_size) {}
- ~BaseWriter() {}
-
- void ReserveHeader() {
- // Make room for recording snapshot buffer size.
- stream_.SetPosition(Snapshot::kHeaderSize);
- }
-
- void FillHeader(Snapshot::Kind kind) {
- intptr_t length;
- Snapshot* header = reinterpret_cast<Snapshot*>(Steal(&length));
- header->set_magic();
- header->set_length(length);
- header->set_kind(kind);
- }
-
- void FreeBuffer() {
- intptr_t unused;
- free(Steal(&unused));
- }
-
- private:
- MallocWriteStream stream_;
-
- DISALLOW_IMPLICIT_CONSTRUCTORS(BaseWriter);
-};
-
-class ForwardList {
- public:
- explicit ForwardList(Thread* thread, intptr_t first_object_id);
- ~ForwardList();
-
- class Node : public ZoneAllocated {
- public:
- Node(const Object* obj, SerializeState state) : obj_(obj), state_(state) {}
- const Object* obj() const { return obj_; }
- bool is_serialized() const { return state_ == kIsSerialized; }
-
- private:
- // Private to ensure the invariant of first_unprocessed_object_id_.
- void set_state(SerializeState value) { state_ = value; }
-
- const Object* obj_;
- SerializeState state_;
-
- friend class ForwardList;
- DISALLOW_COPY_AND_ASSIGN(Node);
- };
-
- Node* NodeForObjectId(intptr_t object_id) const {
- return nodes_[object_id - first_object_id_];
- }
-
- // Returns the id for the added object.
- intptr_t AddObject(Zone* zone, ObjectPtr raw, SerializeState state);
-
- // Returns the id for the object it it exists in the list.
- intptr_t FindObject(ObjectPtr raw);
-
- // Exhaustively processes all unserialized objects in this list. 'writer' may
- // concurrently add more objects.
- void SerializeAll(ObjectVisitor* writer);
-
- // Set state of object in forward list.
- void SetState(intptr_t object_id, SerializeState state) {
- NodeForObjectId(object_id)->set_state(state);
- }
-
- private:
- intptr_t first_object_id() const { return first_object_id_; }
- intptr_t next_object_id() const { return nodes_.length() + first_object_id_; }
- Isolate* isolate() const { return thread_->isolate(); }
-
- Thread* thread_;
- const intptr_t first_object_id_;
- GrowableArray<Node*> nodes_;
- intptr_t first_unprocessed_object_id_;
-
- void SetObjectId(ObjectPtr object, intptr_t id);
- intptr_t GetObjectId(ObjectPtr object);
-
- DISALLOW_COPY_AND_ASSIGN(ForwardList);
-};
-
-class SnapshotWriter : public BaseWriter {
- protected:
- SnapshotWriter(Thread* thread,
- Snapshot::Kind kind,
- intptr_t initial_size,
- ForwardList* forward_list,
- bool can_send_any_object);
-
- public:
- // Snapshot kind.
- Snapshot::Kind kind() const { return kind_; }
- Thread* thread() const { return thread_; }
- Zone* zone() const { return thread_->zone(); }
- Isolate* isolate() const { return thread_->isolate(); }
- IsolateGroup* isolate_group() const { return thread_->isolate_group(); }
- Heap* heap() const { return isolate_group()->heap(); }
-
- // Serialize an object into the buffer.
- void WriteObject(ObjectPtr raw);
-
- static uint32_t GetObjectTags(ObjectPtr raw);
- static uint32_t GetObjectTags(UntaggedObject* raw);
- static uword GetObjectTagsAndHash(ObjectPtr raw);
-
- Exceptions::ExceptionType exception_type() const { return exception_type_; }
- void set_exception_type(Exceptions::ExceptionType type) {
- exception_type_ = type;
- }
- const char* exception_msg() const { return exception_msg_; }
- void set_exception_msg(const char* msg) { exception_msg_ = msg; }
- bool can_send_any_object() const { return can_send_any_object_; }
- void ThrowException(Exceptions::ExceptionType type, const char* msg);
-
- // Write a version string for the snapshot.
- void WriteVersionAndFeatures();
-
- FunctionPtr IsSerializableClosure(ClosurePtr closure);
-
- void WriteStaticImplicitClosure(intptr_t object_id,
- FunctionPtr func,
- intptr_t tags,
- TypeArgumentsPtr delayed_type_arguments);
-
- protected:
- bool CheckAndWritePredefinedObject(ObjectPtr raw);
- bool HandleVMIsolateObject(ObjectPtr raw);
-
- void WriteClassId(UntaggedClass* cls);
- void WriteObjectImpl(ObjectPtr raw, bool as_reference);
- void WriteMarkedObjectImpl(ObjectPtr raw,
- intptr_t tags,
- intptr_t object_id,
- bool as_reference);
- void WriteForwardedObjects();
- void ArrayWriteTo(intptr_t object_id,
- intptr_t array_kind,
- intptr_t tags,
- SmiPtr length,
- TypeArgumentsPtr type_arguments,
- CompressedObjectPtr data[],
- bool as_reference);
- ClassPtr GetFunctionOwner(FunctionPtr func);
- void CheckForNativeFields(ClassPtr cls);
- void SetWriteException(Exceptions::ExceptionType type, const char* msg);
- void WriteInstance(ObjectPtr raw,
- ClassPtr cls,
- intptr_t tags,
- intptr_t object_id,
- bool as_reference);
- bool AllowObjectsInDartLibrary(LibraryPtr library);
- intptr_t FindVmSnapshotObject(ObjectPtr rawobj);
-
- ObjectStore* object_store() const { return object_store_; }
-
- private:
- Thread* thread_;
- Snapshot::Kind kind_;
- ObjectStore* object_store_; // Object store for common classes.
- ClassTable* class_table_; // Class table for the class index to class lookup.
- ForwardList* forward_list_;
- Exceptions::ExceptionType exception_type_; // Exception type.
- const char* exception_msg_; // Message associated with exception.
- bool can_send_any_object_; // True if any Dart instance can be sent.
-
- friend class UntaggedArray;
- friend class UntaggedClass;
- friend class UntaggedCode;
- friend class UntaggedContextScope;
- friend class UntaggedDynamicLibrary;
- friend class UntaggedExceptionHandlers;
- friend class UntaggedField;
- friend class UntaggedFunction;
- friend class UntaggedFunctionType;
- friend class UntaggedGrowableObjectArray;
- friend class UntaggedImmutableArray;
- friend class UntaggedInstructions;
- friend class UntaggedLibrary;
- friend class UntaggedLinkedHashMap;
- friend class UntaggedLocalVarDescriptors;
- friend class UntaggedMirrorReference;
- friend class UntaggedObjectPool;
- friend class UntaggedPointer;
- friend class UntaggedReceivePort;
- friend class UntaggedRegExp;
- friend class UntaggedScript;
- friend class UntaggedStackTrace;
- friend class UntaggedSubtypeTestCache;
- friend class UntaggedTransferableTypedData;
- friend class UntaggedType;
- friend class UntaggedTypeArguments;
- friend class UntaggedTypeParameter;
- friend class UntaggedTypeRef;
- friend class UntaggedTypedDataView;
- friend class UntaggedUserTag;
- friend class UntaggedWeakSerializationReference;
- friend class SnapshotWriterVisitor;
- friend class WriteInlinedObjectVisitor;
- DISALLOW_COPY_AND_ASSIGN(SnapshotWriter);
-};
-
class SerializedObjectBuffer : public StackResource {
public:
SerializedObjectBuffer()
@@ -723,46 +130,6 @@
std::unique_ptr<Message> message_;
};
-class MessageWriter : public SnapshotWriter {
- public:
- static const intptr_t kInitialSize = 512;
- explicit MessageWriter(bool can_send_any_object);
- ~MessageWriter();
-
- std::unique_ptr<Message> WriteMessage(const Object& obj,
- Dart_Port dest_port,
- Message::Priority priority);
-
- MessageFinalizableData* finalizable_data() const { return finalizable_data_; }
-
- private:
- ForwardList forward_list_;
- MessageFinalizableData* finalizable_data_;
-
- DISALLOW_COPY_AND_ASSIGN(MessageWriter);
-};
-
-// An object pointer visitor implementation which writes out
-// objects to a snapshot.
-class SnapshotWriterVisitor : public ObjectPointerVisitor {
- public:
- SnapshotWriterVisitor(SnapshotWriter* writer, bool as_references)
- : ObjectPointerVisitor(Isolate::Current()->group()),
- writer_(writer),
- as_references_(as_references) {}
-
- void VisitPointers(ObjectPtr* first, ObjectPtr* last);
- void VisitCompressedPointers(uword heap_base,
- CompressedObjectPtr* first,
- CompressedObjectPtr* last);
-
- private:
- SnapshotWriter* writer_;
- bool as_references_;
-
- DISALLOW_COPY_AND_ASSIGN(SnapshotWriterVisitor);
-};
-
} // namespace dart
#endif // RUNTIME_VM_SNAPSHOT_H_
diff --git a/runtime/vm/snapshot_ids.h b/runtime/vm/snapshot_ids.h
deleted file mode 100644
index b38bf1b..0000000
--- a/runtime/vm/snapshot_ids.h
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright (c) 2012, 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.
-
-#ifndef RUNTIME_VM_SNAPSHOT_IDS_H_
-#define RUNTIME_VM_SNAPSHOT_IDS_H_
-
-#include "vm/dart_entry.h"
-#include "vm/raw_object.h"
-
-namespace dart {
-
-// Index for predefined singleton objects used in a snapshot.
-enum {
- kNullObject = 0,
- kSentinelObject,
- kTransitionSentinelObject,
- kEmptyArrayObject,
- kZeroArrayObject,
- kTrueValue,
- kFalseValue,
- // Marker for special encoding of double objects in message snapshots.
- kDoubleObject,
- // Object id has been optimized away; reader should use next available id.
- kOmittedObjectId,
-
- kClassIdsOffset = kOmittedObjectId,
-
- // The class ids of predefined classes are included in this list
- // at an offset of kClassIdsOffset.
-
- kFirstTypeSnapshotId = (kNumPredefinedCids + kClassIdsOffset),
- kLegacyObjectType = kFirstTypeSnapshotId,
- kNullableObjectType,
- kNullType,
- kDynamicType,
- kVoidType,
- kNeverType,
- kLegacyFunctionType,
- kLegacyNumberType,
- kLegacySmiType,
- kLegacyMintType,
- kLegacyDoubleType,
- kLegacyIntType,
- kLegacyBoolType,
- kLegacyStringType,
- kLegacyArrayType,
- kNonNullableObjectType,
- kNonNullableFunctionType,
- kNonNullableNumberType,
- kNonNullableSmiType,
- kNonNullableMintType,
- kNonNullableDoubleType,
- kNonNullableIntType,
- kNonNullableBoolType,
- kNonNullableStringType,
- kNonNullableArrayType,
- kLastTypeSnapshotId = kNonNullableArrayType,
-
- kFirstTypeArgumentsSnapshotId = kLastTypeSnapshotId + 1,
- kLegacyIntTypeArguments = kFirstTypeArgumentsSnapshotId,
- kLegacyDoubleTypeArguments,
- kLegacyStringTypeArguments,
- kLegacyStringDynamicTypeArguments,
- kLegacyStringLegacyStringTypeArguments,
- kNonNullableIntTypeArguments,
- kNonNullableDoubleTypeArguments,
- kNonNullableStringTypeArguments,
- kNonNullableStringDynamicTypeArguments,
- kNonNullableStringNonNullableStringTypeArguments,
- kEmptyTypeArguments,
- kLastTypeArgumentsSnapshotId = kEmptyTypeArguments,
-
- kExtractorParameterTypes,
- kExtractorParameterNames,
- kEmptyContextScopeObject,
- kImplicitClosureScopeObject,
- kEmptyObjectPool,
- kEmptyDescriptors,
- kEmptyVarDescriptors,
- kEmptyExceptionHandlers,
- kCachedArgumentsDescriptor0,
- kCachedArgumentsDescriptorN =
- (kCachedArgumentsDescriptor0 +
- ArgumentsDescriptor::kCachedDescriptorCount - 1),
- kCachedICDataArray0,
- kCachedICDataArrayN =
- (kCachedICDataArray0 + ICData::kCachedICDataArrayCount - 1),
-
- kInstanceObjectId,
- kStaticImplicitClosureObjectId,
- kMaxPredefinedObjectIds,
- kInvalidIndex = -1,
-};
-
-} // namespace dart
-
-#endif // RUNTIME_VM_SNAPSHOT_IDS_H_
diff --git a/runtime/vm/snapshot_test.cc b/runtime/vm/snapshot_test.cc
index 944124f..8affadb 100644
--- a/runtime/vm/snapshot_test.cc
+++ b/runtime/vm/snapshot_test.cc
@@ -15,6 +15,7 @@
#include "vm/debugger_api_impl_test.h"
#include "vm/flags.h"
#include "vm/malloc_hooks.h"
+#include "vm/message_snapshot.h"
#include "vm/snapshot.h"
#include "vm/symbols.h"
#include "vm/timer.h"
@@ -59,7 +60,6 @@
// Return immediately if entering a cycle.
if (second->type == Dart_CObject_kNumberOfTypes) return;
- EXPECT_NE(first, second);
EXPECT_EQ(first->type, second->type);
switch (first->type) {
case Dart_CObject_kNull:
@@ -106,23 +106,20 @@
}
}
-static void CheckEncodeDecodeMessage(Dart_CObject* root) {
+static void CheckEncodeDecodeMessage(Zone* zone, Dart_CObject* root) {
// Encode and decode the message.
- ApiMessageWriter writer;
std::unique_ptr<Message> message =
- writer.WriteCMessage(root, ILLEGAL_PORT, Message::kNormalPriority);
+ WriteApiMessage(zone, root, ILLEGAL_PORT, Message::kNormalPriority);
- ApiMessageReader api_reader(message.get());
- Dart_CObject* new_root = api_reader.ReadMessage();
+ Dart_CObject* new_root = ReadApiMessage(zone, message.get());
// Check that the two messages are the same.
CompareDartCObjects(root, new_root);
}
-static void ExpectEncodeFail(Dart_CObject* root) {
- ApiMessageWriter writer;
+static void ExpectEncodeFail(Zone* zone, Dart_CObject* root) {
std::unique_ptr<Message> message =
- writer.WriteCMessage(root, ILLEGAL_PORT, Message::kNormalPriority);
+ WriteApiMessage(zone, root, ILLEGAL_PORT, Message::kNormalPriority);
EXPECT(message == nullptr);
}
@@ -131,22 +128,21 @@
// Write snapshot with object content.
const Object& null_object = Object::Handle();
- MessageWriter writer(true);
std::unique_ptr<Message> message =
- writer.WriteMessage(null_object, ILLEGAL_PORT, Message::kNormalPriority);
+ WriteMessage(/* can_send_any_object */ true, null_object, ILLEGAL_PORT,
+ Message::kNormalPriority);
// Read object back from the snapshot.
- MessageSnapshotReader reader(message.get(), thread);
- const Object& serialized_object = Object::Handle(reader.ReadObject());
+ const Object& serialized_object =
+ Object::Handle(ReadMessage(thread, message.get()));
EXPECT(Equals(null_object, serialized_object));
// Read object back from the snapshot into a C structure.
ApiNativeScope scope;
- ApiMessageReader api_reader(message.get());
- Dart_CObject* root = api_reader.ReadMessage();
+ Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kNull, root->type);
- CheckEncodeDecodeMessage(root);
+ CheckEncodeDecodeMessage(scope.zone(), root);
}
ISOLATE_UNIT_TEST_CASE(SerializeSmi1) {
@@ -154,23 +150,22 @@
// Write snapshot with object content.
const Smi& smi = Smi::Handle(Smi::New(124));
- MessageWriter writer(true);
std::unique_ptr<Message> message =
- writer.WriteMessage(smi, ILLEGAL_PORT, Message::kNormalPriority);
+ WriteMessage(/* can_send_any_object */ true, smi, ILLEGAL_PORT,
+ Message::kNormalPriority);
// Read object back from the snapshot.
- MessageSnapshotReader reader(message.get(), thread);
- const Object& serialized_object = Object::Handle(reader.ReadObject());
+ const Object& serialized_object =
+ Object::Handle(ReadMessage(thread, message.get()));
EXPECT(Equals(smi, serialized_object));
// Read object back from the snapshot into a C structure.
ApiNativeScope scope;
- ApiMessageReader api_reader(message.get());
- Dart_CObject* root = api_reader.ReadMessage();
+ Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kInt32, root->type);
EXPECT_EQ(smi.Value(), root->value.as_int32);
- CheckEncodeDecodeMessage(root);
+ CheckEncodeDecodeMessage(scope.zone(), root);
}
ISOLATE_UNIT_TEST_CASE(SerializeSmi2) {
@@ -178,46 +173,44 @@
// Write snapshot with object content.
const Smi& smi = Smi::Handle(Smi::New(-1));
- MessageWriter writer(true);
std::unique_ptr<Message> message =
- writer.WriteMessage(smi, ILLEGAL_PORT, Message::kNormalPriority);
+ WriteMessage(/* can_send_any_object */ true, smi, ILLEGAL_PORT,
+ Message::kNormalPriority);
// Read object back from the snapshot.
- MessageSnapshotReader reader(message.get(), thread);
- const Object& serialized_object = Object::Handle(reader.ReadObject());
+ const Object& serialized_object =
+ Object::Handle(ReadMessage(thread, message.get()));
EXPECT(Equals(smi, serialized_object));
// Read object back from the snapshot into a C structure.
ApiNativeScope scope;
- ApiMessageReader api_reader(message.get());
- Dart_CObject* root = api_reader.ReadMessage();
+ Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kInt32, root->type);
EXPECT_EQ(smi.Value(), root->value.as_int32);
- CheckEncodeDecodeMessage(root);
+ CheckEncodeDecodeMessage(scope.zone(), root);
}
-Dart_CObject* SerializeAndDeserializeMint(const Mint& mint) {
+Dart_CObject* SerializeAndDeserializeMint(Zone* zone, const Mint& mint) {
// Write snapshot with object content.
- MessageWriter writer(true);
std::unique_ptr<Message> message =
- writer.WriteMessage(mint, ILLEGAL_PORT, Message::kNormalPriority);
+ WriteMessage(/* can_send_any_object */ true, mint, ILLEGAL_PORT,
+ Message::kNormalPriority);
{
// Switch to a regular zone, where VM handle allocation is allowed.
Thread* thread = Thread::Current();
StackZone zone(thread);
// Read object back from the snapshot.
- MessageSnapshotReader reader(message.get(), thread);
- const Object& serialized_object = Object::Handle(reader.ReadObject());
+ const Object& serialized_object =
+ Object::Handle(ReadMessage(thread, message.get()));
EXPECT(serialized_object.IsMint());
}
// Read object back from the snapshot into a C structure.
- ApiMessageReader api_reader(message.get());
- Dart_CObject* root = api_reader.ReadMessage();
+ Dart_CObject* root = ReadApiMessage(zone, message.get());
EXPECT_NOTNULL(root);
- CheckEncodeDecodeMessage(root);
+ CheckEncodeDecodeMessage(zone, root);
return root;
}
@@ -227,7 +220,8 @@
Mint& mint = Mint::Handle();
mint ^= Integer::New(value);
- Dart_CObject* mint_cobject = SerializeAndDeserializeMint(mint);
+ Dart_CObject* mint_cobject =
+ SerializeAndDeserializeMint(zone.GetZone(), mint);
// On 64-bit platforms mints always require 64-bits as the smi range
// here covers most of the 64-bit range. On 32-bit platforms the smi
// range covers most of the 32-bit range and values outside that
@@ -270,23 +264,22 @@
// Write snapshot with object content.
const Double& dbl = Double::Handle(Double::New(101.29));
- MessageWriter writer(true);
std::unique_ptr<Message> message =
- writer.WriteMessage(dbl, ILLEGAL_PORT, Message::kNormalPriority);
+ WriteMessage(/* can_send_any_object */ true, dbl, ILLEGAL_PORT,
+ Message::kNormalPriority);
// Read object back from the snapshot.
- MessageSnapshotReader reader(message.get(), thread);
- const Object& serialized_object = Object::Handle(reader.ReadObject());
+ const Object& serialized_object =
+ Object::Handle(ReadMessage(thread, message.get()));
EXPECT(Equals(dbl, serialized_object));
// Read object back from the snapshot into a C structure.
ApiNativeScope scope;
- ApiMessageReader api_reader(message.get());
- Dart_CObject* root = api_reader.ReadMessage();
+ Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kDouble, root->type);
EXPECT_EQ(dbl.value(), root->value.as_double);
- CheckEncodeDecodeMessage(root);
+ CheckEncodeDecodeMessage(scope.zone(), root);
}
ISOLATE_UNIT_TEST_CASE(SerializeTrue) {
@@ -294,25 +287,24 @@
// Write snapshot with true object.
const Bool& bl = Bool::True();
- MessageWriter writer(true);
- std::unique_ptr<Message> message =
- writer.WriteMessage(bl, ILLEGAL_PORT, Message::kNormalPriority);
+ std::unique_ptr<Message> message = WriteMessage(
+ /* can_send_any_object */ true, bl, ILLEGAL_PORT,
+ Message::kNormalPriority);
// Read object back from the snapshot.
- MessageSnapshotReader reader(message.get(), thread);
- const Object& serialized_object = Object::Handle(reader.ReadObject());
+ const Object& serialized_object =
+ Object::Handle(ReadMessage(thread, message.get()));
fprintf(stderr, "%s / %s\n", bl.ToCString(), serialized_object.ToCString());
EXPECT(Equals(bl, serialized_object));
// Read object back from the snapshot into a C structure.
ApiNativeScope scope;
- ApiMessageReader api_reader(message.get());
- Dart_CObject* root = api_reader.ReadMessage();
+ Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kBool, root->type);
EXPECT_EQ(true, root->value.as_bool);
- CheckEncodeDecodeMessage(root);
+ CheckEncodeDecodeMessage(scope.zone(), root);
}
ISOLATE_UNIT_TEST_CASE(SerializeFalse) {
@@ -320,57 +312,55 @@
// Write snapshot with false object.
const Bool& bl = Bool::False();
- MessageWriter writer(true);
- std::unique_ptr<Message> message =
- writer.WriteMessage(bl, ILLEGAL_PORT, Message::kNormalPriority);
+ std::unique_ptr<Message> message = WriteMessage(
+ /* can_send_any_object */ true, bl, ILLEGAL_PORT,
+ Message::kNormalPriority);
// Read object back from the snapshot.
- MessageSnapshotReader reader(message.get(), thread);
- const Object& serialized_object = Object::Handle(reader.ReadObject());
+ const Object& serialized_object =
+ Object::Handle(ReadMessage(thread, message.get()));
EXPECT(Equals(bl, serialized_object));
// Read object back from the snapshot into a C structure.
ApiNativeScope scope;
- ApiMessageReader api_reader(message.get());
- Dart_CObject* root = api_reader.ReadMessage();
+ Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kBool, root->type);
EXPECT_EQ(false, root->value.as_bool);
- CheckEncodeDecodeMessage(root);
+ CheckEncodeDecodeMessage(scope.zone(), root);
}
ISOLATE_UNIT_TEST_CASE(SerializeCapability) {
// Write snapshot with object content.
const Capability& capability = Capability::Handle(Capability::New(12345));
- MessageWriter writer(true);
std::unique_ptr<Message> message =
- writer.WriteMessage(capability, ILLEGAL_PORT, Message::kNormalPriority);
+ WriteMessage(/* can_send_any_object */ true, capability, ILLEGAL_PORT,
+ Message::kNormalPriority);
// Read object back from the snapshot.
- MessageSnapshotReader reader(message.get(), thread);
Capability& obj = Capability::Handle();
- obj ^= reader.ReadObject();
+ obj ^= ReadMessage(thread, message.get());
EXPECT_EQ(static_cast<uint64_t>(12345), obj.Id());
// Read object back from the snapshot into a C structure.
ApiNativeScope scope;
- ApiMessageReader api_reader(message.get());
- Dart_CObject* root = api_reader.ReadMessage();
+ Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kCapability, root->type);
int64_t id = root->value.as_capability.id;
EXPECT_EQ(12345, id);
- CheckEncodeDecodeMessage(root);
+ CheckEncodeDecodeMessage(scope.zone(), root);
}
#define TEST_ROUND_TRIP_IDENTICAL(object) \
{ \
- MessageWriter writer(true); \
- std::unique_ptr<Message> message = writer.WriteMessage( \
- Object::Handle(object), ILLEGAL_PORT, Message::kNormalPriority); \
- MessageSnapshotReader reader(message.get(), thread); \
- EXPECT(reader.ReadObject() == object); \
+ const Object& before = Object::Handle(object); \
+ std::unique_ptr<Message> message = \
+ WriteMessage(/* can_send_any_object */ true, before, ILLEGAL_PORT, \
+ Message::kNormalPriority); \
+ const Object& after = Object::Handle(ReadMessage(thread, message.get())); \
+ EXPECT(before.ptr() == after.ptr()); \
}
ISOLATE_UNIT_TEST_CASE(SerializeSingletons) {
@@ -393,23 +383,21 @@
EXPECT(Utf8::IsValid(reinterpret_cast<const uint8_t*>(cstr), strlen(cstr)));
// Write snapshot with object content.
String& str = String::Handle(String::New(cstr));
- MessageWriter writer(true);
std::unique_ptr<Message> message =
- writer.WriteMessage(str, ILLEGAL_PORT, Message::kNormalPriority);
+ WriteMessage(/* can_send_any_object */ true, str, ILLEGAL_PORT,
+ Message::kNormalPriority);
// Read object back from the snapshot.
- MessageSnapshotReader reader(message.get(), thread);
String& serialized_str = String::Handle();
- serialized_str ^= reader.ReadObject();
+ serialized_str ^= ReadMessage(thread, message.get());
EXPECT(str.Equals(serialized_str));
// Read object back from the snapshot into a C structure.
ApiNativeScope scope;
- ApiMessageReader api_reader(message.get());
- Dart_CObject* root = api_reader.ReadMessage();
+ Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_EQ(Dart_CObject_kString, root->type);
EXPECT_STREQ(cstr, root->value.as_string);
- CheckEncodeDecodeMessage(root);
+ CheckEncodeDecodeMessage(scope.zone(), root);
}
ISOLATE_UNIT_TEST_CASE(SerializeString) {
@@ -436,20 +424,18 @@
smi ^= Smi::New(i);
array.SetAt(i, smi);
}
- MessageWriter writer(true);
std::unique_ptr<Message> message =
- writer.WriteMessage(array, ILLEGAL_PORT, Message::kNormalPriority);
+ WriteMessage(/* can_send_any_object */ true, array, ILLEGAL_PORT,
+ Message::kNormalPriority);
// Read object back from the snapshot.
- MessageSnapshotReader reader(message.get(), thread);
Array& serialized_array = Array::Handle();
- serialized_array ^= reader.ReadObject();
+ serialized_array ^= ReadMessage(thread, message.get());
EXPECT(array.CanonicalizeEquals(serialized_array));
// Read object back from the snapshot into a C structure.
ApiNativeScope scope;
- ApiMessageReader api_reader(message.get());
- Dart_CObject* root = api_reader.ReadMessage();
+ Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_EQ(Dart_CObject_kArray, root->type);
EXPECT_EQ(kArrayLength, root->value.as_array.length);
for (int i = 0; i < kArrayLength; i++) {
@@ -457,7 +443,7 @@
EXPECT_EQ(Dart_CObject_kInt32, element->type);
EXPECT_EQ(i, element->value.as_int32);
}
- CheckEncodeDecodeMessage(root);
+ CheckEncodeDecodeMessage(scope.zone(), root);
}
ISOLATE_UNIT_TEST_CASE(SerializeArrayWithTypeArgument) {
@@ -471,20 +457,18 @@
smi ^= Smi::New(i);
array.SetAt(i, smi);
}
- MessageWriter writer(true);
std::unique_ptr<Message> message =
- writer.WriteMessage(array, ILLEGAL_PORT, Message::kNormalPriority);
+ WriteMessage(/* can_send_any_object */ true, array, ILLEGAL_PORT,
+ Message::kNormalPriority);
// Read object back from the snapshot.
- MessageSnapshotReader reader(message.get(), thread);
Array& serialized_array = Array::Handle();
- serialized_array ^= reader.ReadObject();
+ serialized_array ^= ReadMessage(thread, message.get());
EXPECT(array.CanonicalizeEquals(serialized_array));
// Read object back from the snapshot into a C structure.
ApiNativeScope scope;
- ApiMessageReader api_reader(message.get());
- Dart_CObject* root = api_reader.ReadMessage();
+ Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_EQ(Dart_CObject_kArray, root->type);
EXPECT_EQ(kArrayLength, root->value.as_array.length);
for (int i = 0; i < kArrayLength; i++) {
@@ -492,7 +476,7 @@
EXPECT_EQ(Dart_CObject_kInt32, element->type);
EXPECT_EQ(i, element->value.as_int32);
}
- CheckEncodeDecodeMessage(root);
+ CheckEncodeDecodeMessage(scope.zone(), root);
}
TEST_CASE(FailSerializeLargeArray) {
@@ -500,7 +484,8 @@
root.type = Dart_CObject_kArray;
root.value.as_array.length = Array::kMaxElements + 1;
root.value.as_array.values = NULL;
- ExpectEncodeFail(&root);
+ ApiNativeScope scope;
+ ExpectEncodeFail(scope.zone(), &root);
}
TEST_CASE(FailSerializeLargeNestedArray) {
@@ -513,7 +498,8 @@
parent.value.as_array.values = values;
child.type = Dart_CObject_kArray;
child.value.as_array.length = Array::kMaxElements + 1;
- ExpectEncodeFail(&parent);
+ ApiNativeScope scope;
+ ExpectEncodeFail(scope.zone(), &parent);
}
TEST_CASE(FailSerializeLargeTypedDataInt8) {
@@ -522,7 +508,8 @@
root.value.as_typed_data.type = Dart_TypedData_kInt8;
root.value.as_typed_data.length =
TypedData::MaxElements(kTypedDataInt8ArrayCid) + 1;
- ExpectEncodeFail(&root);
+ ApiNativeScope scope;
+ ExpectEncodeFail(scope.zone(), &root);
}
TEST_CASE(FailSerializeLargeTypedDataUint8) {
@@ -531,39 +518,40 @@
root.value.as_typed_data.type = Dart_TypedData_kUint8;
root.value.as_typed_data.length =
TypedData::MaxElements(kTypedDataUint8ArrayCid) + 1;
- ExpectEncodeFail(&root);
+ ApiNativeScope scope;
+ ExpectEncodeFail(scope.zone(), &root);
}
TEST_CASE(FailSerializeLargeExternalTypedData) {
Dart_CObject root;
root.type = Dart_CObject_kExternalTypedData;
- root.value.as_typed_data.length =
+ root.value.as_external_typed_data.type = Dart_TypedData_kUint8;
+ root.value.as_external_typed_data.length =
ExternalTypedData::MaxElements(kExternalTypedDataUint8ArrayCid) + 1;
- ExpectEncodeFail(&root);
+ ApiNativeScope scope;
+ ExpectEncodeFail(scope.zone(), &root);
}
ISOLATE_UNIT_TEST_CASE(SerializeEmptyArray) {
// Write snapshot with object content.
const int kArrayLength = 0;
Array& array = Array::Handle(Array::New(kArrayLength));
- MessageWriter writer(true);
std::unique_ptr<Message> message =
- writer.WriteMessage(array, ILLEGAL_PORT, Message::kNormalPriority);
+ WriteMessage(/* can_send_any_object */ true, array, ILLEGAL_PORT,
+ Message::kNormalPriority);
// Read object back from the snapshot.
- MessageSnapshotReader reader(message.get(), thread);
Array& serialized_array = Array::Handle();
- serialized_array ^= reader.ReadObject();
+ serialized_array ^= ReadMessage(thread, message.get());
EXPECT(array.CanonicalizeEquals(serialized_array));
// Read object back from the snapshot into a C structure.
ApiNativeScope scope;
- ApiMessageReader api_reader(message.get());
- Dart_CObject* root = api_reader.ReadMessage();
+ Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_EQ(Dart_CObject_kArray, root->type);
EXPECT_EQ(kArrayLength, root->value.as_array.length);
EXPECT(root->value.as_array.values == NULL);
- CheckEncodeDecodeMessage(root);
+ CheckEncodeDecodeMessage(scope.zone(), root);
}
ISOLATE_UNIT_TEST_CASE(SerializeByteArray) {
@@ -574,26 +562,24 @@
for (int i = 0; i < kTypedDataLength; i++) {
typed_data.SetUint8(i, i);
}
- MessageWriter writer(true);
std::unique_ptr<Message> message =
- writer.WriteMessage(typed_data, ILLEGAL_PORT, Message::kNormalPriority);
+ WriteMessage(/* can_send_any_object */ true, typed_data, ILLEGAL_PORT,
+ Message::kNormalPriority);
// Read object back from the snapshot.
- MessageSnapshotReader reader(message.get(), thread);
TypedData& serialized_typed_data = TypedData::Handle();
- serialized_typed_data ^= reader.ReadObject();
+ serialized_typed_data ^= ReadMessage(thread, message.get());
EXPECT(serialized_typed_data.IsTypedData());
// Read object back from the snapshot into a C structure.
ApiNativeScope scope;
- ApiMessageReader api_reader(message.get());
- Dart_CObject* root = api_reader.ReadMessage();
+ Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_EQ(Dart_CObject_kTypedData, root->type);
EXPECT_EQ(kTypedDataLength, root->value.as_typed_data.length);
for (int i = 0; i < kTypedDataLength; i++) {
EXPECT(root->value.as_typed_data.values[i] == i);
}
- CheckEncodeDecodeMessage(root);
+ CheckEncodeDecodeMessage(scope.zone(), root);
}
#define TEST_TYPED_ARRAY(darttype, ctype) \
@@ -606,12 +592,11 @@
for (int i = 0; i < kArrayLength; i++) { \
array.Set##darttype((i * scale), i); \
} \
- MessageWriter writer(true); \
std::unique_ptr<Message> message = \
- writer.WriteMessage(array, ILLEGAL_PORT, Message::kNormalPriority); \
- MessageSnapshotReader reader(message.get(), thread); \
+ WriteMessage(/* can_send_any_object */ true, array, ILLEGAL_PORT, \
+ Message::kNormalPriority); \
TypedData& serialized_array = TypedData::Handle(); \
- serialized_array ^= reader.ReadObject(); \
+ serialized_array ^= ReadMessage(thread, message.get()); \
for (int i = 0; i < kArrayLength; i++) { \
EXPECT_EQ(static_cast<ctype>(i), \
serialized_array.Get##darttype(i* scale)); \
@@ -627,12 +612,11 @@
ExternalTypedData::New(kExternalTypedData##darttype##ArrayCid, \
reinterpret_cast<uint8_t*>(data), length)); \
intptr_t scale = array.ElementSizeInBytes(); \
- MessageWriter writer(true); \
std::unique_ptr<Message> message = \
- writer.WriteMessage(array, ILLEGAL_PORT, Message::kNormalPriority); \
- MessageSnapshotReader reader(message.get(), thread); \
+ WriteMessage(/* can_send_any_object */ true, array, ILLEGAL_PORT, \
+ Message::kNormalPriority); \
ExternalTypedData& serialized_array = ExternalTypedData::Handle(); \
- serialized_array ^= reader.ReadObject(); \
+ serialized_array ^= ReadMessage(thread, message.get()); \
for (int i = 0; i < length; i++) { \
EXPECT_EQ(static_cast<ctype>(data[i]), \
serialized_array.Get##darttype(i* scale)); \
@@ -670,25 +654,23 @@
const int kTypedDataLength = 0;
TypedData& typed_data = TypedData::Handle(
TypedData::New(kTypedDataUint8ArrayCid, kTypedDataLength));
- MessageWriter writer(true);
std::unique_ptr<Message> message =
- writer.WriteMessage(typed_data, ILLEGAL_PORT, Message::kNormalPriority);
+ WriteMessage(/* can_send_any_object */ true, typed_data, ILLEGAL_PORT,
+ Message::kNormalPriority);
// Read object back from the snapshot.
- MessageSnapshotReader reader(message.get(), thread);
TypedData& serialized_typed_data = TypedData::Handle();
- serialized_typed_data ^= reader.ReadObject();
+ serialized_typed_data ^= ReadMessage(thread, message.get());
EXPECT(serialized_typed_data.IsTypedData());
// Read object back from the snapshot into a C structure.
ApiNativeScope scope;
- ApiMessageReader api_reader(message.get());
- Dart_CObject* root = api_reader.ReadMessage();
+ Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_EQ(Dart_CObject_kTypedData, root->type);
EXPECT_EQ(Dart_TypedData_kUint8, root->value.as_typed_data.type);
EXPECT_EQ(kTypedDataLength, root->value.as_typed_data.length);
EXPECT(root->value.as_typed_data.values == NULL);
- CheckEncodeDecodeMessage(root);
+ CheckEncodeDecodeMessage(scope.zone(), root);
}
VM_UNIT_TEST_CASE(FullSnapshot) {
@@ -790,47 +772,38 @@
Object& obj = Object::Handle(Api::UnwrapHandle(result));
// Serialize the object into a message.
- MessageWriter writer(false);
- return writer.WriteMessage(obj, ILLEGAL_PORT, Message::kNormalPriority);
-}
-
-// Helper function to deserialize the result into a Dart_CObject structure.
-static Dart_CObject* GetDeserialized(Message* message) {
- // Read object back from the snapshot into a C structure.
- ApiMessageReader api_reader(message);
- return api_reader.ReadMessage();
+ return WriteMessage(/* can_send_any_object */ false, obj, ILLEGAL_PORT,
+ Message::kNormalPriority);
}
static void CheckString(Dart_Handle dart_string, const char* expected) {
StackZone zone(Thread::Current());
String& str = String::Handle();
str ^= Api::UnwrapHandle(dart_string);
- MessageWriter writer(false);
std::unique_ptr<Message> message =
- writer.WriteMessage(str, ILLEGAL_PORT, Message::kNormalPriority);
+ WriteMessage(/* can_send_any_object */ false, str, ILLEGAL_PORT,
+ Message::kNormalPriority);
// Read object back from the snapshot into a C structure.
ApiNativeScope scope;
- ApiMessageReader api_reader(message.get());
- Dart_CObject* root = api_reader.ReadMessage();
+ Dart_CObject* root = ReadApiMessage(zone.GetZone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kString, root->type);
EXPECT_STREQ(expected, root->value.as_string);
- CheckEncodeDecodeMessage(root);
+ CheckEncodeDecodeMessage(zone.GetZone(), root);
}
static void CheckStringInvalid(Dart_Handle dart_string) {
StackZone zone(Thread::Current());
String& str = String::Handle();
str ^= Api::UnwrapHandle(dart_string);
- MessageWriter writer(false);
std::unique_ptr<Message> message =
- writer.WriteMessage(str, ILLEGAL_PORT, Message::kNormalPriority);
+ WriteMessage(/* can_send_any_object */ false, str, ILLEGAL_PORT,
+ Message::kNormalPriority);
// Read object back from the snapshot into a C structure.
ApiNativeScope scope;
- ApiMessageReader api_reader(message.get());
- Dart_CObject* root = api_reader.ReadMessage();
+ Dart_CObject* root = ReadApiMessage(zone.GetZone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kUnsupported, root->type);
}
@@ -928,18 +901,17 @@
StackZone zone(thread);
Smi& smi = Smi::Handle();
smi ^= Api::UnwrapHandle(smi_result);
- MessageWriter writer(false);
std::unique_ptr<Message> message =
- writer.WriteMessage(smi, ILLEGAL_PORT, Message::kNormalPriority);
+ WriteMessage(/* can_send_any_object */ false, smi, ILLEGAL_PORT,
+ Message::kNormalPriority);
// Read object back from the snapshot into a C structure.
ApiNativeScope scope;
- ApiMessageReader api_reader(message.get());
- Dart_CObject* root = api_reader.ReadMessage();
+ Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kInt32, root->type);
EXPECT_EQ(42, root->value.as_int32);
- CheckEncodeDecodeMessage(root);
+ CheckEncodeDecodeMessage(scope.zone(), root);
}
CheckString(ascii_string_result, "Hello, world!");
CheckString(non_ascii_string_result, "Blåbærgrød");
@@ -1000,20 +972,20 @@
// Generate a list of nulls from Dart code.
std::unique_ptr<Message> message = GetSerialized(lib, "getList");
ApiNativeScope scope;
- Dart_CObject* root = GetDeserialized(message.get());
+ Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kArray, root->type);
EXPECT_EQ(kArrayLength, root->value.as_array.length);
for (int i = 0; i < kArrayLength; i++) {
EXPECT_EQ(Dart_CObject_kNull, root->value.as_array.values[i]->type);
}
- CheckEncodeDecodeMessage(root);
+ CheckEncodeDecodeMessage(scope.zone(), root);
}
{
// Generate a list of ints from Dart code.
std::unique_ptr<Message> message = GetSerialized(lib, "getIntList");
ApiNativeScope scope;
- Dart_CObject* root = GetDeserialized(message.get());
+ Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kArray, root->type);
EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1021,13 +993,13 @@
EXPECT_EQ(Dart_CObject_kInt32, root->value.as_array.values[i]->type);
EXPECT_EQ(i, root->value.as_array.values[i]->value.as_int32);
}
- CheckEncodeDecodeMessage(root);
+ CheckEncodeDecodeMessage(scope.zone(), root);
}
{
// Generate a list of strings from Dart code.
std::unique_ptr<Message> message = GetSerialized(lib, "getStringList");
ApiNativeScope scope;
- Dart_CObject* root = GetDeserialized(message.get());
+ Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kArray, root->type);
EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1042,7 +1014,7 @@
// Generate a list of objects of different types from Dart code.
std::unique_ptr<Message> message = GetSerialized(lib, "getMixedList");
ApiNativeScope scope;
- Dart_CObject* root = GetDeserialized(message.get());
+ Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kArray, root->type);
EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1124,20 +1096,20 @@
// Generate a list of nulls from Dart code.
std::unique_ptr<Message> message = GetSerialized(lib, "getList");
ApiNativeScope scope;
- Dart_CObject* root = GetDeserialized(message.get());
+ Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kArray, root->type);
EXPECT_EQ(kArrayLength, root->value.as_array.length);
for (int i = 0; i < kArrayLength; i++) {
EXPECT_EQ(Dart_CObject_kNull, root->value.as_array.values[i]->type);
}
- CheckEncodeDecodeMessage(root);
+ CheckEncodeDecodeMessage(scope.zone(), root);
}
{
// Generate a list of ints from Dart code.
std::unique_ptr<Message> message = GetSerialized(lib, "getIntList");
ApiNativeScope scope;
- Dart_CObject* root = GetDeserialized(message.get());
+ Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kArray, root->type);
EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1145,13 +1117,13 @@
EXPECT_EQ(Dart_CObject_kInt32, root->value.as_array.values[i]->type);
EXPECT_EQ(i, root->value.as_array.values[i]->value.as_int32);
}
- CheckEncodeDecodeMessage(root);
+ CheckEncodeDecodeMessage(scope.zone(), root);
}
{
// Generate a list of strings from Dart code.
std::unique_ptr<Message> message = GetSerialized(lib, "getStringList");
ApiNativeScope scope;
- Dart_CObject* root = GetDeserialized(message.get());
+ Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kArray, root->type);
EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1166,7 +1138,7 @@
// Generate a list of lists from Dart code.
std::unique_ptr<Message> message = GetSerialized(lib, "getListList");
ApiNativeScope scope;
- Dart_CObject* root = GetDeserialized(message.get());
+ Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kArray, root->type);
EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1185,7 +1157,7 @@
// Generate a list of objects of different types from Dart code.
std::unique_ptr<Message> message = GetSerialized(lib, "getMixedList");
ApiNativeScope scope;
- Dart_CObject* root = GetDeserialized(message.get());
+ Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kArray, root->type);
EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1357,7 +1329,7 @@
// Generate a list of strings from Dart code.
std::unique_ptr<Message> message = GetSerialized(lib, "getStringList");
ApiNativeScope scope;
- Dart_CObject* root = GetDeserialized(message.get());
+ Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kArray, root->type);
EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1372,7 +1344,7 @@
// Generate a list of medium ints from Dart code.
std::unique_ptr<Message> message = GetSerialized(lib, "getMintList");
ApiNativeScope scope;
- Dart_CObject* root = GetDeserialized(message.get());
+ Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kArray, root->type);
EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1387,7 +1359,7 @@
// Generate a list of doubles from Dart code.
std::unique_ptr<Message> message = GetSerialized(lib, "getDoubleList");
ApiNativeScope scope;
- Dart_CObject* root = GetDeserialized(message.get());
+ Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kArray, root->type);
EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1396,8 +1368,6 @@
EXPECT_EQ(3.14, element->value.as_double);
for (int i = 1; i < kArrayLength; i++) {
element = root->value.as_array.values[i];
- // Double values are expected to not be canonicalized in messages.
- EXPECT_NE(root->value.as_array.values[0], element);
EXPECT_EQ(Dart_CObject_kDouble, element->type);
EXPECT_EQ(3.14, element->value.as_double);
}
@@ -1406,7 +1376,7 @@
// Generate a list of Uint8Lists from Dart code.
std::unique_ptr<Message> message = GetSerialized(lib, "getTypedDataList");
ApiNativeScope scope;
- Dart_CObject* root = GetDeserialized(message.get());
+ Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kArray, root->type);
EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1423,7 +1393,7 @@
std::unique_ptr<Message> message =
GetSerialized(lib, "getTypedDataViewList");
ApiNativeScope scope;
- Dart_CObject* root = GetDeserialized(message.get());
+ Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kArray, root->type);
EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1441,7 +1411,7 @@
// Generate a list of objects of different types from Dart code.
std::unique_ptr<Message> message = GetSerialized(lib, "getMixedList");
ApiNativeScope scope;
- Dart_CObject* root = GetDeserialized(message.get());
+ Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kArray, root->type);
EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1458,8 +1428,6 @@
EXPECT_EQ(Dart_CObject_kString, element->type);
EXPECT_STREQ("A", element->value.as_string);
} else {
- // Double values are expected to not be canonicalized in messages.
- EXPECT_NE(root->value.as_array.values[1], element);
EXPECT_EQ(Dart_CObject_kDouble, element->type);
EXPECT_EQ(2.72, element->value.as_double);
}
@@ -1469,7 +1437,7 @@
// Generate a list of objects of different types from Dart code.
std::unique_ptr<Message> message = GetSerialized(lib, "getSelfRefList");
ApiNativeScope scope;
- Dart_CObject* root = GetDeserialized(message.get());
+ Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kArray, root->type);
EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1560,7 +1528,7 @@
// Generate a list of strings from Dart code.
std::unique_ptr<Message> message = GetSerialized(lib, "getStringList");
ApiNativeScope scope;
- Dart_CObject* root = GetDeserialized(message.get());
+ Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kArray, root->type);
EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1575,7 +1543,7 @@
// Generate a list of medium ints from Dart code.
std::unique_ptr<Message> message = GetSerialized(lib, "getMintList");
ApiNativeScope scope;
- Dart_CObject* root = GetDeserialized(message.get());
+ Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kArray, root->type);
EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1590,18 +1558,15 @@
// Generate a list of doubles from Dart code.
std::unique_ptr<Message> message = GetSerialized(lib, "getDoubleList");
ApiNativeScope scope;
- Dart_CObject* root = GetDeserialized(message.get());
+ Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kArray, root->type);
EXPECT_EQ(kArrayLength, root->value.as_array.length);
Dart_CObject* element = root->value.as_array.values[0];
- // Double values are expected to not be canonicalized in messages.
EXPECT_EQ(Dart_CObject_kDouble, element->type);
EXPECT_EQ(3.14, element->value.as_double);
for (int i = 1; i < kArrayLength; i++) {
element = root->value.as_array.values[i];
- // Double values are expected to not be canonicalized in messages.
- EXPECT_NE(root->value.as_array.values[0], element);
EXPECT_EQ(Dart_CObject_kDouble, element->type);
EXPECT_EQ(3.14, element->value.as_double);
}
@@ -1610,7 +1575,7 @@
// Generate a list of Uint8Lists from Dart code.
std::unique_ptr<Message> message = GetSerialized(lib, "getTypedDataList");
ApiNativeScope scope;
- Dart_CObject* root = GetDeserialized(message.get());
+ Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kArray, root->type);
EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1627,7 +1592,7 @@
std::unique_ptr<Message> message =
GetSerialized(lib, "getTypedDataViewList");
ApiNativeScope scope;
- Dart_CObject* root = GetDeserialized(message.get());
+ Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kArray, root->type);
EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1645,7 +1610,7 @@
// Generate a list of objects of different types from Dart code.
std::unique_ptr<Message> message = GetSerialized(lib, "getMixedList");
ApiNativeScope scope;
- Dart_CObject* root = GetDeserialized(message.get());
+ Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kArray, root->type);
EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1662,8 +1627,6 @@
EXPECT_EQ(Dart_CObject_kString, element->type);
EXPECT_STREQ(".", element->value.as_string);
} else {
- // Double values are expected to not be canonicalized in messages.
- EXPECT_NE(root->value.as_array.values[1], element);
EXPECT_EQ(Dart_CObject_kDouble, element->type);
EXPECT_EQ(2.72, element->value.as_double);
}
@@ -1673,7 +1636,7 @@
// Generate a list of objects of different types from Dart code.
std::unique_ptr<Message> message = GetSerialized(lib, "getSelfRefList");
ApiNativeScope scope;
- Dart_CObject* root = GetDeserialized(message.get());
+ Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kArray, root->type);
EXPECT_EQ(kArrayLength, root->value.as_array.length);
@@ -1806,7 +1769,7 @@
// Generate a list of Uint8Lists from Dart code.
std::unique_ptr<Message> message = GetSerialized(lib, "getTypedDataList");
ApiNativeScope scope;
- Dart_CObject* root = GetDeserialized(message.get());
+ Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kArray, root->type);
struct {
@@ -1834,7 +1797,7 @@
std::unique_ptr<Message> message =
GetSerialized(lib, "getTypedDataViewList");
ApiNativeScope scope;
- Dart_CObject* root = GetDeserialized(message.get());
+ Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kArray, root->type);
struct {
@@ -1882,7 +1845,7 @@
std::unique_ptr<Message> message =
GetSerialized(lib, "getMultipleTypedDataViewList");
ApiNativeScope scope;
- Dart_CObject* root = GetDeserialized(message.get());
+ Dart_CObject* root = ReadApiMessage(scope.zone(), message.get());
EXPECT_NOTNULL(root);
EXPECT_EQ(Dart_CObject_kArray, root->type);
struct {
@@ -2009,15 +1972,6 @@
Dart_ExitScope();
}
-ISOLATE_UNIT_TEST_CASE(OmittedObjectEncodingLength) {
- StackZone zone(Thread::Current());
- MessageWriter writer(true);
- writer.WriteInlinedObjectHeader(kOmittedObjectId);
- // For performance, we'd like single-byte headers when ids are omitted.
- // If this starts failing, consider renumbering the snapshot ids.
- EXPECT_EQ(1, writer.BytesWritten());
-}
-
TEST_CASE(IsKernelNegative) {
EXPECT(!Dart_IsKernel(NULL, 0));
diff --git a/runtime/vm/source_report.cc b/runtime/vm/source_report.cc
index 03eaf12..f999c81 100644
--- a/runtime/vm/source_report.cc
+++ b/runtime/vm/source_report.cc
@@ -59,7 +59,7 @@
// Build the profile.
SampleFilter samplesForIsolate(thread_->isolate()->main_port(),
Thread::kMutatorTask, -1, -1);
- profile_.Build(thread, &samplesForIsolate, Profiler::sample_buffer());
+ profile_.Build(thread, &samplesForIsolate, Profiler::sample_block_buffer());
}
}
diff --git a/runtime/vm/source_report_test.cc b/runtime/vm/source_report_test.cc
index ad8c574..5934703 100644
--- a/runtime/vm/source_report_test.cc
+++ b/runtime/vm/source_report_test.cc
@@ -497,7 +497,7 @@
ISOLATE_UNIT_TEST_CASE(SourceReport_CallSites_SimpleCall) {
// WARNING: This MUST be big enough for the serialised JSON string.
- const int kBufferSize = 1024;
+ const int kBufferSize = 2048;
char buffer[kBufferSize];
const char* kScript =
"helper0() {}\n"
@@ -537,6 +537,7 @@
"\"name\":\"helper0\",\"owner\":{\"type\":\"@Library\",\"fixedId\":true,"
"\"id\":\"\",\"name\":\"\",\"uri\":\"file:\\/\\/\\/test-lib\"},"
"\"_kind\":\"RegularFunction\",\"static\":true,\"const\":false,"
+ "\"implicit\":false,"
"\"_intrinsic\":false,\"_native\":false,\"location\":{\"type\":"
"\"SourceLocation\",\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
"\"id\":\"\",\"uri\":\"file:\\/\\/\\/test-lib\",\"_kind\":\"kernel\"},"
@@ -617,7 +618,8 @@
"\"library\":{\"type\":\"@Library\",\"fixedId\":true,"
"\"id\":\"\",\"name\":\"\",\"uri\":\"file:\\/\\/\\/test-lib\"}"
"},\"_kind\":\"RegularFunction\","
- "\"static\":false,\"const\":false,\"_intrinsic\":false,"
+ "\"static\":false,\"const\":false,\"implicit\":false,\"_intrinsic\":"
+ "false,"
"\"_native\":false,"
"\"location\":{\"type\":\"SourceLocation\","
"\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
@@ -649,7 +651,8 @@
"\"library\":{\"type\":\"@Library\",\"fixedId\":true,"
"\"id\":\"\",\"name\":\"\",\"uri\":\"file:\\/\\/\\/test-lib\"}"
"},\"_kind\":\"RegularFunction\","
- "\"static\":false,\"const\":false,\"_intrinsic\":false,"
+ "\"static\":false,\"const\":false,\"implicit\":false,\"_intrinsic\":"
+ "false,"
"\"_native\":false,"
"\"location\":{\"type\":\"SourceLocation\","
"\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
@@ -705,7 +708,8 @@
"\"target\":{\"type\":\"@Function\",\"fixedId\":true,\"id\":\"\","
"\"name\":\"helper0\",\"owner\":{\"type\":\"@Library\",\"fixedId\":true,"
"\"id\":\"\",\"name\":\"\",\"uri\":\"file:\\/\\/\\/test-lib\"},\"_"
- "kind\":\"RegularFunction\",\"static\":true,\"const\":false,\"_"
+ "kind\":\"RegularFunction\",\"static\":true,\"const\":false,\"implicit\":"
+ "false,\"_"
"intrinsic\":false,\"_native\":false,\"location\":{\"type\":"
"\"SourceLocation\",\"script\":{\"type\":\"@Script\",\"fixedId\":true,"
"\"id\":\"\",\"uri\":\"file:\\/\\/\\/test-lib\",\"_kind\":\"kernel\"},"
diff --git a/runtime/vm/stack_trace.cc b/runtime/vm/stack_trace.cc
index 74fa21a..1f29e90 100644
--- a/runtime/vm/stack_trace.cc
+++ b/runtime/vm/stack_trace.cc
@@ -5,6 +5,7 @@
#include "vm/stack_trace.h"
#include "vm/dart_api_impl.h"
+#include "vm/object_store.h"
#include "vm/stack_frame.h"
#include "vm/symbols.h"
@@ -242,14 +243,26 @@
parent_function_ = receiver_function_.parent_function();
if (parent_function_.recognized_kind() ==
MethodRecognizer::kFutureTimeout) {
- context_entry_ = receiver_context_.At(Context::kFutureTimeoutFutureIndex);
+ ASSERT(IsolateGroup::Current()
+ ->object_store()
+ ->future_timeout_future_index() != Object::null());
+ const intptr_t future_index =
+ Smi::Value(IsolateGroup::Current()
+ ->object_store()
+ ->future_timeout_future_index());
+ context_entry_ = receiver_context_.At(future_index);
return GetCallerInFutureImpl(context_entry_);
}
if (parent_function_.recognized_kind() == MethodRecognizer::kFutureWait) {
receiver_context_ = receiver_context_.parent();
ASSERT(!receiver_context_.IsNull());
- context_entry_ = receiver_context_.At(Context::kFutureWaitFutureIndex);
+ ASSERT(
+ IsolateGroup::Current()->object_store()->future_wait_future_index() !=
+ Object::null());
+ const intptr_t future_index = Smi::Value(
+ IsolateGroup::Current()->object_store()->future_wait_future_index());
+ context_entry_ = receiver_context_.At(future_index);
return GetCallerInFutureImpl(context_entry_);
}
}
diff --git a/runtime/vm/stub_code.cc b/runtime/vm/stub_code.cc
index 91474a0..8a54e72 100644
--- a/runtime/vm/stub_code.cc
+++ b/runtime/vm/stub_code.cc
@@ -299,8 +299,8 @@
#endif // !defined(DART_PRECOMPILED_RUNTIME)
#if !defined(TARGET_ARCH_IA32)
-CodePtr StubCode::GetBuildMethodExtractorStub(
- compiler::ObjectPoolBuilder* pool) {
+CodePtr StubCode::GetBuildMethodExtractorStub(compiler::ObjectPoolBuilder* pool,
+ bool generic) {
#if !defined(DART_PRECOMPILED_RUNTIME)
auto thread = Thread::Current();
auto Z = thread->zone();
@@ -314,9 +314,10 @@
compiler::ObjectPoolBuilder object_pool_builder;
compiler::Assembler assembler(pool != nullptr ? pool : &object_pool_builder);
compiler::StubCodeCompiler::GenerateBuildMethodExtractorStub(
- &assembler, closure_allocation_stub, context_allocation_stub);
+ &assembler, closure_allocation_stub, context_allocation_stub, generic);
- const char* name = "BuildMethodExtractor";
+ const char* name = generic ? "BuildGenericMethodExtractor"
+ : "BuildNonGenericMethodExtractor";
const Code& stub = Code::Handle(Code::FinalizeCodeAndNotify(
name, nullptr, &assembler, Code::PoolAttachment::kNotAttachPool,
/*optimized=*/false));
@@ -368,7 +369,8 @@
return "_iso_stub_" #name "Stub"; \
}
OBJECT_STORE_STUB_CODE_LIST(MATCH)
- MATCH(build_method_extractor_code, BuildMethodExtractor)
+ MATCH(build_generic_method_extractor_code, BuildGenericMethodExtractor)
+ MATCH(build_nongeneric_method_extractor_code, BuildNonGenericMethodExtractor)
#undef MATCH
return nullptr;
}
diff --git a/runtime/vm/stub_code.h b/runtime/vm/stub_code.h
index ae39cae..3eac0b6 100644
--- a/runtime/vm/stub_code.h
+++ b/runtime/vm/stub_code.h
@@ -21,8 +21,6 @@
class Code;
class Isolate;
class ObjectPointerVisitor;
-class SnapshotReader;
-class SnapshotWriter;
DECLARE_FLAG(bool, disassemble_stubs);
@@ -72,7 +70,14 @@
#endif // !defined(DART_PRECOMPILED_RUNTIME)
#if !defined(TARGET_ARCH_IA32)
- static CodePtr GetBuildMethodExtractorStub(compiler::ObjectPoolBuilder* pool);
+ static CodePtr GetBuildGenericMethodExtractorStub(
+ compiler::ObjectPoolBuilder* pool) {
+ return GetBuildMethodExtractorStub(pool, /*generic=*/true);
+ }
+ static CodePtr GetBuildNonGenericMethodExtractorStub(
+ compiler::ObjectPoolBuilder* pool) {
+ return GetBuildMethodExtractorStub(pool, /*generic=*/false);
+ }
#endif
#if !defined(DART_PRECOMPILED_RUNTIME)
@@ -110,6 +115,9 @@
private:
friend class MegamorphicCacheTable;
+ static CodePtr GetBuildMethodExtractorStub(compiler::ObjectPoolBuilder* pool,
+ bool generic);
+
enum {
#define STUB_CODE_ENTRY(name) k##name##Index,
VM_STUB_CODE_LIST(STUB_CODE_ENTRY)
diff --git a/runtime/vm/symbols.cc b/runtime/vm/symbols.cc
index c6819b0..673f26e 100644
--- a/runtime/vm/symbols.cc
+++ b/runtime/vm/symbols.cc
@@ -14,7 +14,6 @@
#include "vm/object_store.h"
#include "vm/raw_object.h"
#include "vm/reusable_handles.h"
-#include "vm/snapshot_ids.h"
#include "vm/visitor.h"
namespace dart {
@@ -357,7 +356,9 @@
// Most common case: The symbol is already in the table.
{
- SafepointReadRwLocker sl(thread, group->symbols_lock());
+ // We do allow lock-free concurrent read access to the symbol table.
+ // Both, the array in the ObjectStore as well as elements in the array
+ // are accessed via store-release/load-acquire barriers.
data = object_store->symbol_table();
CanonicalStringSet table(&key, &value, &data);
symbol ^= table.GetOrNull(str);
@@ -365,7 +366,7 @@
}
// Otherwise we'll have to get exclusive access and get-or-insert it.
if (symbol.IsNull()) {
- SafepointWriteRwLocker sl(thread, group->symbols_lock());
+ SafepointMutexLocker ml(group->symbols_mutex());
data = object_store->symbol_table();
CanonicalStringSet table(&key, &value, &data);
symbol ^= table.InsertNewOrGet(str);
@@ -403,14 +404,13 @@
// In DEBUG mode the snapshot writer also calls this method inside a
// safepoint.
#if !defined(DEBUG)
- RELEASE_ASSERT(IsolateGroup::AreIsolateGroupsEnabled() || !USING_PRODUCT);
+ RELEASE_ASSERT(FLAG_enable_isolate_groups || !USING_PRODUCT);
#endif
data = object_store->symbol_table();
CanonicalStringSet table(&key, &value, &data);
symbol ^= table.GetOrNull(str);
table.Release();
} else {
- SafepointReadRwLocker sl(thread, group->symbols_lock());
data = object_store->symbol_table();
CanonicalStringSet table(&key, &value, &data);
symbol ^= table.GetOrNull(str);
@@ -513,22 +513,4 @@
table.Release();
}
-intptr_t Symbols::LookupPredefinedSymbol(ObjectPtr obj) {
- for (intptr_t i = 1; i < Symbols::kMaxPredefinedId; i++) {
- if (symbol_handles_[i]->ptr() == obj) {
- return (i + kMaxPredefinedObjectIds);
- }
- }
- return kInvalidIndex;
-}
-
-ObjectPtr Symbols::GetPredefinedSymbol(intptr_t object_id) {
- ASSERT(IsPredefinedSymbolId(object_id));
- intptr_t i = (object_id - kMaxPredefinedObjectIds);
- if ((i > kIllegal) && (i < Symbols::kMaxPredefinedId)) {
- return symbol_handles_[i]->ptr();
- }
- return Object::null();
-}
-
} // namespace dart
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index 533119d..76d0070 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -7,7 +7,6 @@
#include "vm/growable_array.h"
#include "vm/object.h"
-#include "vm/snapshot_ids.h"
namespace dart {
@@ -105,6 +104,7 @@
V(ExceptionHandlers, "ExceptionHandlers") \
V(ExceptionParameter, ":exception") \
V(ExceptionVar, ":exception_var") \
+ V(Expando, "Expando") \
V(ExprTemp, ":expr_temp") \
V(ExternalName, "ExternalName") \
V(ExternalOneByteString, "_ExternalOneByteString") \
@@ -415,6 +415,7 @@
V(_objectNoSuchMethod, "_objectNoSuchMethod") \
V(_objectToString, "_objectToString") \
V(_onData, "_onData") \
+ V(_rehash, "_rehash") \
V(_rehashObjects, "_rehashObjects") \
V(_resultOrListeners, "_resultOrListeners") \
V(_runExtension, "_runExtension") \
@@ -698,13 +699,6 @@
template <typename StringType>
static StringPtr NewSymbol(Thread* thread, const StringType& str);
- static intptr_t LookupPredefinedSymbol(ObjectPtr obj);
- static ObjectPtr GetPredefinedSymbol(intptr_t object_id);
- static bool IsPredefinedSymbolId(intptr_t object_id) {
- return (object_id >= kMaxPredefinedObjectIds &&
- object_id < (kMaxPredefinedObjectIds + kMaxPredefinedId));
- }
-
// List of Latin1 characters stored in the vm isolate as symbols
// in order to make Symbols::FromCharCode fast. This structure is
// used in generated dart code for direct access to these objects.
@@ -715,11 +709,8 @@
friend class Dart;
friend class String;
- friend class SnapshotReader;
- friend class SnapshotWriter;
friend class Serializer;
friend class Deserializer;
- friend class ApiMessageReader;
DISALLOW_COPY_AND_ASSIGN(Symbols);
};
diff --git a/runtime/vm/tagged_pointer.h b/runtime/vm/tagged_pointer.h
index 4f3b1f6..ffd7d32 100644
--- a/runtime/vm/tagged_pointer.h
+++ b/runtime/vm/tagged_pointer.h
@@ -396,6 +396,7 @@
DEFINE_TAGGED_POINTER(GrowableObjectArray, Instance)
DEFINE_TAGGED_POINTER(LinkedHashBase, Instance)
DEFINE_TAGGED_POINTER(LinkedHashMap, LinkedHashBase)
+DEFINE_TAGGED_POINTER(LinkedHashSet, LinkedHashBase)
DEFINE_TAGGED_POINTER(Float32x4, Instance)
DEFINE_TAGGED_POINTER(Int32x4, Instance)
DEFINE_TAGGED_POINTER(Float64x2, Instance)
diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc
index 16a1f8f..09a3b25 100644
--- a/runtime/vm/thread.cc
+++ b/runtime/vm/thread.cc
@@ -91,9 +91,6 @@
no_safepoint_scope_depth_(0),
#endif
reusable_handles_(),
- defer_oob_messages_count_(0),
- deferred_interrupts_mask_(0),
- deferred_interrupts_(0),
stack_overflow_count_(0),
hierarchy_info_(NULL),
type_usage_info_(NULL),
@@ -398,7 +395,7 @@
MonitorLocker ml(&thread_lock_);
if (!HasScheduledInterrupts()) {
// No interrupt pending, set stack_limit_ too.
- stack_limit_ = limit;
+ stack_limit_.store(limit);
}
saved_stack_limit_ = limit;
}
@@ -407,96 +404,40 @@
SetStackLimit(~static_cast<uword>(0));
}
-void Thread::ScheduleInterrupts(uword interrupt_bits) {
- MonitorLocker ml(&thread_lock_);
- ScheduleInterruptsLocked(interrupt_bits);
+static bool IsInterruptLimit(uword limit) {
+ return (limit & ~Thread::kInterruptsMask) ==
+ (kInterruptStackLimit & ~Thread::kInterruptsMask);
}
-void Thread::ScheduleInterruptsLocked(uword interrupt_bits) {
- ASSERT(thread_lock_.IsOwnedByCurrentThread());
+void Thread::ScheduleInterrupts(uword interrupt_bits) {
ASSERT((interrupt_bits & ~kInterruptsMask) == 0); // Must fit in mask.
- // Check to see if any of the requested interrupts should be deferred.
- uword defer_bits = interrupt_bits & deferred_interrupts_mask_;
- if (defer_bits != 0) {
- deferred_interrupts_ |= defer_bits;
- interrupt_bits &= ~deferred_interrupts_mask_;
- if (interrupt_bits == 0) {
- return;
+ uword old_limit = stack_limit_.load();
+ uword new_limit;
+ do {
+ if (IsInterruptLimit(old_limit)) {
+ new_limit = old_limit | interrupt_bits;
+ } else {
+ new_limit = (kInterruptStackLimit & ~kInterruptsMask) | interrupt_bits;
}
- }
-
- if (stack_limit_ == saved_stack_limit_) {
- stack_limit_ = (kInterruptStackLimit & ~kInterruptsMask) | interrupt_bits;
- } else {
- stack_limit_ = stack_limit_ | interrupt_bits;
- }
+ } while (!stack_limit_.compare_exchange_weak(old_limit, new_limit));
}
uword Thread::GetAndClearInterrupts() {
- MonitorLocker ml(&thread_lock_);
- if (stack_limit_ == saved_stack_limit_) {
- return 0; // No interrupt was requested.
- }
- uword interrupt_bits = stack_limit_ & kInterruptsMask;
- stack_limit_ = saved_stack_limit_;
+ uword interrupt_bits = 0;
+ uword old_limit = stack_limit_.load();
+ uword new_limit = saved_stack_limit_;
+ do {
+ if (IsInterruptLimit(old_limit)) {
+ interrupt_bits = interrupt_bits | (old_limit & kInterruptsMask);
+ } else {
+ return interrupt_bits;
+ }
+ } while (!stack_limit_.compare_exchange_weak(old_limit, new_limit));
+
return interrupt_bits;
}
-void Thread::DeferOOBMessageInterrupts() {
- MonitorLocker ml(&thread_lock_);
- defer_oob_messages_count_++;
- if (defer_oob_messages_count_ > 1) {
- // OOB message interrupts are already deferred.
- return;
- }
- ASSERT(deferred_interrupts_mask_ == 0);
- deferred_interrupts_mask_ = kMessageInterrupt;
-
- if (stack_limit_ != saved_stack_limit_) {
- // Defer any interrupts which are currently pending.
- deferred_interrupts_ = stack_limit_ & deferred_interrupts_mask_;
-
- // Clear deferrable interrupts, if present.
- stack_limit_ = stack_limit_ & ~deferred_interrupts_mask_;
-
- if ((stack_limit_ & kInterruptsMask) == 0) {
- // No other pending interrupts. Restore normal stack limit.
- stack_limit_ = saved_stack_limit_;
- }
- }
-#if !defined(PRODUCT)
- if (FLAG_trace_service && FLAG_trace_service_verbose) {
- OS::PrintErr("[+%" Pd64 "ms] Isolate %s deferring OOB interrupts\n",
- Dart::UptimeMillis(), isolate()->name());
- }
-#endif // !defined(PRODUCT)
-}
-
-void Thread::RestoreOOBMessageInterrupts() {
- MonitorLocker ml(&thread_lock_);
- defer_oob_messages_count_--;
- if (defer_oob_messages_count_ > 0) {
- return;
- }
- ASSERT(defer_oob_messages_count_ == 0);
- ASSERT(deferred_interrupts_mask_ == kMessageInterrupt);
- deferred_interrupts_mask_ = 0;
- if (deferred_interrupts_ != 0) {
- if (stack_limit_ == saved_stack_limit_) {
- stack_limit_ = kInterruptStackLimit & ~kInterruptsMask;
- }
- stack_limit_ = stack_limit_ | deferred_interrupts_;
- deferred_interrupts_ = 0;
- }
-#if !defined(PRODUCT)
- if (FLAG_trace_service && FLAG_trace_service_verbose) {
- OS::PrintErr("[+%" Pd64 "ms] Isolate %s restoring OOB interrupts\n",
- Dart::UptimeMillis(), isolate()->name());
- }
-#endif // !defined(PRODUCT)
-}
-
ErrorPtr Thread::HandleInterrupts() {
uword interrupt_bits = GetAndClearInterrupts();
if ((interrupt_bits & kVMInterrupt) != 0) {
@@ -507,6 +448,15 @@
}
heap()->CollectGarbage(Heap::kNew);
}
+
+#if !defined(PRODUCT)
+ // Processes completed SampleBlocks and sends CPU sample events over the
+ // service protocol when applicable.
+ SampleBlockBuffer* sample_buffer = Profiler::sample_block_buffer();
+ if (sample_buffer != nullptr && sample_buffer->process_blocks()) {
+ sample_buffer->ProcessCompletedBlocks();
+ }
+#endif // !defined(PRODUCT)
}
if ((interrupt_bits & kMessageInterrupt) != 0) {
MessageHandler::MessageStatus status =
diff --git a/runtime/vm/thread.h b/runtime/vm/thread.h
index 2d80830..6e3ff67 100644
--- a/runtime/vm/thread.h
+++ b/runtime/vm/thread.h
@@ -417,11 +417,10 @@
};
void ScheduleInterrupts(uword interrupt_bits);
- void ScheduleInterruptsLocked(uword interrupt_bits);
ErrorPtr HandleInterrupts();
uword GetAndClearInterrupts();
bool HasScheduledInterrupts() const {
- return (stack_limit_ & kInterruptsMask) != 0;
+ return (stack_limit_.load() & kInterruptsMask) != 0;
}
// Monitor corresponding to this thread.
@@ -1031,7 +1030,7 @@
// in SIMARM(IA32) and ARM, and the same offsets in SIMARM64(X64) and ARM64.
// We use only word-sized fields to avoid differences in struct packing on the
// different architectures. See also CheckOffsets in dart.cc.
- RelaxedAtomic<uword> stack_limit_;
+ volatile RelaxedAtomic<uword> stack_limit_;
uword write_barrier_mask_;
uword heap_base_;
Isolate* isolate_;
@@ -1107,9 +1106,6 @@
int32_t no_safepoint_scope_depth_;
#endif
VMHandles reusable_handles_;
- intptr_t defer_oob_messages_count_;
- uint16_t deferred_interrupts_mask_;
- uint16_t deferred_interrupts_;
int32_t stack_overflow_count_;
uint32_t runtime_call_count_ = 0;
@@ -1205,9 +1201,6 @@
static void SetCurrent(Thread* current) { OSThread::SetCurrentTLS(current); }
- void DeferOOBMessageInterrupts();
- void RestoreOOBMessageInterrupts();
-
#define REUSABLE_FRIEND_DECLARATION(name) \
friend class Reusable##name##HandleScope;
REUSABLE_HANDLE_LIST(REUSABLE_FRIEND_DECLARATION)
@@ -1218,9 +1211,7 @@
friend class InterruptChecker;
friend class Isolate;
friend class IsolateGroup;
- friend class IsolateTestHelper;
friend class NoActiveIsolateScope;
- friend class NoOOBMessageScope;
friend class NoReloadScope;
friend class Simulator;
friend class StackZone;
diff --git a/runtime/vm/type_testing_stubs.cc b/runtime/vm/type_testing_stubs.cc
index 45d98c8..28b108b 100644
--- a/runtime/vm/type_testing_stubs.cc
+++ b/runtime/vm/type_testing_stubs.cc
@@ -50,7 +50,7 @@
string_ = lib_.url();
curl = OS::SCreate(Z, "%s_", string_.ToCString());
} else {
- static intptr_t counter = 0;
+ static std::atomic<intptr_t> counter = 0;
curl = OS::SCreate(Z, "nolib%" Pd "_", counter++);
}
diff --git a/runtime/vm/v8_snapshot_writer.h b/runtime/vm/v8_snapshot_writer.h
index 644a2e0..c69abdc 100644
--- a/runtime/vm/v8_snapshot_writer.h
+++ b/runtime/vm/v8_snapshot_writer.h
@@ -58,7 +58,8 @@
private:
static constexpr size_t kIdSpaceBits =
Utils::BitLength(static_cast<int64_t>(IdSpace::kArtificial));
- static constexpr int64_t kIdSpaceMask = Utils::NBitMaskUnsafe(kIdSpaceBits);
+ static constexpr int64_t kIdSpaceMask =
+ Utils::NBitMask<int64_t>(kIdSpaceBits);
static const char* IdSpaceToCString(IdSpace space);
int64_t encoded_;
diff --git a/runtime/vm/version_in.cc b/runtime/vm/version_in.cc
index 2fcf5c5..4fe06a5 100644
--- a/runtime/vm/version_in.cc
+++ b/runtime/vm/version_in.cc
@@ -2,23 +2,31 @@
// 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.
-#include "vm/version.h"
+#include "platform/atomic.h"
#include "vm/cpu.h"
#include "vm/os.h"
+#include "vm/version.h"
namespace dart {
-// TODO(iposva): Avoid racy initialization.
-static const char* formatted_version = NULL;
+// We use acquire-release semantics to ensure initializing stores to the string
+// are visible when the string becomes visible.
+static AcqRelAtomic<const char*> formatted_version = nullptr;
const char* Version::String() {
- if (formatted_version == NULL) {
+ if (formatted_version.load() == nullptr) {
const char* os = OS::Name();
const char* arch = CPU::Id();
- formatted_version = OS::SCreate(NULL, "%s on \"%s_%s\"", str_, os, arch);
+ char* version_string =
+ OS::SCreate(nullptr, "%s on \"%s_%s\"", str_, os, arch);
+ const char* expect_old_is_null = nullptr;
+ if (!formatted_version.compare_exchange_strong(expect_old_is_null,
+ version_string)) {
+ free(version_string);
+ }
}
- return formatted_version;
+ return formatted_version.load();
}
const char* Version::SnapshotString() {
diff --git a/runtime/vm/virtual_memory_win.cc b/runtime/vm/virtual_memory_win.cc
index 5348b3c..e352adc 100644
--- a/runtime/vm/virtual_memory_win.cc
+++ b/runtime/vm/virtual_memory_win.cc
@@ -62,10 +62,7 @@
PAGE_READWRITE, nullptr);
if (address == nullptr) {
int error = GetLastError();
- const int kBufferSize = 1024;
- char error_buf[kBufferSize];
- FATAL2("Failed to reserve region for compressed heap: %d (%s)", error,
- Utils::StrError(error, error_buf, kBufferSize));
+ FATAL("Failed to reserve region for compressed heap: %d", error);
}
VirtualMemoryCompressedHeap::Init(address);
}
@@ -74,8 +71,9 @@
void VirtualMemory::Cleanup() {
#if defined(DART_COMPRESSED_POINTERS)
- VirtualFree(VirtualMemoryCompressedHeap::Cleanup(), kCompressedHeapSize,
- MEM_RELEASE);
+ void* heap_base = VirtualMemoryCompressedHeap::GetRegion();
+ VirtualFree(heap_base, kCompressedHeapSize, MEM_RELEASE);
+ VirtualMemoryCompressedHeap::Cleanup();
#endif // defined(DART_COMPRESSED_POINTERS)
}
diff --git a/runtime/vm/vm_sources.gni b/runtime/vm/vm_sources.gni
index 8d6dcb2..2f21ac1 100644
--- a/runtime/vm/vm_sources.gni
+++ b/runtime/vm/vm_sources.gni
@@ -70,7 +70,6 @@
"dart.cc",
"dart.h",
"dart_api_impl.h",
- "dart_api_message.cc",
"dart_api_message.h",
"dart_api_state.cc",
"dart_api_state.h",
@@ -169,6 +168,8 @@
"message.h",
"message_handler.cc",
"message_handler.h",
+ "message_snapshot.cc",
+ "message_snapshot.h",
"metrics.cc",
"metrics.h",
"native_arguments.h",
@@ -186,6 +187,8 @@
"object.h",
"object_graph.cc",
"object_graph.h",
+ "object_graph_copy.cc",
+ "object_graph_copy.h",
"object_id_ring.cc",
"object_id_ring.h",
"object_reload.cc",
@@ -233,7 +236,6 @@
"raw_object.h",
"raw_object_fields.cc",
"raw_object_fields.h",
- "raw_object_snapshot.cc",
"regexp.cc",
"regexp.h",
"regexp_assembler.cc",
@@ -287,7 +289,6 @@
"simulator_arm64.h",
"snapshot.cc",
"snapshot.h",
- "snapshot_ids.h",
"source_report.cc",
"source_report.h",
"stack_frame.cc",
diff --git a/runtime/vm/zone.h b/runtime/vm/zone.h
index 2022c9d..cb45741 100644
--- a/runtime/vm/zone.h
+++ b/runtime/vm/zone.h
@@ -177,6 +177,7 @@
friend class StackZone;
friend class ApiZone;
+ friend class AllocOnlyStackZone;
template <typename T, typename B, typename Allocator>
friend class BaseGrowableArray;
template <typename T, typename B, typename Allocator>
@@ -212,6 +213,23 @@
DISALLOW_IMPLICIT_CONSTRUCTORS(StackZone);
};
+class AllocOnlyStackZone : public ValueObject {
+ public:
+ AllocOnlyStackZone() : zone_() {}
+ ~AllocOnlyStackZone() {
+ // This zone is not linked into the thread, so any handles would not be
+ // visited.
+ ASSERT(zone_.handles()->IsEmpty());
+ }
+
+ Zone* GetZone() { return &zone_; }
+
+ private:
+ Zone zone_;
+
+ DISALLOW_COPY_AND_ASSIGN(AllocOnlyStackZone);
+};
+
inline uword Zone::AllocUnsafe(intptr_t size) {
ASSERT(size >= 0);
// Round up the requested size to fit the alignment.
diff --git a/sdk/lib/_internal/js_dev_runtime/patch/io_patch.dart b/sdk/lib/_internal/js_dev_runtime/patch/io_patch.dart
index 041dfd5..882f10c 100644
--- a/sdk/lib/_internal/js_dev_runtime/patch/io_patch.dart
+++ b/sdk/lib/_internal/js_dev_runtime/patch/io_patch.dart
@@ -364,8 +364,8 @@
Map<String, String>? environment,
bool includeParentEnvironment = true,
bool runInShell = false,
- Encoding stdoutEncoding = systemEncoding,
- Encoding stderrEncoding = systemEncoding}) {
+ Encoding? stdoutEncoding = systemEncoding,
+ Encoding? stderrEncoding = systemEncoding}) {
throw UnsupportedError("Process.run");
}
@@ -375,8 +375,8 @@
Map<String, String>? environment,
bool includeParentEnvironment = true,
bool runInShell = false,
- Encoding stdoutEncoding = systemEncoding,
- Encoding stderrEncoding = systemEncoding}) {
+ Encoding? stdoutEncoding = systemEncoding,
+ Encoding? stderrEncoding = systemEncoding}) {
throw UnsupportedError("Process.runSync");
}
diff --git a/sdk/lib/_internal/js_dev_runtime/patch/js_patch.dart b/sdk/lib/_internal/js_dev_runtime/patch/js_patch.dart
index feb5ef1..033b303 100644
--- a/sdk/lib/_internal/js_dev_runtime/patch/js_patch.dart
+++ b/sdk/lib/_internal/js_dev_runtime/patch/js_patch.dart
@@ -9,6 +9,7 @@
import 'dart:_js_helper' show patch, NoReifyGeneric, Primitives;
import 'dart:_foreign_helper' show JS;
+import 'dart:_interceptors' show JavaScriptObject;
import 'dart:_runtime' as dart;
@patch
@@ -367,7 +368,7 @@
int ms = JS('!', '#.getTime()', o);
return DateTime.fromMillisecondsSinceEpoch(ms);
} else if (o is _DartObject &&
- !identical(dart.getReifiedType(o), dart.jsobject)) {
+ !identical(dart.getReifiedType(o), dart.typeRep<JavaScriptObject>())) {
return o._dartObj;
} else {
return _wrapToDart(o);
diff --git a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart
index 54576b0..33854c7 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart
@@ -85,10 +85,14 @@
gbind(f, @rest List<Object> typeArgs) {
GenericFunctionType type = JS('!', '#[#]', f, _runtimeType);
type.checkBounds(typeArgs);
- // Create a JS wrapper function that will also pass the type arguments, and
- // tag it with the instantiated function type.
+ // Create a JS wrapper function that will also pass the type arguments.
var result =
JS('', '(...args) => #.apply(null, #.concat(args))', f, typeArgs);
+ // Tag the wrapper with the original function to be used for equality checks.
+ JS('', '#["_originalFn"] = #', result, f);
+ JS('', '#["_typeArgs"] = #', result, constList(typeArgs, Object));
+
+ // Tag the wrapper with the instantiated function type.
return fn(result, type.instantiate(typeArgs));
}
diff --git a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/rtti.dart b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/rtti.dart
index 1f362a8..9e99b26 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/rtti.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/rtti.dart
@@ -92,13 +92,13 @@
return JS('', '#.constructor', obj);
}
var result = JS('', '#[#]', obj, _extensionType);
- if (result == null) return JS('', '#', jsobject);
+ if (result == null) return typeRep<JavaScriptObject>();
return result;
case "function":
// All Dart functions and callable classes must set _runtimeType
var result = JS('', '#[#]', obj, _runtimeType);
if (result != null) return result;
- return JS('', '#', jsobject);
+ return typeRep<JavaScriptObject>();
case "undefined":
return JS('', '#', Null);
case "number":
@@ -109,7 +109,7 @@
return JS('', '#', String);
case "symbol":
default:
- return JS('', '#', jsobject);
+ return typeRep<JavaScriptObject>();
}
}
diff --git a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/runtime.dart b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/runtime.dart
index e4afbf4..6ff9de7 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/runtime.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/runtime.dart
@@ -10,7 +10,8 @@
import 'dart:_debugger' show stackTraceMapper, trackCall;
import 'dart:_foreign_helper' show JS, JSExportName, rest, spread;
-import 'dart:_interceptors' show JSArray, jsNull, JSFunction, NativeError;
+import 'dart:_interceptors'
+ show JSArray, jsNull, JSFunction, NativeError, JavaScriptObject;
import 'dart:_internal' as internal show LateError, Symbol;
import 'dart:_js_helper'
show
@@ -180,8 +181,8 @@
/// A list of functions to reset static fields back to their uninitialized
/// state.
///
-/// This is populated by [defineLazyField] and [LazyJSType] and only contains
-/// fields that have been initialized.
+/// This is populated by [defineLazyField] and only contains fields that have
+/// been initialized.
@notNull
final List<void Function()> _resetFields = JS('', '[]');
diff --git a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart
index 7874940..3c0267d 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart
@@ -81,6 +81,15 @@
final metadata = JS('', 'Symbol("metadata")');
+/// A javascript Symbol used to store a canonical version of T? on T.
+final _cachedNullable = JS('', 'Symbol("cachedNullable")');
+
+/// A javascript Symbol used to store a canonical version of T* on T.
+final _cachedLegacy = JS('', 'Symbol("cachedLegacy")');
+
+/// A javascript Symbol used to store prior subtype checks and their results.
+final _subtypeCache = JS('', 'Symbol("_subtypeCache")');
+
/// Types in dart are represented internally at runtime as follows.
///
/// - Normal nominal types, produced from classes, are represented
@@ -154,7 +163,8 @@
}
@notNull
-bool _isJsObject(obj) => JS('!', '# === #', getReifiedType(obj), jsobject);
+bool _isJsObject(obj) =>
+ JS('!', '# === #', getReifiedType(obj), typeRep<JavaScriptObject>());
/// Asserts that [f] is a native JS functions and returns it if so.
///
@@ -196,67 +206,17 @@
return JS('', '#', ret);
}
-/// The Dart type that represents a JavaScript class(/constructor) type.
-///
-/// The JavaScript type may not exist, either because it's not loaded yet, or
-/// because it's not available (such as with mocks). To handle this gracefully,
-/// we disable type checks for in these cases, and allow any JS object to work
-/// as if it were an instance of this JS type.
-class LazyJSType extends DartType {
- Function() _getRawJSTypeFn;
- @notNull
- final String _dartName;
- Object? _rawJSType;
-
- LazyJSType(this._getRawJSTypeFn, this._dartName);
-
- toString() {
- var raw = _getRawJSType();
- return raw != null ? typeName(raw) : "JSObject<$_dartName>";
- }
-
- Object? _getRawJSType() {
- var raw = _rawJSType;
- if (raw != null) return raw;
-
- // Try to evaluate the JS type. If this fails for any reason, we'll try
- // again next time.
- // TODO(jmesserly): is it worth trying again? It may create unnecessary
- // overhead, especially if exceptions are being thrown. Also it means the
- // behavior of a given type check can change later on.
- try {
- raw = _getRawJSTypeFn();
- } catch (e) {}
-
- if (raw == null) {
- _warn('Cannot find native JavaScript type ($_dartName) for type check');
- } else {
- _rawJSType = raw;
- JS('', '#.push(() => # = null)', _resetFields, _rawJSType);
- }
- return raw;
- }
-
- Object rawJSTypeForCheck() => _getRawJSType() ?? jsobject;
-
- @notNull
- @JSExportName('is')
- bool is_T(obj) =>
- obj != null &&
- (_isJsObject(obj) || isSubtypeOf(getReifiedType(obj), this));
-
- @JSExportName('as')
- as_T(obj) => is_T(obj) ? obj : castError(obj, this);
-}
-
-/// An anonymous JS type
+/// Dart type that represents a package:js class type (either anonymous or not).
///
/// For the purposes of subtype checks, these match any JS type.
-class AnonymousJSType extends DartType {
+class PackageJSType extends DartType {
final String _dartName;
- AnonymousJSType(this._dartName);
- toString() => _dartName;
+ PackageJSType(this._dartName);
+ @override
+ String toString() => _dartName;
+
+ @notNull
@JSExportName('is')
bool is_T(obj) =>
obj != null &&
@@ -298,35 +258,25 @@
}
}
-var _lazyJSTypes = JS<Object>('', 'new Map()');
-var _anonymousJSTypes = JS<Object>('', 'new Map()');
+var _packageJSTypes = JS<Object>('', 'new Map()');
-lazyJSType(Function() getJSTypeCallback, String name) {
- var ret = JS('', '#.get(#)', _lazyJSTypes, name);
+packageJSType(String name) {
+ var ret = JS('', '#.get(#)', _packageJSTypes, name);
if (ret == null) {
- ret = LazyJSType(getJSTypeCallback, name);
- JS('', '#.set(#, #)', _lazyJSTypes, name, ret);
+ ret = PackageJSType(name);
+ JS('', '#.set(#, #)', _packageJSTypes, name, ret);
}
return ret;
}
-anonymousJSType(String name) {
- var ret = JS('', '#.get(#)', _anonymousJSTypes, name);
- if (ret == null) {
- ret = AnonymousJSType(name);
- JS('', '#.set(#, #)', _anonymousJSTypes, name, ret);
- }
- return ret;
-}
-
-/// A javascript Symbol used to store a canonical version of T? on T.
-final _cachedNullable = JS('', 'Symbol("cachedNullable")');
-
-/// A javascript Symbol used to store a canonical version of T* on T.
-final _cachedLegacy = JS('', 'Symbol("cachedLegacy")');
-
-/// A javascript Symbol used to store prior subtype checks and their results.
-final _subtypeCache = JS('', 'Symbol("_subtypeCache")');
+/// Since package:js types are all subtypes of each other, we use this var to
+/// denote *some* package:js type in our subtyping logic.
+///
+/// Used only when a concrete PackageJSType is not available i.e. when neither
+/// the object nor the target type is a PackageJSType. Avoids initializating a
+/// new PackageJSType every time. Note that we don't add it to the set of JS
+/// types, since it's not an actual JS class.
+final _pkgJSTypeForSubtyping = PackageJSType('');
/// Returns a nullable (question, ?) version of [type].
///
@@ -478,12 +428,6 @@
final bottom = unwrapType(Null);
-class JSObjectType extends DartType {
- toString() => 'NativeJavaScriptObject';
-}
-
-final jsobject = JSObjectType();
-
/// Dev Compiler's implementation of Type, wrapping its internal [_type].
class _Type extends Type {
/// The internal type representation, either a [DartType] or class constructor
@@ -1518,8 +1462,29 @@
return ${_equalType(t2, Function)};
}
- // All JS types are subtypes of anonymous JS types.
- if ($t1 === $jsobject && ${_jsInstanceOf(t2, AnonymousJSType)}) {
+ // Even though lazy and anonymous JS types are natural subtypes of
+ // JavaScriptObject, JS types should be treated as mutual subtypes of each
+ // other. This allows users to be able to interface with both extension
+ // types on JavaScriptObject and package:js using the same object.
+ //
+ // Therefore, the following relationships hold true:
+ //
+ // JavaScriptObject <: package:js types
+ // package:js types <: JavaScriptObject
+
+ if (${_isInterfaceSubtype(t1, JavaScriptObject, strictMode)}
+ &&
+ // TODO: Since package:js types are instances of PackageJSType and
+ // we don't have a mechanism to determine if *some* package:js type
+ // implements t2. This will possibly require keeping a map of these
+ // relationships for this subtyping check. For now, this will only
+ // work if t2 is also a PackageJSType.
+ ${_isInterfaceSubtype(_pkgJSTypeForSubtyping, t2, strictMode)}) {
+ return true;
+ }
+
+ if (${_isInterfaceSubtype(JavaScriptObject, t2, strictMode)}
+ && ${_isInterfaceSubtype(t1, _pkgJSTypeForSubtyping, strictMode)}) {
return true;
}
@@ -1587,10 +1552,11 @@
})()''');
bool _isInterfaceSubtype(t1, t2, @notNull bool strictMode) => JS('', '''(() => {
- // If we have lazy JS types, unwrap them. This will effectively
- // reduce to a prototype check below.
- if (${_jsInstanceOf(t1, LazyJSType)}) $t1 = $t1.rawJSTypeForCheck();
- if (${_jsInstanceOf(t2, LazyJSType)}) $t2 = $t2.rawJSTypeForCheck();
+ // Instances of PackageJSType are all subtypes of each other.
+ if (${_jsInstanceOf(t1, PackageJSType)}
+ && ${_jsInstanceOf(t2, PackageJSType)}) {
+ return true;
+ }
if ($t1 === $t2) {
return true;
diff --git a/sdk/lib/_internal/js_dev_runtime/private/interceptors.dart b/sdk/lib/_internal/js_dev_runtime/private/interceptors.dart
index 71c559c..fdc771d 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/interceptors.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/interceptors.dart
@@ -74,45 +74,40 @@
operator []=(int index, E value);
}
-/**
- * The interface implemented by JavaScript objects. These are methods in
- * addition to the regular Dart Object methods like [Object.hashCode].
- *
- * This is the type that should be exported by a JavaScript interop library.
- */
+/// The interface implemented by JavaScript objects.
+///
+/// These are methods in addition to the regular Dart Object methods like
+/// [Object.hashCode]. This is the type that should be exported by a JavaScript
+/// interop library.
abstract class JSObject {}
-/**
- * Interceptor base class for JavaScript objects not recognized as some more
- * specific native type.
- */
+/// Interceptor base class for JavaScript objects not recognized as some more
+/// specific native type.
+
+/// Unlike dart2js, ddc does not intercept JS objects, so this is only used as
+/// an on-type for JS interop extension types. All JS interop objects should be
+/// castable to this type.
abstract class JavaScriptObject extends Interceptor implements JSObject {
const JavaScriptObject();
-
- // It would be impolite to stash a property on the object.
- int get hashCode => 0;
-
- Type get runtimeType => JSObject;
}
-/**
- * Interceptor for plain JavaScript objects created as JavaScript object
- * literals or `new Object()`.
- */
+/// Interceptor for plain JavaScript objects created as JavaScript object
+/// literals or `new Object()`.
+///
+/// Note that this isn't being used today in ddc. Instead of using interceptors,
+/// we have other type logic to distinguish JS types.
class PlainJavaScriptObject extends JavaScriptObject {
const PlainJavaScriptObject();
}
-/**
- * Interceptor for unclassified JavaScript objects, typically objects with a
- * non-trivial prototype chain.
- *
- * This class also serves as a fallback for unknown JavaScript exceptions.
- */
+/// Interceptor for unclassified JavaScript objects, typically objects with a
+/// non-trivial prototype chain.
+///
+/// This class also serves as a fallback for unknown JavaScript exceptions.
+/// Note that this isn't being used today in ddc. Instead of using interceptors,
+/// we have other type logic to distinguish JS types.
class UnknownJavaScriptObject extends JavaScriptObject {
const UnknownJavaScriptObject();
-
- String toString() => JS<String>('!', 'String(#)', this);
}
class NativeError extends Interceptor {
diff --git a/sdk/lib/_internal/js_runtime/lib/constant_map.dart b/sdk/lib/_internal/js_runtime/lib/constant_map.dart
index d5a5174..669a7e8 100644
--- a/sdk/lib/_internal/js_runtime/lib/constant_map.dart
+++ b/sdk/lib/_internal/js_runtime/lib/constant_map.dart
@@ -12,37 +12,24 @@
abstract class ConstantMap<K, V> implements Map<K, V> {
// Used to create unmodifiable maps from other maps.
factory ConstantMap.from(Map other) {
- var keys = new List<K>.from(other.keys);
+ final keys = List<K>.from(other.keys);
bool allStrings = true;
for (var k in keys) {
- if (k is! String) {
+ if (k is! String || '__proto__' == k) {
allStrings = false;
break;
}
}
if (allStrings) {
- bool containsProto = false;
- var protoValue = null;
var object = JS('=Object', '{}');
- int length = 0;
- for (var k in keys) {
+ for (final k in keys) {
V v = other[k];
- if (k != '__proto__') {
- if (!jsHasOwnProperty(object, k as String)) length++;
- JS('void', '#[#] = #', object, k, v);
- } else {
- containsProto = true;
- protoValue = v;
- }
+ JS('void', '#[#] = #', object, k, v);
}
- if (containsProto) {
- length++;
- return new ConstantProtoMap<K, V>._(length, object, keys, protoValue);
- }
- return new ConstantStringMap<K, V>._(length, object, keys);
+ return ConstantStringMap<K, V>._(keys.length, object, keys);
}
// TODO(lrn): Make a proper unmodifiable map implementation.
- return new ConstantMapView<K, V>(new Map.from(other));
+ return ConstantMapView<K, V>(Map.from(other));
}
const ConstantMap._();
@@ -55,7 +42,7 @@
String toString() => MapBase.mapToString(this);
static Never _throwUnmodifiable() {
- throw new UnsupportedError('Cannot modify unmodifiable Map');
+ throw UnsupportedError('Cannot modify unmodifiable Map');
}
void operator []=(K key, V val) {
@@ -70,14 +57,19 @@
_throwUnmodifiable();
}
- void clear() => _throwUnmodifiable();
- void addAll(Map<K, V> other) => _throwUnmodifiable();
+ void clear() {
+ _throwUnmodifiable();
+ }
+
+ void addAll(Map<K, V> other) {
+ _throwUnmodifiable();
+ }
Iterable<MapEntry<K, V>> get entries sync* {
// `this[key]` has static type `V?` but is always `V`. Rather than `as V`,
// we use `as dynamic` so the upcast requires no checking and the implicit
// downcast to `V` will be discarded in production.
- for (var key in keys) yield new MapEntry<K, V>(key, this[key] as dynamic);
+ for (var key in keys) yield MapEntry<K, V>(key, this[key] as dynamic);
}
void addEntries(Iterable<MapEntry<K, V>> entries) {
@@ -151,32 +143,14 @@
}
Iterable<K> get keys {
- return new _ConstantMapKeyIterable<K>(this);
+ return _ConstantMapKeyIterable<K>(this);
}
Iterable<V> get values {
- return new MappedIterable<K, V>(_keysArray, (key) => _fetch(key));
+ return MappedIterable<K, V>(_keysArray, (key) => _fetch(key));
}
}
-class ConstantProtoMap<K, V> extends ConstantStringMap<K, V> {
- // This constructor is not used. The instantiation is shortcut by the
- // compiler. It is here to make the uninitialized final fields legal.
- ConstantProtoMap._(length, jsObject, keys, this._protoValue)
- : super._(length, jsObject, keys);
-
- final V _protoValue;
-
- bool containsKey(Object? key) {
- if (key is! String) return false;
- if ('__proto__' == key) return true;
- return jsHasOwnProperty(_jsObject, key);
- }
-
- _fetch(key) =>
- '__proto__' == key ? _protoValue : jsPropertyAccess(_jsObject, key);
-}
-
class _ConstantMapKeyIterable<K> extends Iterable<K> {
ConstantStringMap<K, dynamic> _map;
_ConstantMapKeyIterable(this._map);
@@ -199,13 +173,35 @@
Map<K, V> _getMap() {
LinkedHashMap<K, V>? backingMap = JS('LinkedHashMap|Null', r'#.$map', this);
if (backingMap == null) {
- backingMap = new JsLinkedHashMap<K, V>();
+ backingMap = LinkedHashMap<K, V>(
+ hashCode: _constantMapHashCode,
+ // In legacy mode (--no-sound-null-safety), `null` keys are
+ // permitted. In sound mode, `null` keys are permitted only if [K] is
+ // nullable.
+ isValidKey: JS_GET_FLAG('LEGACY') ? _typeTest<K?>() : _typeTest<K>());
fillLiteralMap(_jsData, backingMap);
JS('', r'#.$map = #', this, backingMap);
}
return backingMap;
}
+ static int _constantMapHashCode(Object? key) {
+ // Types are tested here one-by-one so that each call to get:hashCode can be
+ // resolved differently.
+
+ // Some common primitives in a GeneralConstantMap.
+ if (key is num) return key.hashCode; // One method on JSNumber.
+
+ // Specially handled known types.
+ if (key is Symbol) return key.hashCode;
+ if (key is Type) return key.hashCode;
+
+ // Everything else, including less common primitives.
+ return identityHashCode(key);
+ }
+
+ static bool Function(Object?) _typeTest<T>() => (Object? o) => o is T;
+
bool containsValue(Object? needle) {
return _getMap().containsValue(needle);
}
diff --git a/sdk/lib/_internal/js_runtime/lib/io_patch.dart b/sdk/lib/_internal/js_runtime/lib/io_patch.dart
index 77a2530..2ee566b 100644
--- a/sdk/lib/_internal/js_runtime/lib/io_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/io_patch.dart
@@ -364,8 +364,8 @@
Map<String, String>? environment,
bool includeParentEnvironment: true,
bool runInShell: false,
- Encoding stdoutEncoding: systemEncoding,
- Encoding stderrEncoding: systemEncoding}) {
+ Encoding? stdoutEncoding: systemEncoding,
+ Encoding? stderrEncoding: systemEncoding}) {
throw new UnsupportedError("Process.run");
}
@@ -375,8 +375,8 @@
Map<String, String>? environment,
bool includeParentEnvironment: true,
bool runInShell: false,
- Encoding stdoutEncoding: systemEncoding,
- Encoding stderrEncoding: systemEncoding}) {
+ Encoding? stdoutEncoding: systemEncoding,
+ Encoding? stderrEncoding: systemEncoding}) {
throw new UnsupportedError("Process.runSync");
}
diff --git a/sdk/lib/_internal/vm/bin/socket_patch.dart b/sdk/lib/_internal/vm/bin/socket_patch.dart
index f04ffbb..ad83f7b 100644
--- a/sdk/lib/_internal/vm/bin/socket_patch.dart
+++ b/sdk/lib/_internal/vm/bin/socket_patch.dart
@@ -1489,7 +1489,8 @@
InternetAddress addr, NetworkInterface? interface) {
// On Mac OS using the interface index for joining IPv4 multicast groups
// is not supported. Here the IP address of the interface is needed.
- if (Platform.isMacOS && addr.type == InternetAddressType.IPv4) {
+ if ((Platform.isMacOS || Platform.isIOS) &&
+ addr.type == InternetAddressType.IPv4) {
if (interface != null) {
for (int i = 0; i < interface.addresses.length; i++) {
if (interface.addresses[i].type == InternetAddressType.IPv4) {
diff --git a/sdk/lib/_internal/vm/lib/bigint_patch.dart b/sdk/lib/_internal/vm/lib/bigint_patch.dart
index dd627df..f040c45 100644
--- a/sdk/lib/_internal/vm/lib/bigint_patch.dart
+++ b/sdk/lib/_internal/vm/lib/bigint_patch.dart
@@ -1657,8 +1657,9 @@
*/
int get bitLength {
if (_used == 0) return 0;
- if (_isNegative) return (~this).bitLength;
- return _digitBits * (_used - 1) + _digits[_used - 1].bitLength;
+ var highBits = _digits[_used - 1];
+ if (_isNegative) highBits -= 1;
+ return _digitBits * (_used - 1) + highBits.bitLength;
}
/**
diff --git a/sdk/lib/_internal/vm/lib/compact_hash.dart b/sdk/lib/_internal/vm/lib/compact_hash.dart
index 492e9bd..dc552c7 100644
--- a/sdk/lib/_internal/vm/lib/compact_hash.dart
+++ b/sdk/lib/_internal/vm/lib/compact_hash.dart
@@ -490,18 +490,14 @@
E get current => _current as E;
}
-// Set implementation, analogous to _CompactLinkedHashMap.
-@pragma('vm:entry-point')
-class _CompactLinkedHashSet<E> extends _HashFieldBase
- with _HashBase, _OperatorEqualsAndHashCode, SetMixin<E>
- implements LinkedHashSet<E> {
- _CompactLinkedHashSet() : super(_HashBase._INITIAL_INDEX_SIZE >> 1) {
- assert(_HashBase._UNUSED_PAIR == 0);
- }
+abstract class _LinkedHashSetMixin<E> implements _HashBase {
+ int _hashCode(e);
+ bool _equals(e1, e2);
+ int get _checkSum;
+ bool _isModifiedSince(List oldData, int oldCheckSum);
- static Set<R> _newEmpty<R>() => new _CompactLinkedHashSet<R>();
-
- Set<R> cast<R>() => Set.castFrom<E, R>(this, newSet: _newEmpty);
+ bool get isEmpty => length == 0;
+ bool get isNotEmpty => !isEmpty;
int get length => _usedData - _deletedKeys;
E get first {
@@ -650,19 +646,51 @@
Iterator<E> get iterator =>
new _CompactIterator<E>(this, _data, _usedData, -1, 1);
- // Returns a set of the same type, although this
- // is not required by the spec. (For instance, always using an identity set
- // would be technically correct, albeit surprising.)
- Set<E> toSet() => new _CompactLinkedHashSet<E>()..addAll(this);
-
// This method is called by [_rehashObjects] (see above).
void _regenerateIndex() {
+ _index = _data.length == 0 ? _initialIndex : new Uint32List(_data.length);
+ assert(_hashMask == 0);
+ _hashMask = _HashBase._indexSizeToHashMask(_index.length);
_rehash();
}
}
-class _CompactLinkedIdentityHashSet<E> extends _CompactLinkedHashSet<E>
- with _IdenticalAndIdentityHashCode {
+// Set implementation, analogous to _CompactLinkedHashMap.
+@pragma('vm:entry-point')
+class _CompactLinkedHashSet<E> extends _HashVMBase
+ with
+ SetMixin<E>,
+ _LinkedHashSetMixin<E>,
+ _HashBase,
+ _OperatorEqualsAndHashCode
+ implements LinkedHashSet<E> {
+ _CompactLinkedHashSet() {
+ _index = _initialIndex;
+ _hashMask = 0;
+ _data = _initialData;
+ _usedData = 0;
+ _deletedKeys = 0;
+ }
+
+ Set<R> cast<R>() => Set.castFrom<E, R>(this, newSet: _newEmpty);
+
+ static Set<R> _newEmpty<R>() => new _CompactLinkedHashSet<R>();
+
+ // Returns a set of the same type, although this
+ // is not required by the spec. (For instance, always using an identity set
+ // would be technically correct, albeit surprising.)
+ Set<E> toSet() => new _CompactLinkedHashSet<E>()..addAll(this);
+}
+
+class _CompactLinkedIdentityHashSet<E> extends _HashFieldBase
+ with
+ SetMixin<E>,
+ _LinkedHashSetMixin<E>,
+ _HashBase,
+ _IdenticalAndIdentityHashCode
+ implements LinkedHashSet<E> {
+ _CompactLinkedIdentityHashSet() : super(_HashBase._INITIAL_INDEX_SIZE);
+
Set<E> toSet() => new _CompactLinkedIdentityHashSet<E>()..addAll(this);
static Set<R> _newEmpty<R>() => new _CompactLinkedIdentityHashSet<R>();
@@ -670,7 +698,9 @@
Set<R> cast<R>() => Set.castFrom<E, R>(this, newSet: _newEmpty);
}
-class _CompactLinkedCustomHashSet<E> extends _CompactLinkedHashSet<E> {
+class _CompactLinkedCustomHashSet<E> extends _HashFieldBase
+ with SetMixin<E>, _LinkedHashSetMixin<E>, _HashBase
+ implements LinkedHashSet<E> {
final _equality;
final _hasher;
final _validKey;
@@ -683,7 +713,8 @@
bool remove(Object? o) => _validKey(o) ? super.remove(o) : false;
_CompactLinkedCustomHashSet(this._equality, this._hasher, validKey)
- : _validKey = (validKey != null) ? validKey : new _TypeTest<E>().test;
+ : _validKey = (validKey != null) ? validKey : new _TypeTest<E>().test,
+ super(_HashBase._INITIAL_INDEX_SIZE);
Set<R> cast<R>() => Set.castFrom<E, R>(this);
Set<E> toSet() =>
diff --git a/sdk/lib/_internal/vm/lib/expando_patch.dart b/sdk/lib/_internal/vm/lib/expando_patch.dart
index cacbc02..36c65df 100644
--- a/sdk/lib/_internal/vm/lib/expando_patch.dart
+++ b/sdk/lib/_internal/vm/lib/expando_patch.dart
@@ -5,11 +5,12 @@
// part of "core_patch.dart";
@patch
+@pragma("vm:entry-point")
class Expando<T> {
@patch
Expando([String? name])
: name = name,
- _data = new List.filled(_minSize, null),
+ _data = new List<_WeakProperty?>.filled(_minSize, null),
_used = 0;
static const _minSize = 8;
@@ -95,6 +96,7 @@
this[object] = value; // Recursively add the value.
}
+ @pragma("vm:entry-point", "call")
_rehash() {
// Determine the population count of the map to allocate an appropriately
// sized map below.
@@ -119,7 +121,7 @@
// Reset the mappings to empty so that we can just add the existing
// valid entries.
- _data = new List.filled(new_size, null);
+ _data = new List<_WeakProperty?>.filled(new_size, null);
_used = 0;
for (var i = 0; i < old_data.length; i++) {
@@ -149,9 +151,9 @@
}
}
- get _size => _data.length;
- get _limit => (3 * (_size ~/ 4));
+ int get _size => _data.length;
+ int get _limit => (3 * (_size ~/ 4));
- List _data;
+ List<_WeakProperty?> _data;
int _used; // Number of used (active and deleted) slots.
}
diff --git a/sdk/lib/_internal/vm/lib/internal_patch.dart b/sdk/lib/_internal/vm/lib/internal_patch.dart
index 6cc2388..67501fb 100644
--- a/sdk/lib/_internal/vm/lib/internal_patch.dart
+++ b/sdk/lib/_internal/vm/lib/internal_patch.dart
@@ -193,6 +193,9 @@
abstract class VMInternalsForTesting {
// This function can be used by tests to enforce garbage collection.
static void collectAllGarbage() native "Internal_collectAllGarbage";
+
+ static void deoptimizeFunctionsOnStack()
+ native "Internal_deoptimizeFunctionsOnStack";
}
@patch
diff --git a/sdk/lib/_internal/vm/lib/isolate_patch.dart b/sdk/lib/_internal/vm/lib/isolate_patch.dart
index 34ce5e4..9703179 100644
--- a/sdk/lib/_internal/vm/lib/isolate_patch.dart
+++ b/sdk/lib/_internal/vm/lib/isolate_patch.dart
@@ -160,8 +160,8 @@
}
/**** Internal implementation details ****/
- _get_id() native "RawReceivePortImpl_get_id";
- _get_sendport() native "RawReceivePortImpl_get_sendport";
+ int _get_id() native "RawReceivePortImpl_get_id";
+ SendPort _get_sendport() native "RawReceivePortImpl_get_sendport";
// Called from the VM to retrieve the handler for a message.
@pragma("vm:entry-point", "call")
@@ -186,7 +186,7 @@
}
// Call into the VM to close the VM maintained mappings.
- _closeInternal() native "RawReceivePortImpl_closeInternal";
+ int _closeInternal() native "RawReceivePortImpl_closeInternal";
// Set this port as active or inactive in the VM. If inactive, this port
// will not be considered live even if it hasn't been explicitly closed.
@@ -195,7 +195,7 @@
_setActive(bool active) native "RawReceivePortImpl_setActive";
void set handler(Function? value) {
- final id = this._get_id();
+ final int id = this._get_id();
if (!_portMap.containsKey(id)) {
_portMap[id] = <String, dynamic>{
'port': this,
@@ -204,7 +204,7 @@
_portMap[id]!['handler'] = value;
}
- static final _portMap = <dynamic, Map<String, dynamic>>{};
+ static final _portMap = <int, Map<String, dynamic>>{};
}
@pragma("vm:entry-point")
diff --git a/sdk/lib/_internal/vm/lib/symbol_patch.dart b/sdk/lib/_internal/vm/lib/symbol_patch.dart
index 06eb588..eeb9e0b 100644
--- a/sdk/lib/_internal/vm/lib/symbol_patch.dart
+++ b/sdk/lib/_internal/vm/lib/symbol_patch.dart
@@ -6,6 +6,7 @@
@patch
class Symbol {
+ // TODO(http://dartbug.com/46716): Recognize Symbol in the VM.
@patch
const Symbol(String name) : this._name = name;
@@ -52,6 +53,7 @@
return result.toString();
}
+ // Must be kept in sync with Symbol::CanonicalizeHash in object.cc.
@patch
int get hashCode {
const arbitraryPrime = 664597;
diff --git a/sdk/lib/async/future.dart b/sdk/lib/async/future.dart
index 2952ad3..555bc3d 100644
--- a/sdk/lib/async/future.dart
+++ b/sdk/lib/async/future.dart
@@ -719,7 +719,7 @@
/// are *expected* to complete with a value.
/// You can use [FutureExtensions.ignore] if you also don't want to know
/// about errors from this future.
-@Since("2.15")
+@Since("2.14")
void unawaited(Future<void> future) {}
/// Convenience methods on futures.
@@ -809,7 +809,7 @@
/// If you merely want to silence the ["unawaited futures" lint](https://dart-lang.github.io/linter/lints/unawaited_futures.html),
/// use the [unawaited] function instead.
/// That will ensure that an unexpected error is still reported.
- @Since("2.15")
+ @Since("2.14")
void ignore() {
var self = this;
if (self is _Future<T>) {
diff --git a/sdk/lib/async/stream.dart b/sdk/lib/async/stream.dart
index d03e095..262b847 100644
--- a/sdk/lib/async/stream.dart
+++ b/sdk/lib/async/stream.dart
@@ -1479,13 +1479,20 @@
/// Creates a new stream with the same events as this stream.
///
- /// Whenever more than [timeLimit] passes between two events from this stream,
- /// the [onTimeout] function is called, which can emit further events on
+ /// When someone is listening on the returned stream and more than
+ /// [timeLimit] passes without any event being emitted by this stream,
+ /// the [onTimeout] function is called, which can then emit further events on
/// the returned stream.
///
- /// The countdown doesn't start until the returned stream is listened to.
- /// The countdown is reset every time an event is forwarded from this stream,
- /// or when this stream is paused and resumed.
+ /// The countdown starts when the returned stream is listened to,
+ /// and is restarted when an event from the this stream is emitted,
+ /// or when listening on the returned stream is paused and resumed.
+ /// The countdown is stopped when listening on the returned stream is
+ /// paused or cancelled.
+ /// No new countdown is started when a countdown completes
+ /// and the [onTimeout] function is called, even if events are emitted.
+ /// If the delay between events of this stream is multiple times
+ /// [timeLimit], at most one timeout will happen between events.
///
/// The [onTimeout] function is called with one argument: an
/// [EventSink] that allows putting events into the returned stream.
@@ -1493,10 +1500,10 @@
/// Calling [EventSink.close] on the sink passed to [onTimeout] closes the
/// returned stream, and no further events are processed.
///
- /// If [onTimeout] is omitted, a timeout will just put a [TimeoutException]
+ /// If [onTimeout] is omitted, a timeout will emit a [TimeoutException]
/// into the error channel of the returned stream.
- /// If the call to [onTimeout] throws, the error is emitted on the returned
- /// stream.
+ /// If the call to [onTimeout] throws, the error is emitted as an error
+ /// on the returned stream.
///
/// The returned stream is a broadcast stream if this stream is.
/// If a broadcast stream is listened to more than once, each subscription
@@ -1519,8 +1526,6 @@
new TimeoutException("No stream event", timeLimit), null);
};
} else {
- // TODO(floitsch): the return type should be 'void', and the type
- // should be inferred.
var registeredOnTimeout =
zone.registerUnaryCallback<void, EventSink<T>>(onTimeout);
var wrapper = new _ControllerEventSinkWrapper<T>(null);
diff --git a/sdk/lib/collection/queue.dart b/sdk/lib/collection/queue.dart
index 97252ba56..fb48484 100644
--- a/sdk/lib/collection/queue.dart
+++ b/sdk/lib/collection/queue.dart
@@ -52,6 +52,11 @@
/// and if all elements stored into the returned queue are actually instance
/// of [S],
/// then the returned queue can be used as a `Queue<T>`.
+ ///
+ /// Methods like [contains] and [remove]
+ /// which accept one `Object?` as argument,
+ /// will pass the argument directly to the this queue's method
+ /// without any checks.
static Queue<T> castFrom<S, T>(Queue<S> source) => CastQueue<S, T>(source);
/// Provides a view of this queue as a queue of [R] instances, if necessary.
@@ -64,6 +69,13 @@
/// must be instance of [R] to be valid arguments to the adding function,
/// and they must be instances of [E] as well to be accepted by
/// this queue as well.
+ ///
+ /// Methods like [contains] and [remove]
+ /// which accept one `Object?` as argument,
+ /// will pass the argument directly to the this queue's method
+ /// without any checks.
+ /// That means that you can do `queueOfStrings.cast<int>().remove("a")`
+ /// successfully, even if it looks like it shouldn't have any effect.
Queue<R> cast<R>();
/// Removes and returns the first element of this queue.
@@ -304,6 +316,7 @@
DoubleLinkedQueue<E>()..addAll(elements);
Queue<R> cast<R>() => Queue.castFrom<E, R>(this);
+
int get length => _elementCount;
void addLast(E value) {
diff --git a/sdk/lib/core/list.dart b/sdk/lib/core/list.dart
index 42db5d5..6c17632 100644
--- a/sdk/lib/core/list.dart
+++ b/sdk/lib/core/list.dart
@@ -187,6 +187,11 @@
/// and if all elements stored into the returned list are actually instance
/// of [S],
/// then the returned list can be used as a `List<T>`.
+ ///
+ /// Methods like [contains] and [remove]
+ /// which accept `Object?` as argument
+ /// will pass the argument directly to the this list's method
+ /// without any checks.
static List<T> castFrom<S, T>(List<S> source) => CastList<S, T>(source);
/// Copy a range of one list into another list.
@@ -254,7 +259,7 @@
/// Returns a view of this list as a list of [R] instances.
///
/// If this list contains only instances of [R], all read operations
- /// will work correctly. If any operation tries to access an element
+ /// will work correctly. If any operation tries to read an element
/// that is not an instance of [R], the access will throw instead.
///
/// Elements added to the list (e.g., by using [add] or [addAll])
@@ -262,6 +267,13 @@
/// and they must be instances of [E] as well to be accepted by
/// this list as well.
///
+ /// Methods like [contains] and [remove]
+ /// which accept `Object?` as argument
+ /// will pass the argument directly to the this list's method
+ /// without any checks.
+ /// That means that you can do `listOfStrings.cast<int>().remove("a")`
+ /// successfully, even if it looks like it shouldn't have any effect.
+ ///
/// Typically implemented as `List.castFrom<E, R>(this)`.
List<R> cast<R>();
diff --git a/sdk/lib/core/map.dart b/sdk/lib/core/map.dart
index 17590cc..f6d36b1 100644
--- a/sdk/lib/core/map.dart
+++ b/sdk/lib/core/map.dart
@@ -163,6 +163,11 @@
/// If all accessed entries of [source] are have [K2] keys and [V2] values
/// and if all entries added to the returned map have [K] keys and [V]] values,
/// then the returned map can be used as a `Map<K2, V2>`.
+ ///
+ /// Methods like [containsKey], [remove] and [operator[]]
+ /// which accept `Object?` as argument
+ /// will pass the argument directly to the this map's method
+ /// without any checks.
static Map<K2, V2> castFrom<K, V, K2, V2>(Map<K, V> source) =>
CastMap<K, V, K2, V2>(source);
@@ -193,6 +198,13 @@
///
/// Entries added to the map must be valid for both a `Map<K, V>` and a
/// `Map<RK, RV>`.
+ ///
+ /// Methods like [containsKey], [remove] and [operator[]]
+ /// which accept `Object?` as argument
+ /// will pass the argument directly to the this map's method
+ /// without any checks.
+ /// That means that you can do `mapWithStringKeys.cast<int,int>().remove("a")`
+ /// successfully, even if it looks like it shouldn't have any effect.
Map<RK, RV> cast<RK, RV>();
/// Whether this map contains the given [value].
diff --git a/sdk/lib/core/set.dart b/sdk/lib/core/set.dart
index eb86364..b19ed8e 100644
--- a/sdk/lib/core/set.dart
+++ b/sdk/lib/core/set.dart
@@ -106,6 +106,11 @@
/// and if all elements added to the returned set are actually instance
/// of [S],
/// then the returned set can be used as a `Set<T>`.
+ ///
+ /// Methods like [contains], [remove] and [removeAll]
+ /// which accept one or more `Object?` as argument,
+ /// will pass the argument directly to the this set's method
+ /// without any checks.
static Set<T> castFrom<S, T>(Set<S> source, {Set<R> Function<R>()? newSet}) =>
CastSet<S, T>(source, newSet);
@@ -119,6 +124,13 @@
/// must be instance of [R] to be valid arguments to the adding function,
/// and they must be instances of [E] as well to be accepted by
/// this set as well.
+ ///
+ /// Methods like [contains], [remove] and [removeAll]
+ /// which accept one or more `Object?` as argument,
+ /// will pass the argument directly to the this set's method
+ /// without any checks.
+ /// That means that you can do `setOfStrings.cast<int>().remove("a")`
+ /// successfully, even if it looks like it shouldn't have any effect.
Set<R> cast<R>();
/// An iterator that iterates over the elements of this set.
diff --git a/sdk/lib/developer/service.dart b/sdk/lib/developer/service.dart
index 8715d25..9d6fe098 100644
--- a/sdk/lib/developer/service.dart
+++ b/sdk/lib/developer/service.dart
@@ -63,12 +63,13 @@
// Port to receive response from service isolate.
final RawReceivePort receivePort =
new RawReceivePort(null, 'Service.getInfo');
- final Completer<Uri?> uriCompleter = new Completer<Uri?>();
- receivePort.handler = (Uri? uri) => uriCompleter.complete(uri);
+ final Completer<String?> completer = new Completer<String?>();
+ receivePort.handler = (String? uriString) => completer.complete(uriString);
// Request the information from the service isolate.
_getServerInfo(receivePort.sendPort);
// Await the response from the service isolate.
- Uri? uri = await uriCompleter.future;
+ String? uriString = await completer.future;
+ Uri? uri = uriString == null ? null : Uri.parse(uriString);
// Close the port.
receivePort.close();
return new ServiceProtocolInfo(uri);
@@ -85,12 +86,13 @@
// Port to receive response from service isolate.
final RawReceivePort receivePort =
new RawReceivePort(null, 'Service.controlWebServer');
- final Completer<Uri> uriCompleter = new Completer<Uri>();
- receivePort.handler = (Uri uri) => uriCompleter.complete(uri);
+ final Completer<String?> completer = new Completer<String?>();
+ receivePort.handler = (String? uriString) => completer.complete(uriString);
// Request the information from the service isolate.
_webServerControl(receivePort.sendPort, enable, silenceOutput);
// Await the response from the service isolate.
- Uri uri = await uriCompleter.future;
+ String? uriString = await completer.future;
+ Uri? uri = uriString == null ? null : Uri.parse(uriString);
// Close the port.
receivePort.close();
return new ServiceProtocolInfo(uri);
diff --git a/sdk/lib/ffi/ffi.dart b/sdk/lib/ffi/ffi.dart
index 0e8be36..1e8a9ea 100644
--- a/sdk/lib/ffi/ffi.dart
+++ b/sdk/lib/ffi/ffi.dart
@@ -806,7 +806,7 @@
///
/// Example:
///```dart
-/// @FfiNative<Int64 Function(Int64, Int64)>("FfiNative_Sum")
+/// @FfiNative<Int64 Function(Int64, Int64)>("FfiNative_Sum", isLeaf:true)
/// external int sum(int a, int b);
///```
/// Calling such functions will throw an exception if no resolver
@@ -817,7 +817,8 @@
/// NOTE: This is an experimental feature and may change in the future.
class FfiNative<T> {
final String nativeName;
- const FfiNative(this.nativeName);
+ final bool isLeaf;
+ const FfiNative(this.nativeName, {this.isLeaf: false});
}
// Bootstrapping native for getting the FFI native C function pointer to look
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index 7f6f21b..15695c1 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -13442,7 +13442,7 @@
* var createdElement = document.body.children[0];
* print(createdElement.classes[0]); // Prints 'something'
* ```
- *
+ *
* See also:
*
* * [insertAdjacentText]
@@ -36529,7 +36529,7 @@
* This is equivalent to the `height` function in jQuery and the calculated
* `height` CSS value, converted to a dimensionless num in pixels. Unlike
* [Element.getBoundingClientRect], `height` will return the same numerical
- * width if the element is hidden or not.
+ * height if the element is hidden or not.
*/
num get height;
@@ -37100,7 +37100,7 @@
new _EventStream<T>(e, _eventType, useCapture);
/**
- * Gets an [Stream] for this event type, on the specified element.
+ * Gets a [Stream] for this event type, on the specified element.
*
* This will always return a broadcast stream so multiple listeners can be
* used simultaneously.
@@ -37126,7 +37126,7 @@
}
/**
- * Gets an [ElementEventStream] for this event type, on the list of elements.
+ * Gets a [Stream] for this event type, on the list of elements.
*
* This will always return a broadcast stream so multiple listeners can be
* used simultaneously.
diff --git a/sdk/lib/html/dartium/nativewrappers.dart b/sdk/lib/html/dartium/nativewrappers.dart
index b6d2dc4..1d7787e 100644
--- a/sdk/lib/html/dartium/nativewrappers.dart
+++ b/sdk/lib/html/dartium/nativewrappers.dart
@@ -6,8 +6,18 @@
class NativeFieldWrapperClass1 {}
-class NativeFieldWrapperClass2 {}
+class NativeFieldWrapperClass2 extends NativeFieldWrapperClass1 {}
-class NativeFieldWrapperClass3 {}
+class NativeFieldWrapperClass3 extends NativeFieldWrapperClass2 {}
-class NativeFieldWrapperClass4 {}
+class NativeFieldWrapperClass4 extends NativeFieldWrapperClass3 {}
+
+/// Gets the value of the native field of [object].
+///
+/// Throws an exception if [object] is null or if the native field was not set.
+///
+/// NOTE: This is function is temporary and will be deprecated in the near
+/// future.
+@pragma("vm:recognized", "other")
+int getNativeField(NativeFieldWrapperClass1 object)
+ native "FullyRecognizedMethod_NoNative";
diff --git a/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart b/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart
index 455de12..ad56eea 100644
--- a/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart
+++ b/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart
@@ -89,13 +89,11 @@
static KeyRange createKeyRange_only(/*Key*/ value) =>
_only(_class(), _translateKey(value));
- static KeyRange createKeyRange_lowerBound(
- /*Key*/ bound,
+ static KeyRange createKeyRange_lowerBound(/*Key*/ bound,
[bool open = false]) =>
_lowerBound(_class(), _translateKey(bound), open);
- static KeyRange createKeyRange_upperBound(
- /*Key*/ bound,
+ static KeyRange createKeyRange_upperBound(/*Key*/ bound,
[bool open = false]) =>
_upperBound(_class(), _translateKey(bound), open);
diff --git a/sdk/lib/internal/symbol.dart b/sdk/lib/internal/symbol.dart
index 718ac68..e494ff6 100644
--- a/sdk/lib/internal/symbol.dart
+++ b/sdk/lib/internal/symbol.dart
@@ -12,92 +12,11 @@
* make it accessible to Dart platform code via the static method
* [getName].
*/
+@pragma('vm:entry-point')
class Symbol implements core.Symbol {
+ @pragma('vm:entry-point')
final String _name;
- /**
- * Source of RegExp matching Dart reserved words.
- *
- * Reserved words are not allowed as identifiers.
- */
- static const String reservedWordRE =
- r'(?:assert|break|c(?:a(?:se|tch)|lass|on(?:st|tinue))|d(?:efault|o)|'
- r'e(?:lse|num|xtends)|f(?:alse|inal(?:ly)?|or)|i[fns]|n(?:ew|ull)|'
- r'ret(?:hrow|urn)|s(?:uper|witch)|t(?:h(?:is|row)|r(?:ue|y))|'
- r'v(?:ar|oid)|w(?:hile|ith))';
- /**
- * Source of RegExp matching any public identifier.
- *
- * A public identifier is a valid identifier (not a reserved word)
- * that doesn't start with '_'.
- */
- static const String publicIdentifierRE =
- r'(?!' '$reservedWordRE' r'\b(?!\$))[a-zA-Z$][\w$]*';
- /**
- * Source of RegExp matching any identifier.
- *
- * It matches identifiers but not reserved words. The identifiers
- * may start with '_'.
- */
- static const String identifierRE =
- r'(?!' '$reservedWordRE' r'\b(?!\$))[a-zA-Z$_][\w$]*';
- /**
- * Source of RegExp matching a declarable operator names.
- *
- * The operators that can be declared using `operator` declarations are
- * also the only ones allowed as symbols. The name of the operators is
- * the same as the operator itself except for unary minus, where the name
- * is "unary-".
- */
- static const String operatorRE =
- r'(?:[\-+*/%&|^]|\[\]=?|==|~/?|<[<=]?|>(?:|=|>>?)|unary-)';
-
- // Grammar if symbols:
- // symbol ::= qualifiedName | <empty>
- // qualifiedName ::= publicIdentifier '.' qualifiedName | name
- // name ::= publicIdentifier
- // | publicIdentifier '='
- // | operator
- // where publicIdentifier is any valid identifier (not a reserved word)
- // that isn't private (doesn't start with '_').
- //
- // Railroad diagram of the accepted grammar:
- //
- // /----------------\
- // | |
- // | /-[.]-/ /-[=]-\
- // \ / / \
- // -------[id]------------------------->
- // \ /
- // \------[operator]---/
- // \ /
- // \------------/
- //
-
- /**
- * RegExp that validates a non-empty non-private symbol.
- *
- * The empty symbol is handled before this regexp is used, and is not
- * accepted.
- */
- static final RegExp publicSymbolPattern = new RegExp(
- '^(?:$operatorRE\$|$publicIdentifierRE(?:=?\$|[.](?!\$)))+?\$');
-
- // The grammar of symbols that may be private is the same as for public
- // symbols, except that "publicIdentifier" is replaced by "identifier",
- // which matches any identifier.
-
- /**
- * RegExp that validates a non-empty symbol.
- *
- * Private symbols are accepted.
- *
- * The empty symbol is handled before this regexp is used, and is not
- * accepted.
- */
- static final RegExp symbolPattern =
- new RegExp('^(?:$operatorRE\$|$identifierRE(?:=?\$|[.](?!\$)))+?\$');
-
external const Symbol(String name);
/**
@@ -115,25 +34,5 @@
/// Platform-private accessor which cannot be called from user libraries.
static String getName(Symbol symbol) => symbol._name;
- static String validatePublicSymbol(String name) {
- if (name.isEmpty || publicSymbolPattern.hasMatch(name)) return name;
- if (name.startsWith('_')) {
- // There may be other private parts in a qualified name than the first
- // one, but this is a common case that deserves a specific error
- // message.
- throw new ArgumentError('"$name" is a private identifier');
- }
- throw new ArgumentError('"$name" is not a valid (qualified) symbol name');
- }
-
- /**
- * Checks whether name is a valid symbol name.
- *
- * This test allows both private and non-private symbols.
- */
- static bool isValidSymbol(String name) {
- return (name.isEmpty || symbolPattern.hasMatch(name));
- }
-
external static String computeUnmangledName(Symbol symbol);
}
diff --git a/sdk/lib/isolate/isolate.dart b/sdk/lib/isolate/isolate.dart
index 3e7a592..8a68d10 100644
--- a/sdk/lib/isolate/isolate.dart
+++ b/sdk/lib/isolate/isolate.dart
@@ -567,10 +567,16 @@
/// Sends an asynchronous [message] through this send port, to its
/// corresponding `ReceivePort`.
///
- /// The content of [message] can be: primitive values
- /// (null, num, bool, double, String), instances of [SendPort],
- /// and lists and maps whose elements are any of these.
- /// List and maps are also allowed to contain cyclic references.
+ /// The content of [message] can be:
+ /// - [Null]
+ /// - [bool]
+ /// - [int]
+ /// - [double]
+ /// - [String]
+ /// - [List] or [Map] (whose elements are any of these)
+ /// - [TransferableTypedData]
+ /// - [SendPort]
+ /// - [Capability]
///
/// In the special circumstances when two isolates share the same code and are
/// running in the same process (e.g. isolates created via [Isolate.spawn]),
diff --git a/sdk/lib/libraries.yaml b/sdk/lib/libraries.yaml
index 6262221..9a1a1d8 100644
--- a/sdk/lib/libraries.yaml
+++ b/sdk/lib/libraries.yaml
@@ -5,7 +5,7 @@
# Note: if you edit this file, you must also generate libraries.json in this
# directory:
#
-# python3 ./tools/yaml2json.py sdk/lib/libraries.yaml sdk/lib/libraries.json
+# dart tools/yaml2json.dart sdk/lib/libraries.yaml sdk/lib/libraries.json
#
# We currently have several different files that needs to be updated when
# changing libraries, sources, and patch files. See
diff --git a/sdk/lib/vmservice/vmservice.dart b/sdk/lib/vmservice/vmservice.dart
index d492dcf..dacc9d5 100644
--- a/sdk/lib/vmservice/vmservice.dart
+++ b/sdk/lib/vmservice/vmservice.dart
@@ -366,7 +366,7 @@
return;
}
final uri = await webServerControl(enable, silenceOutput);
- sp.send(uri);
+ sp.send(uri?.toString());
break;
case Constants.SERVER_INFO_MESSAGE_ID:
final serverInformation = VMServiceEmbedderHooks.serverInformation;
@@ -375,7 +375,7 @@
return;
}
final uri = await serverInformation();
- sp.send(uri);
+ sp.send(uri?.toString());
break;
}
}
diff --git a/sdk/lib/vmservice_libraries.yaml b/sdk/lib/vmservice_libraries.yaml
index 40015c3..d5e049c 100644
--- a/sdk/lib/vmservice_libraries.yaml
+++ b/sdk/lib/vmservice_libraries.yaml
@@ -5,7 +5,7 @@
# Note: if you edit this file, you must also generate libraries.json in this
# directory:
#
-# python3 ./tools/yaml2json.py sdk/lib/vmservice_libraries.yaml sdk/lib/vmservice_libraries.json
+# dart tools/yaml2json.dart sdk/lib/vmservice_libraries.yaml sdk/lib/vmservice_libraries.json
#
# We currently have several different files that needs to be updated when
# changing libraries, sources, and patch files. See
diff --git a/tests/co19_2/co19_2-co19.status b/tests/co19_2/co19_2-co19.status
index c281e44..3d7b0c2 100644
--- a/tests/co19_2/co19_2-co19.status
+++ b/tests/co19_2/co19_2-co19.status
@@ -2,5 +2,9 @@
# 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.
-[ $compiler != fasta ]
-
+Language/Generics/Superbounded_types/typedef1_A01_t03: SkipByDesign # https://github.com/dart-lang/sdk/issues/46483
+Language/Generics/Superbounded_types/typedef1_A01_t04: SkipByDesign # https://github.com/dart-lang/sdk/issues/46483
+Language/Generics/Superbounded_types/typedef2_A01_t04: SkipByDesign # https://github.com/dart-lang/sdk/issues/46483
+Language/Generics/typedef_A08_t02: SkipByDesign # https://github.com/dart-lang/sdk/issues/46483
+Language/Generics/typedef_A08_t03: SkipByDesign # https://github.com/dart-lang/sdk/issues/46483
+Language/Generics/typedef_A08_t04: SkipByDesign # https://github.com/dart-lang/sdk/issues/46483
diff --git a/tests/co19_2/co19_2-dart2js.status b/tests/co19_2/co19_2-dart2js.status
index 5ba60fe..5c38055 100644
--- a/tests/co19_2/co19_2-dart2js.status
+++ b/tests/co19_2/co19_2-dart2js.status
@@ -6,6 +6,7 @@
Language/Expressions/Null/instance_of_class_null_t01: SkipByDesign # dart:mirrors not supported https://github.com/dart-lang/co19/issues/522.
Language/Expressions/Numbers/syntax_t06: SkipByDesign # uses integer literal not representable as JavaScript number
Language/Expressions/Numbers/syntax_t09: SkipByDesign # uses integer literal not representable as JavaScript number
+Language/Expressions/Object_Identity/object_t02: SkipByDesign # https://github.com/dart-lang/sdk/issues/42222#issuecomment-640431711
Language/Expressions/Spawning_an_Isolate/new_isolate_t01: SkipByDesign
Language/Functions/External_Functions/not_connected_to_a_body_t01: SkipByDesign # Non-JS-interop external members are not supported
Language/Libraries_and_Scripts/Scripts/top_level_syntax_t01: SkipByDesign # Non-JS-interop external members are not supported
diff --git a/tests/dartdevc/debugger/debugger_test_golden.txt b/tests/dartdevc/debugger/debugger_test_golden.txt
index 76772be..a879c6e 100644
--- a/tests/dartdevc/debugger/debugger_test_golden.txt
+++ b/tests/dartdevc/debugger/debugger_test_golden.txt
@@ -6519,7 +6519,7 @@
{
"style": "background-color: #d9edf7;color: black"
},
- "Instance of 'TestGenericClass<JSObject<ExampleJSClass>, int>'"
+ "Instance of 'TestGenericClass<ExampleJSClass, int>'"
]
-----------------------------------
Test: TestGenericClassJSInterop instance body
@@ -6616,7 +6616,7 @@
{
"style": "background-color: #d9edf7;color: black"
},
- "TestGenericClass<JSObject<ExampleJSClass>, int>"
+ "TestGenericClass<ExampleJSClass, int>"
]
-----------------------------------
Test: TestGenericClassJSInterop definition formatting body
diff --git a/tests/dartdevc_2/debugger/debugger_test_golden.txt b/tests/dartdevc_2/debugger/debugger_test_golden.txt
index 76772be..a879c6e 100644
--- a/tests/dartdevc_2/debugger/debugger_test_golden.txt
+++ b/tests/dartdevc_2/debugger/debugger_test_golden.txt
@@ -6519,7 +6519,7 @@
{
"style": "background-color: #d9edf7;color: black"
},
- "Instance of 'TestGenericClass<JSObject<ExampleJSClass>, int>'"
+ "Instance of 'TestGenericClass<ExampleJSClass, int>'"
]
-----------------------------------
Test: TestGenericClassJSInterop instance body
@@ -6616,7 +6616,7 @@
{
"style": "background-color: #d9edf7;color: black"
},
- "TestGenericClass<JSObject<ExampleJSClass>, int>"
+ "TestGenericClass<ExampleJSClass, int>"
]
-----------------------------------
Test: TestGenericClassJSInterop definition formatting body
diff --git a/tests/ffi/ffi.status b/tests/ffi/ffi.status
index 16826bf..c54ce09 100644
--- a/tests/ffi/ffi.status
+++ b/tests/ffi/ffi.status
@@ -40,7 +40,3 @@
[ $compiler == dart2analyzer || $compiler == fasta ]
vmspecific_enable_ffi_test: SkipByDesign # This is a check for VM only.
-
-[ $hot_reload || $hot_reload_rollback ]
-snapshot_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-vmspecific_function_callbacks_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
diff --git a/tests/ffi/ffi_native_test.dart b/tests/ffi/ffi_native_test.dart
new file mode 100644
index 0000000..b700981
--- /dev/null
+++ b/tests/ffi/ffi_native_test.dart
@@ -0,0 +1,66 @@
+// 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.
+//
+// SharedObjects=ffi_test_functions
+
+// NOTE: There is no `test/ffi_2/...` version of this test since annotations
+// with type arguments isn't supported in that version of Dart.
+
+import 'dart:ffi';
+
+import 'package:expect/expect.dart';
+
+import 'dylib_utils.dart';
+
+final nativeLib = dlopenPlatformSpecific('ffi_test_functions');
+final getRootLibraryUrl = nativeLib
+ .lookupFunction<Handle Function(), Object Function()>('GetRootLibraryUrl');
+final setFfiNativeResolverForTest = nativeLib
+ .lookupFunction<Void Function(Handle), void Function(Object)>('SetFfiNativeResolverForTest');
+
+@FfiNative<IntPtr Function(IntPtr)>('ReturnIntPtr')
+external int returnIntPtr(int x);
+
+@FfiNative<IntPtr Function(IntPtr)>('ReturnIntPtr', isLeaf: true)
+external int returnIntPtrLeaf(int x);
+
+@FfiNative<IntPtr Function()>('IsThreadInGenerated')
+external int isThreadInGenerated();
+
+@FfiNative<IntPtr Function()>('IsThreadInGenerated', isLeaf: true)
+external int isThreadInGeneratedLeaf();
+
+// Error: FFI leaf call must not have Handle return type.
+@FfiNative<Handle Function()>("foo", isLeaf: true) //# 01: compile-time error
+external Object foo(); //# 01: compile-time error
+
+// Error: FFI leaf call must not have Handle argument types.
+@FfiNative<Void Function(Handle)>("bar", isLeaf: true) //# 02: compile-time error
+external void bar(Object); //# 02: compile-time error
+
+class Classy {
+ @FfiNative<IntPtr Function(IntPtr)>('ReturnIntPtr')
+ external static int returnIntPtrStatic(int x);
+
+ // Error: FfiNative annotations can only be used on static functions.
+ @FfiNative<IntPtr Function(IntPtr)>('ReturnIntPtr') //# 03: compile-time error
+ external int returnIntPtrMethod(int x); //# 03: compile-time error
+}
+
+void main() {
+ // Register test resolver for top-level functions above.
+ final root_lib_url = getRootLibraryUrl();
+ setFfiNativeResolverForTest(root_lib_url);
+
+ // Test we can call FfiNative functions.
+ Expect.equals(123, returnIntPtr(123));
+ Expect.equals(123, returnIntPtrLeaf(123));
+ Expect.equals(123, Classy.returnIntPtrStatic(123));
+
+ // Test FfiNative leaf calls remain in generated code.
+ // Regular calls should transition generated -> native.
+ Expect.equals(0, isThreadInGenerated());
+ // Leaf calls should remain in generated state.
+ Expect.equals(1, isThreadInGeneratedLeaf());
+}
diff --git a/tests/ffi/snapshot_test.dart b/tests/ffi/snapshot_test.dart
index 5bb0b10..b27b88b 100644
--- a/tests/ffi/snapshot_test.dart
+++ b/tests/ffi/snapshot_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
//
// Checks that the VM throws an appropriate exception when FFI objects are
diff --git a/tests/ffi/vmspecific_function_callbacks_test.dart b/tests/ffi/vmspecific_function_callbacks_test.dart
index f35ae18..6d192a9 100644
--- a/tests/ffi/vmspecific_function_callbacks_test.dart
+++ b/tests/ffi/vmspecific_function_callbacks_test.dart
@@ -5,7 +5,7 @@
//
// Dart test program for testing dart:ffi function pointers with callbacks.
//
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// VMOptions=--stacktrace-every=100
// VMOptions=--write-protect-code --no-dual-map-code
diff --git a/tests/ffi_2/ffi_2.status b/tests/ffi_2/ffi_2.status
index 16826bf..c54ce09 100644
--- a/tests/ffi_2/ffi_2.status
+++ b/tests/ffi_2/ffi_2.status
@@ -40,7 +40,3 @@
[ $compiler == dart2analyzer || $compiler == fasta ]
vmspecific_enable_ffi_test: SkipByDesign # This is a check for VM only.
-
-[ $hot_reload || $hot_reload_rollback ]
-snapshot_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-vmspecific_function_callbacks_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
diff --git a/tests/ffi_2/snapshot_test.dart b/tests/ffi_2/snapshot_test.dart
index 129a8d0..7574cea 100644
--- a/tests/ffi_2/snapshot_test.dart
+++ b/tests/ffi_2/snapshot_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
//
// Checks that the VM throws an appropriate exception when FFI objects are
diff --git a/tests/ffi_2/vmspecific_function_callbacks_test.dart b/tests/ffi_2/vmspecific_function_callbacks_test.dart
index 6d9311f..e86bb95 100644
--- a/tests/ffi_2/vmspecific_function_callbacks_test.dart
+++ b/tests/ffi_2/vmspecific_function_callbacks_test.dart
@@ -7,7 +7,7 @@
// Dart test program for testing dart:ffi function pointers with callbacks.
//
// SharedObjects=ffi_test_functions
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// VMOptions=--stacktrace-every=100
// VMOptions=--use-slow-path
diff --git a/tests/language/abstract/exact_selector_runtime_test.dart b/tests/language/abstract/exact_selector_runtime_test.dart
index e8fc4ec..3d8f29e 100644
--- a/tests/language/abstract/exact_selector_runtime_test.dart
+++ b/tests/language/abstract/exact_selector_runtime_test.dart
@@ -9,13 +9,13 @@
// methods to handle `noSuchMethod`.
import "package:expect/expect.dart";
-import "../compiler_annotations.dart";
class Foo {
noSuchMethod(im) => 42;
}
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
returnFoo() {
(() => 42)();
return new Foo();
diff --git a/tests/language/abstract/exact_selector_test.dart b/tests/language/abstract/exact_selector_test.dart
index 0df1020..fc6dba8 100644
--- a/tests/language/abstract/exact_selector_test.dart
+++ b/tests/language/abstract/exact_selector_test.dart
@@ -6,13 +6,13 @@
// methods to handle `noSuchMethod`.
import "package:expect/expect.dart";
-import "../compiler_annotations.dart";
abstract class Foo {
noSuchMethod(im) => 42;
}
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
returnFoo() {
(() => 42)();
return new Foo();
diff --git a/tests/language/closure/regress46568_test.dart b/tests/language/closure/regress46568_test.dart
new file mode 100644
index 0000000..33e34b6
--- /dev/null
+++ b/tests/language/closure/regress46568_test.dart
@@ -0,0 +1,40 @@
+// 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.
+
+import 'package:expect/expect.dart';
+
+// Regression test for https://github.com/dart-lang/sdk/issues/46568.
+
+var genericTopLevelFunctionCallCount = 0;
+var genericStaticMethodCallCount = 0;
+
+T? genericTopLevelFunction<T>() {
+ genericTopLevelFunctionCallCount++;
+ return null;
+}
+
+class A {
+ static T? genericStaticMethod<T>() {
+ genericStaticMethodCallCount++;
+ return null;
+ }
+}
+
+const int? Function() cIntTopLevelFunction1 = genericTopLevelFunction;
+const int? Function() cIntStaticMethod1 = A.genericStaticMethod;
+
+void main() {
+ // Two different const generic function instantiations should not be
+ // canonicalized to the same value.
+ Expect.isFalse(identical(cIntTopLevelFunction1, cIntStaticMethod1));
+ Expect.notEquals(cIntTopLevelFunction1, cIntStaticMethod1);
+
+ cIntTopLevelFunction1();
+ Expect.equals(1, genericTopLevelFunctionCallCount);
+ Expect.equals(0, genericStaticMethodCallCount);
+
+ cIntStaticMethod1();
+ Expect.equals(1, genericTopLevelFunctionCallCount);
+ Expect.equals(1, genericStaticMethodCallCount);
+}
diff --git a/tests/language/compiler_annotations.dart b/tests/language/compiler_annotations.dart
deleted file mode 100644
index c920add..0000000
--- a/tests/language/compiler_annotations.dart
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright (c) 2013, 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.
-
-library compiler_annotations;
-
-// This library contains annotations useful for testing.
-
-// TODO(ngeoffray): Implement in dart2js.
-class DontInline {
- const DontInline();
-}
diff --git a/tests/language/const/constructor_mixin2_test.dart b/tests/language/const/constructor_mixin2_test.dart
index a7bc863..873141d 100644
--- a/tests/language/const/constructor_mixin2_test.dart
+++ b/tests/language/const/constructor_mixin2_test.dart
@@ -15,8 +15,6 @@
{
const B(foo) : super(foo);
// ^
-// [analyzer] COMPILE_TIME_ERROR.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD
-// ^
// [analyzer] COMPILE_TIME_ERROR.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD
// ^
// [cfe] A constant constructor can't call a non-constant super constructor.
diff --git a/tests/language/const/map2_runtime_test.dart b/tests/language/const/map2_runtime_test.dart
index 9e1fe97..02e6a9e 100644
--- a/tests/language/const/map2_runtime_test.dart
+++ b/tests/language/const/map2_runtime_test.dart
@@ -13,12 +13,10 @@
class B implements A {
const B();
-
-
}
confuse(x) {
- if (new DateTime.now() == 42) return confuse(2);
+ if (DateTime.now().millisecondsSinceEpoch == 42) return confuse(2);
return x;
}
diff --git a/tests/language/const/map2_test.dart b/tests/language/const/map2_test.dart
index a5f3798..dd392be 100644
--- a/tests/language/const/map2_test.dart
+++ b/tests/language/const/map2_test.dart
@@ -15,7 +15,7 @@
}
confuse(x) {
- if (new DateTime.now() == 42) return confuse(2);
+ if (DateTime.now().millisecondsSinceEpoch == 42) return confuse(2);
return x;
}
diff --git a/tests/language/const/map5_test.dart b/tests/language/const/map5_test.dart
new file mode 100644
index 0000000..0fbd8de
--- /dev/null
+++ b/tests/language/const/map5_test.dart
@@ -0,0 +1,47 @@
+// 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.
+
+// Tests lookup of type literals of user-defined classes in const maps.
+
+import 'package:expect/expect.dart';
+
+class A {}
+
+class C<T> {}
+
+typedef F = T Function<T>();
+typedef Cint = C<int>;
+
+const aType = A;
+const fType = F;
+const cIntType = Cint;
+
+main() {
+ final map = const {A: 42, F: 2, 'asdf': 'fdsa', Cint: 'foo'};
+ Expect.equals(42, map[getValueNonOptimized(A)]);
+ Expect.equals(42, map[getValueNonOptimized(aType)]);
+ Expect.equals(2, map[getValueNonOptimized(F)]);
+ Expect.equals(2, map[getValueNonOptimized(fType)]);
+ Expect.equals('foo', map[getValueNonOptimized(Cint)]);
+ Expect.equals('foo', map[getValueNonOptimized(cIntType)]);
+ Expect.isTrue(map.containsKey(getValueNonOptimized(A)));
+ Expect.isTrue(map.containsKey(getValueNonOptimized(aType)));
+ Expect.isTrue(map.containsKey(getValueNonOptimized(F)));
+ Expect.isTrue(map.containsKey(getValueNonOptimized(fType)));
+ Expect.isTrue(map.containsKey(getValueNonOptimized(Cint)));
+ Expect.isTrue(map.containsKey(getValueNonOptimized(cIntType)));
+}
+
+/// Returns its argument.
+///
+/// Prevents static optimizations and inlining.
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
+dynamic getValueNonOptimized(dynamic x) {
+ // DateTime.now() cannot be predicted statically, never equal to 42.
+ if (DateTime.now().millisecondsSinceEpoch == 42) {
+ return getValueNonOptimized(2);
+ }
+ return x;
+}
diff --git a/tests/language/const/map_hashcode_override2_test.dart b/tests/language/const/map_hashcode_override2_test.dart
index b747a97..d2e5858 100644
--- a/tests/language/const/map_hashcode_override2_test.dart
+++ b/tests/language/const/map_hashcode_override2_test.dart
@@ -7,9 +7,13 @@
/// Returns its argument.
///
/// Prevents static optimizations and inlining.
-getValueNonOptimized(x) {
- // DateTime.now() cannot be predicted statically, never equal to ASCII 42 '*'.
- if (new DateTime.now() == 42) return getValueNonOptimized(2);
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
+dynamic getValueNonOptimized(dynamic x) {
+ // DateTime.now() cannot be predicted statically, never equal to 42.
+ if (DateTime.now().millisecondsSinceEpoch == 42) {
+ return getValueNonOptimized(2);
+ }
return x;
}
diff --git a/tests/language/const/map_hashcode_override_test.dart b/tests/language/const/map_hashcode_override_test.dart
index e378e05..f8aa3cc 100644
--- a/tests/language/const/map_hashcode_override_test.dart
+++ b/tests/language/const/map_hashcode_override_test.dart
@@ -7,9 +7,13 @@
/// Returns its argument.
///
/// Prevents static optimizations and inlining.
-getValueNonOptimized(x) {
- // DateTime.now() cannot be predicted statically, never equal to ASCII 42 '*'.
- if (new DateTime.now() == 42) return getValueNonOptimized(2);
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
+dynamic getValueNonOptimized(dynamic x) {
+ // DateTime.now() cannot be predicted statically, never equal to 42.
+ if (DateTime.now().millisecondsSinceEpoch == 42) {
+ return getValueNonOptimized(2);
+ }
return x;
}
diff --git a/tests/language/const/map_null_lookup_test.dart b/tests/language/const/map_null_lookup_test.dart
new file mode 100644
index 0000000..e493653
--- /dev/null
+++ b/tests/language/const/map_null_lookup_test.dart
@@ -0,0 +1,29 @@
+// 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.
+
+// Tests lookup of null in const maps.
+
+import 'package:expect/expect.dart';
+
+main() {
+ final map1 = const {1: 42, null: 2, 'asdf': 'fdsa'};
+ Expect.equals(2, map1[getValueNonOptimized(null)]);
+ Expect.isTrue(map1.containsKey(null));
+ final map2 = const {1: 42, 2: 2, 'asdf': 'fdsa'};
+ Expect.equals(null, map2[getValueNonOptimized(null)]);
+ Expect.isFalse(map2.containsKey(null));
+}
+
+/// Returns its argument.
+///
+/// Prevents static optimizations and inlining.
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
+dynamic getValueNonOptimized(dynamic x) {
+ // DateTime.now() cannot be predicted statically, never equal to 42.
+ if (DateTime.now().millisecondsSinceEpoch == 42) {
+ return getValueNonOptimized(2);
+ }
+ return x;
+}
diff --git a/tests/language/const/map_test.dart b/tests/language/const/map_test.dart
index 13c6720..d1a88fe 100644
--- a/tests/language/const/map_test.dart
+++ b/tests/language/const/map_test.dart
@@ -7,9 +7,13 @@
/// Returns its argument.
///
/// Prevents static optimizations and inlining.
-getValueNonOptimized(x) {
- // DateTime.now() cannot be predicted statically, never equal to ASCII 42 '*'.
- if (new DateTime.now() == 42) return getValueNonOptimized(2);
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
+dynamic getValueNonOptimized(dynamic x) {
+ // DateTime.now() cannot be predicted statically, never equal to 42.
+ if (DateTime.now().millisecondsSinceEpoch == 42) {
+ return getValueNonOptimized(2);
+ }
return x;
}
diff --git a/tests/language/const/set5_test.dart b/tests/language/const/set5_test.dart
new file mode 100644
index 0000000..f27b5f9
--- /dev/null
+++ b/tests/language/const/set5_test.dart
@@ -0,0 +1,47 @@
+// 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.
+
+// Tests lookup of type literals of user-defined classes in const sets.
+
+import 'package:expect/expect.dart';
+
+class A {}
+
+class C<T> {}
+
+typedef F = T Function<T>();
+typedef Cint = C<int>;
+
+const aType = A;
+const fType = F;
+const cIntType = Cint;
+
+main() {
+ final set1 = const {A, 1, 'asdf', F, Cint};
+ Expect.isTrue(set1.contains(getValueNonOptimized(A)));
+ Expect.isTrue(set1.contains(getValueNonOptimized(aType)));
+ Expect.isTrue(set1.contains(getValueNonOptimized(F)));
+ Expect.isTrue(set1.contains(getValueNonOptimized(fType)));
+ Expect.isTrue(set1.contains(getValueNonOptimized(Cint)));
+ Expect.isTrue(set1.contains(getValueNonOptimized(cIntType)));
+ Expect.equals(A, set1.lookup(getValueNonOptimized(A)));
+ Expect.equals(A, set1.lookup(getValueNonOptimized(aType)));
+ Expect.equals(F, set1.lookup(getValueNonOptimized(F)));
+ Expect.equals(F, set1.lookup(getValueNonOptimized(fType)));
+ Expect.equals(Cint, set1.lookup(getValueNonOptimized(Cint)));
+ Expect.equals(Cint, set1.lookup(getValueNonOptimized(cIntType)));
+}
+
+/// Returns its argument.
+///
+/// Prevents static optimizations and inlining.
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
+dynamic getValueNonOptimized(dynamic x) {
+ // DateTime.now() cannot be predicted statically, never equal to 42.
+ if (DateTime.now().millisecondsSinceEpoch == 42) {
+ return getValueNonOptimized(2);
+ }
+ return x;
+}
diff --git a/tests/language/const/set_hashcode_override2_test.dart b/tests/language/const/set_hashcode_override2_test.dart
index 1fc8665..cbe8944 100644
--- a/tests/language/const/set_hashcode_override2_test.dart
+++ b/tests/language/const/set_hashcode_override2_test.dart
@@ -7,9 +7,13 @@
/// Returns its argument.
///
/// Prevents static optimizations and inlining.
-getValueNonOptimized(x) {
- // DateTime.now() cannot be predicted statically, never equal to ASCII 42 '*'.
- if (new DateTime.now() == 42) return getValueNonOptimized(2);
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
+dynamic getValueNonOptimized(dynamic x) {
+ // DateTime.now() cannot be predicted statically, never equal to 42.
+ if (DateTime.now().millisecondsSinceEpoch == 42) {
+ return getValueNonOptimized(2);
+ }
return x;
}
diff --git a/tests/language/const/set_null_lookup_test.dart b/tests/language/const/set_null_lookup_test.dart
new file mode 100644
index 0000000..a2b4044
--- /dev/null
+++ b/tests/language/const/set_null_lookup_test.dart
@@ -0,0 +1,29 @@
+// 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.
+
+// Tests lookup of null in const maps.
+
+import 'package:expect/expect.dart';
+
+main() {
+ final set1 = const {null, 1, 'asdf'};
+ Expect.isTrue(set1.contains(getValueNonOptimized(null)));
+ Expect.equals(null, set1.lookup(null));
+ final set2 = const {42, 1, 'asdf'};
+ Expect.isFalse(set2.contains(getValueNonOptimized(null)));
+ Expect.equals(null, set2.lookup(null));
+}
+
+/// Returns its argument.
+///
+/// Prevents static optimizations and inlining.
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
+dynamic getValueNonOptimized(dynamic x) {
+ // DateTime.now() cannot be predicted statically, never equal to 42.
+ if (DateTime.now().millisecondsSinceEpoch == 42) {
+ return getValueNonOptimized(2);
+ }
+ return x;
+}
diff --git a/tests/language/constructor/multiple_field_assignment_constructor_test.dart b/tests/language/constructor/multiple_field_assignment_constructor_test.dart
index 7292e80..c499161 100644
--- a/tests/language/constructor/multiple_field_assignment_constructor_test.dart
+++ b/tests/language/constructor/multiple_field_assignment_constructor_test.dart
@@ -3,7 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
import "package:expect/expect.dart";
-import "../compiler_annotations.dart";
var a = [null];
@@ -11,7 +10,8 @@
var foo;
var bar;
- @DontInline()
+ @pragma('vm:never-inline')
+ @pragma('dart2js:noInline')
A() {
// Currently defeat inlining by using a closure.
bar = () => 42;
@@ -24,7 +24,8 @@
var foo;
var bar;
- @DontInline()
+ @pragma('vm:never-inline')
+ @pragma('dart2js:noInline')
B() {
// Currently defeat inlining by using a closure.
bar = () => 42;
@@ -44,7 +45,8 @@
new B();
}
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
bar() {
// Currently defeat inlining by using a closure.
Expect.throwsNoSuchMethodError(() => new A().foo + 42);
diff --git a/tests/language/constructor/tear_off_test.dart b/tests/language/constructor/tear_off_test.dart
index f890b44..a0764886 100644
--- a/tests/language/constructor/tear_off_test.dart
+++ b/tests/language/constructor/tear_off_test.dart
@@ -24,18 +24,16 @@
const NGenRedir._(this.x);
}
-class NFac {
+class NFac implements NFacRedir {
final int x;
- factory NFac(int x) => NFacRedir._(x);
- factory NFac.named(int x) => NFacRedir._(x);
- NFac._(this.x);
+ factory NFac(int x) => NFac._(x);
+ factory NFac.named(int x) => NFac._(x);
+ const NFac._(this.x);
}
class NFacRedir {
- final int x;
const factory NFacRedir(int x) = NFac._;
const factory NFacRedir.named(int x) = NFac._;
- NFacRedir._(this.x);
}
// Generic classes.
@@ -52,18 +50,16 @@
const GGenRedir._(this.x);
}
-class GFac<T> {
+class GFac<T> implements GFacRedir<T> {
final int x;
- factory GFac(int x) => GFacRedir._(x);
- factory GFac.named(int x) => GFacRedir._(x);
- GFac._(this.x);
+ factory GFac(int x) => GFac._(x);
+ factory GFac.named(int x) => GFac._(x);
+ const GFac._(this.x);
}
class GFacRedir<T> {
- final int x;
const factory GFacRedir(int x) = GFac._;
const factory GFacRedir.named(int x) = GFac._;
- GFacRedir._(this.x);
}
class Optional<T> {
@@ -96,9 +92,9 @@
GGen<int>.new.expectStaticType<Exactly<GGen<int> Function(int)>>();
GGen<int>.named.expectStaticType<Exactly<GGen<int> Function(int)>>();
GGenRedir<int>.new
- .expectStaticType<Exactly<GGenRedir<T> Function<T>(int)>>();
+ .expectStaticType<Exactly<GGenRedir<int> Function(int)>>();
GGenRedir<int>.named
- .expectStaticType<Exactly<GGenRedir<T> Function<T>(int)>>();
+ .expectStaticType<Exactly<GGenRedir<int> Function(int)>>();
GFac<int>.new.expectStaticType<Exactly<GFac<int> Function(int)>>();
GFac<int>.named.expectStaticType<Exactly<GFac<int> Function(int)>>();
GFacRedir<int>.new
@@ -106,26 +102,26 @@
GFacRedir<int>.named
.expectStaticType<Exactly<GFacRedir<int> Function(int)>>();
- contextType<GGen<int> Function(int)>(
+ context<GGen<int> Function(int)>(
GGen.new..expectStaticType<Exactly<GGen<int> Function(int)>>());
- contextType<GGen<int> Function(int)>(
+ context<GGen<int> Function(int)>(
GGen.named..expectStaticType<Exactly<GGen<int> Function(int)>>());
- contextType<GGenRedir<int> Function(int)>(GGenRedir.new
+ context<GGenRedir<int> Function(int)>(GGenRedir.new
..expectStaticType<Exactly<GGenRedir<int> Function(int)>>());
- contextType<GGenRedir<int> Function(int)>(GGenRedir.named
+ context<GGenRedir<int> Function(int)>(GGenRedir.named
..expectStaticType<Exactly<GGenRedir<int> Function(int)>>());
- contextType<GFac<int> Function(int)>(
+ context<GFac<int> Function(int)>(
GFac.new..expectStaticType<Exactly<GFac<int> Function(int)>>());
- contextType<GFac<int> Function(int)>(
+ context<GFac<int> Function(int)>(
GFac.named..expectStaticType<Exactly<GFac<int> Function(int)>>());
- contextType<GFacRedir<int> Function(int)>(
+ context<GFacRedir<int> Function(int)>(
GFacRedir.new..expectStaticType<Exactly<GFacRedir<int> Function(int)>>());
- contextType<GFacRedir<int> Function(int)>(GFacRedir.named
+ context<GFacRedir<int> Function(int)>(GFacRedir.named
..expectStaticType<Exactly<GFacRedir<int> Function(int)>>());
- contextType<Optional<int> Function()>(Optional.new
+ context<Optional<int> Function()>(Optional.new
..expectStaticType<Exactly<Optional<int> Function([int, int])>>());
- contextType<Optional<int> Function()>(Optional.named
+ context<Optional<int> Function()>(Optional.named
..expectStaticType<Exactly<Optional<int> Function({int x, int y})>>());
// Check that tear-offs are canonicalized where possible
diff --git a/tests/language/generic_methods/explicit_instantiated_tearoff_test.dart b/tests/language/generic_methods/explicit_instantiated_tearoff_test.dart
index 968ae22..5813d60 100644
--- a/tests/language/generic_methods/explicit_instantiated_tearoff_test.dart
+++ b/tests/language/generic_methods/explicit_instantiated_tearoff_test.dart
@@ -68,7 +68,8 @@
Expect.identical(staticMethod<int, String>, staticTearOff);
- Expect.equals(
+ // Extension instance methods are not equal unless identical.
+ Expect.notEquals(
extInstanceMethod<int, String>, this.extInstanceMethod<int, String>);
}
}
@@ -132,7 +133,9 @@
o.instanceMethod<int, String>, o.instanceMethod<int, String>);
Expect.equals(
o.mixinInstanceMethod<int, String>, o.mixinInstanceMethod<int, String>);
- Expect.equals(
+
+ // Instantiated extension methods are not equal unless they are identical.
+ Expect.notEquals(
o.extInstanceMethod<int, String>, o.extInstanceMethod<int, String>);
// And not canonicalized where they shouldn't (different types).
diff --git a/tests/language/map/literal15_test.dart b/tests/language/map/literal15_test.dart
new file mode 100644
index 0000000..049486e
--- /dev/null
+++ b/tests/language/map/literal15_test.dart
@@ -0,0 +1,21 @@
+// 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.
+
+// Test the use of `null` keys in const maps.
+
+library map_literal15_test;
+
+import "package:expect/expect.dart";
+
+void main() {
+ var m1 = const <String, int>{null: 10, 'null': 20};
+ // ^^^^
+ // [analyzer] COMPILE_TIME_ERROR.MAP_KEY_TYPE_NOT_ASSIGNABLE
+ // [cfe] The value 'null' can't be assigned to a variable of type 'String' because 'String' is not nullable.
+
+ var m2 = const <Comparable, int>{null: 10, 'null': 20};
+ // ^^^^
+ // [analyzer] COMPILE_TIME_ERROR.MAP_KEY_TYPE_NOT_ASSIGNABLE
+ // [cfe] The value 'null' can't be assigned to a variable of type 'Comparable<dynamic>' because 'Comparable<dynamic>' is not nullable.
+}
diff --git a/tests/language/optimize/inferrer_constructor2_test.dart b/tests/language/optimize/inferrer_constructor2_test.dart
index 58da3ad..4d28519 100644
--- a/tests/language/optimize/inferrer_constructor2_test.dart
+++ b/tests/language/optimize/inferrer_constructor2_test.dart
@@ -7,13 +7,13 @@
// inlined.
import "package:expect/expect.dart";
-import "../compiler_annotations.dart";
class A {
var foo;
var bar;
- @DontInline()
+ @pragma('vm:never-inline')
+ @pragma('dart2js:noInline')
A() {
// Currently defeat inlining by using a closure.
bar = () => 42;
@@ -33,7 +33,8 @@
class B {
var bar;
var closure;
- @DontInline()
+ @pragma('vm:never-inline')
+ @pragma('dart2js:noInline')
B() {
// Currently defeat inlining by using a closure.
closure = () => 42;
@@ -41,7 +42,8 @@
}
}
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
bar() {
// Make sure B's constructor is analyzed first by surrounding the
// body by two allocations.
@@ -52,7 +54,8 @@
new B();
}
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
codegenLast() {
// This assignment currently defeats simple type inference, but not
// the optimistic inferrer.
diff --git a/tests/language/optimize/inferrer_constructor3_test.dart b/tests/language/optimize/inferrer_constructor3_test.dart
index 395f113..a3e9038 100644
--- a/tests/language/optimize/inferrer_constructor3_test.dart
+++ b/tests/language/optimize/inferrer_constructor3_test.dart
@@ -7,7 +7,6 @@
// inlined.
import "package:expect/expect.dart";
-import "../compiler_annotations.dart";
class A {
var field;
@@ -24,14 +23,16 @@
bar();
}
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
doIt() {
() => 42;
var c = new A(null);
Expect.throwsNoSuchMethodError(() => c.field + 42);
}
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
bar() {
() => 42;
return inlineLevel1();
diff --git a/tests/language/optimize/inferrer_named_parameter_test.dart b/tests/language/optimize/inferrer_named_parameter_test.dart
index a6655b4..c06fc38 100644
--- a/tests/language/optimize/inferrer_named_parameter_test.dart
+++ b/tests/language/optimize/inferrer_named_parameter_test.dart
@@ -6,9 +6,9 @@
// correctly infer optional named parameters.
import "package:expect/expect.dart";
-import "../compiler_annotations.dart";
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
foo({path}) {
() => 42;
return path;
diff --git a/tests/language/optimize/inferrer_synthesized_super_constructor_test.dart b/tests/language/optimize/inferrer_synthesized_super_constructor_test.dart
index 1a7284b..dc81959 100644
--- a/tests/language/optimize/inferrer_synthesized_super_constructor_test.dart
+++ b/tests/language/optimize/inferrer_synthesized_super_constructor_test.dart
@@ -2,10 +2,9 @@
// 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.
-import '../compiler_annotations.dart';
-
class A {
- @DontInline()
+ @pragma('vm:never-inline')
+ @pragma('dart2js:noInline')
A([a]) {
() => 42;
if (a != null) throw 'Test failed';
diff --git a/tests/language/regress/regress12284_test.dart b/tests/language/regress/regress12284_test.dart
index 4164c44..aeaf366 100644
--- a/tests/language/regress/regress12284_test.dart
+++ b/tests/language/regress/regress12284_test.dart
@@ -3,12 +3,12 @@
// BSD-style license that can be found in the LICENSE file.
import "package:expect/expect.dart";
-import "../compiler_annotations.dart";
class A {
int field = -1;
- @DontInline()
+ @pragma('vm:never-inline')
+ @pragma('dart2js:noInline')
A(param) {
// Currently defeat inlining by using a closure.
var bar = () => 42;
diff --git a/tests/language/regress/regress12336_test.dart b/tests/language/regress/regress12336_test.dart
index 029c3f1..7630c49 100644
--- a/tests/language/regress/regress12336_test.dart
+++ b/tests/language/regress/regress12336_test.dart
@@ -6,7 +6,6 @@
// [foo].
import "package:expect/expect.dart";
-import "../compiler_annotations.dart";
main() {
var result = foo(1, 2);
@@ -18,7 +17,8 @@
Expect.listEquals([], result[1]);
}
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
foo(a, b) {
() => 42;
if (a is List) {
diff --git a/tests/language/regress/regress15720_test.dart b/tests/language/regress/regress15720_test.dart
index 638fc98..85c102c 100644
--- a/tests/language/regress/regress15720_test.dart
+++ b/tests/language/regress/regress15720_test.dart
@@ -7,7 +7,7 @@
class B {}
confuse(x) {
- if (new DateTime.now() == 42) return confuse(x);
+ if (DateTime.now().millisecondsSinceEpoch == 42) return confuse(x);
return x;
}
diff --git a/tests/language/regress/regress23244_test.dart b/tests/language/regress/regress23244_test.dart
index c955874..6a25b57 100644
--- a/tests/language/regress/regress23244_test.dart
+++ b/tests/language/regress/regress23244_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// Regression test case for http://dartbug.com/23244
diff --git a/tests/language/regress/regress46550_test.dart b/tests/language/regress/regress46550_test.dart
new file mode 100644
index 0000000..9b609da
--- /dev/null
+++ b/tests/language/regress/regress46550_test.dart
@@ -0,0 +1,21 @@
+// 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.
+
+// VMOptions=--optimization_counter_threshold=100 --deterministic
+
+import "package:expect/expect.dart";
+
+typedef void test1<T extends num>();
+
+void t1<T extends int>() {
+ Expect.equals(int, T);
+}
+
+const test1 res1 = t1;
+
+main() {
+ for (int i = 0; i < 120; ++i) {
+ res1();
+ }
+}
diff --git a/tests/language/static_type_helper.dart b/tests/language/static_type_helper.dart
index 4a7809a..14acd63 100644
--- a/tests/language/static_type_helper.dart
+++ b/tests/language/static_type_helper.dart
@@ -6,7 +6,7 @@
Type typeOf<T>() => T;
/// Ensures a context type of [T] for the operand.
-void context<T>(T x) {}
+Object? context<T>(T x) => x;
/// Captures the context type of the call and returns the same type.
///
diff --git a/tests/language/string/optimizations_test.dart b/tests/language/string/optimizations_test.dart
index a40bc0b..b595437 100644
--- a/tests/language/string/optimizations_test.dart
+++ b/tests/language/string/optimizations_test.dart
@@ -6,15 +6,16 @@
// correctly infer optional named parameters.
import "package:expect/expect.dart";
-import "../compiler_annotations.dart";
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
foo({path}) {
() => 42;
return path.toString();
}
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
bar({path}) {
() => 42;
return path;
diff --git a/tests/language/type_object/explicit_instantiated_type_literal_test.dart b/tests/language/type_object/explicit_instantiated_type_literal_test.dart
index 07fa243..6b3b07f 100644
--- a/tests/language/type_object/explicit_instantiated_type_literal_test.dart
+++ b/tests/language/type_object/explicit_instantiated_type_literal_test.dart
@@ -18,8 +18,8 @@
Type type<T>() => T;
void main() {
- C.expectStaticType<Type>();
- C<int>.expectStaticType<Type>();
+ (C).expectStaticType<Exactly<Type>>();
+ (C<int>).expectStaticType<Exactly<Type>>();
Expect.identical(C<num>, C);
Expect.identical(C<int>, C<int>);
@@ -30,8 +30,8 @@
Expect.identical(C<dynamic>, C<dynamic>);
Expect.equals(C<dynamic>, type<C<dynamic>>());
- prefix.C.expectStaticType<Type>();
- prefix.C<int>.expectStaticType<Type>();
+ (prefix.C).expectStaticType<Exactly<Type>>();
+ (prefix.C<int>).expectStaticType<Exactly<Type>>();
Expect.identical(prefix.C<num>, prefix.C);
Expect.identical(prefix.C<int>, prefix.C<int>);
diff --git a/tests/language/typedef/aliased_constructor_tear_off_test.dart b/tests/language/typedef/aliased_constructor_tear_off_test.dart
index e63b693..7d51dfb 100644
--- a/tests/language/typedef/aliased_constructor_tear_off_test.dart
+++ b/tests/language/typedef/aliased_constructor_tear_off_test.dart
@@ -14,7 +14,7 @@
void use(Type type) {}
class C<T> {
- final T value;
+ final T x;
C(this.x);
C.named(this.x);
}
@@ -37,7 +37,7 @@
// or if instantiated with a constant type.
const List<Object> constructors = [
Special.new,
- Spceial.named,
+ Special.named,
Direct.new,
Direct.named,
Bounded.new,
@@ -64,12 +64,12 @@
Wrapping.new,
Wrapping.named,
],
- const <C<int, int> Function(C<int>)>[
+ const <C<int> Function(int)>[
Extra.new,
Extra.named,
]
];
- Expect.notNull(constructors); // Use variable.
+ Expect.isNotNull(constructors); // Use variable.
// The static type is as expected.
@@ -83,8 +83,8 @@
Bounded.new.expectStaticType<Exactly<C<T> Function<T extends num>(T)>>();
Bounded.named.expectStaticType<Exactly<C<T> Function<T extends num>(T)>>();
- Wrapping.new.expectStaticType<Exactly<C<C<T>> Function<T>(T)>>();
- Wrapping.named.expectStaticType<Exactly<C<C<T>> Function<T>(T)>>();
+ Wrapping.new.expectStaticType<Exactly<C<C<T>> Function<T>(C<T>)>>();
+ Wrapping.named.expectStaticType<Exactly<C<C<T>> Function<T>(C<T>)>>();
Extra.new.expectStaticType<Exactly<C<T> Function<T, S>(T)>>();
Extra.named.expectStaticType<Exactly<C<T> Function<T, S>(T)>>();
@@ -105,24 +105,24 @@
Extra<int, String>.named.expectStaticType<Exactly<C<int> Function(int)>>();
// Implicitly instantiated.
- contextType<C<int> Function(int)>(
- Direct<int>.new..expectStaticType<Exactly<C<int> Function(int)>>());
- contextType<C<int> Function(int)>(
- Direct<int>.named..expectStaticType<Exactly<C<int> Function(int)>>());
+ context<C<int> Function(int)>(
+ Direct.new..expectStaticType<Exactly<C<int> Function(int)>>());
+ context<C<int> Function(int)>(
+ Direct.named..expectStaticType<Exactly<C<int> Function(int)>>());
- contextType<C<int> Function(int)>(
- Bounded<int>.new..expectStaticType<Exactly<C<int> Function(int)>>());
- contextType<C<int> Function(int)>(
- Bounded<int>.named..expectStaticType<Exactly<C<int> Function(int)>>());
+ context<C<int> Function(int)>(
+ Bounded.new..expectStaticType<Exactly<C<int> Function(int)>>());
+ context<C<int> Function(int)>(
+ Bounded.named..expectStaticType<Exactly<C<int> Function(int)>>());
- contextType<C<C<int>> Function(C<int>)>(Wrapping<int>.new
+ context<C<C<int>> Function(C<int>)>(Wrapping.new
..expectStaticType<Exactly<C<C<int>> Function(C<int>)>>());
- contextType<C<C<int>> Function(C<int>)>(Wrapping<int>.named
+ context<C<C<int>> Function(C<int>)>(Wrapping.named
..expectStaticType<Exactly<C<C<int>> Function(C<int>)>>());
- contextType<C<int, String> Function(int)>(Extra<int, String>.new
+ context<C<int> Function(int)>(Extra.new
..expectStaticType<Exactly<C<int> Function(int)>>());
- contextType<C<int, String> Function(int)>(Extra<int, String>.named
+ context<C<int> Function(int)>(Extra.named
..expectStaticType<Exactly<C<int> Function(int)>>());
// Uninstantiated tear-offs always canonicalize.
@@ -176,35 +176,35 @@
// Implicit instantiation.
Expect.identical(
- contextType<C<int> Function(int)>(Direct.new),
+ context<C<int> Function(int)>(Direct.new),
C<int>.new,
);
Expect.identical(
- contextType<C<int> Function(int)>(Direct.named),
+ context<C<int> Function(int)>(Direct.named),
C<int>.named,
);
Expect.identical(
- contextType<C<int> Function(int)>(Bounded.new),
+ context<C<int> Function(int)>(Bounded.new),
C<int>.new,
);
Expect.identical(
- contextType<C<int> Function(int)>(Bounded.named),
+ context<C<int> Function(int)>(Bounded.named),
C<int>.named,
);
Expect.identical(
- contextType<C<C<int>> Function(C<int>)>(Wrapping.new),
+ context<C<C<int>> Function(C<int>)>(Wrapping.new),
C<C<int>>.new,
);
Expect.identical(
- contextType<C<C<int>> Function(C<int>)>(Wrapping.named),
+ context<C<C<int>> Function(C<int>)>(Wrapping.named),
C<C<int>>.named,
);
Expect.identical(
- contextType<D<int, String> Function()>(Swapped.new),
+ context<D<int, String> Function()>(Swapped.new),
D<int, String>.new,
);
Expect.identical(
- contextType<D<int, String> Function()>(Swapped.named),
+ context<D<int, String> Function()>(Swapped.named),
D<int, String>.named,
);
diff --git a/tests/language/typedef/aliased_type_literal_instantiation_test.dart b/tests/language/typedef/aliased_type_literal_instantiation_test.dart
index c99e904..25dc8f9 100644
--- a/tests/language/typedef/aliased_type_literal_instantiation_test.dart
+++ b/tests/language/typedef/aliased_type_literal_instantiation_test.dart
@@ -10,7 +10,7 @@
import "package:expect/expect.dart";
class C<T> {
- final T value;
+ final T x;
C(this.x);
C.named(this.x);
}
@@ -55,7 +55,7 @@
Expect.identical(e2, co);
Expect.identical(e3, ci);
- (<T>() {
+ (<T extends num>() {
// Using a non-constant type.
Expect.equals(Direct<T>, ci);
Expect.equals(Bounded<T>, ci);
diff --git a/tests/language/unsorted/refine_receiver_null_test.dart b/tests/language/unsorted/refine_receiver_null_test.dart
index 499e998..50a5fa7 100644
--- a/tests/language/unsorted/refine_receiver_null_test.dart
+++ b/tests/language/unsorted/refine_receiver_null_test.dart
@@ -7,7 +7,6 @@
// work for Object methods.
import "package:expect/expect.dart";
-import "../compiler_annotations.dart";
main() {
var a = true ? null : 42;
@@ -15,7 +14,8 @@
foo(a);
}
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
foo(a) {
var f = () => 42;
Expect.throwsNoSuchMethodError(() => a + 42);
diff --git a/tests/language/vm/optimized_guarded_field_isolates_test.dart b/tests/language/vm/optimized_guarded_field_isolates_test.dart
index 428fd8d..9278ea9 100644
--- a/tests/language/vm/optimized_guarded_field_isolates_test.dart
+++ b/tests/language/vm/optimized_guarded_field_isolates_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// VMOptions=--optimization_counter_threshold=100 --no-background_compilation
diff --git a/tests/language/vm/regress_flutter_85311_test.dart b/tests/language/vm/regress_flutter_85311_test.dart
new file mode 100644
index 0000000..122d13a
--- /dev/null
+++ b/tests/language/vm/regress_flutter_85311_test.dart
@@ -0,0 +1,34 @@
+// 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.
+
+// This is a regression test for the bug in
+// https://github.com/flutter/flutter/issues/51828.
+// Verifies that temporaries aren't incorrectly assigned types when they're
+// reused.
+
+import "package:expect/expect.dart";
+
+bool wasCalled = false;
+
+class Z {
+ bool operator ==(Object other) {
+ wasCalled = true;
+ return true;
+ }
+}
+
+class Y {
+ final dynamic v;
+ Y(this.v);
+}
+
+Future<bool> crash(dynamic y) async {
+ return (y.v == (await 7) || y == (await 9));
+}
+
+void main() async {
+ await crash(Y(Z()));
+
+ Expect.isTrue(wasCalled);
+}
diff --git a/tests/language_2/abstract/exact_selector_runtime_test.dart b/tests/language_2/abstract/exact_selector_runtime_test.dart
index 2d18f98..eb8d0c8 100644
--- a/tests/language_2/abstract/exact_selector_runtime_test.dart
+++ b/tests/language_2/abstract/exact_selector_runtime_test.dart
@@ -11,14 +11,13 @@
// methods to handle `noSuchMethod`.
import "package:expect/expect.dart";
-import "../compiler_annotations.dart";
-
- class Foo {
+class Foo {
noSuchMethod(im) => 42;
}
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
returnFoo() {
(() => 42)();
return new Foo();
diff --git a/tests/language_2/abstract/exact_selector_test.dart b/tests/language_2/abstract/exact_selector_test.dart
index 23a69e0..dff88cb 100644
--- a/tests/language_2/abstract/exact_selector_test.dart
+++ b/tests/language_2/abstract/exact_selector_test.dart
@@ -8,14 +8,13 @@
// methods to handle `noSuchMethod`.
import "package:expect/expect.dart";
-import "../compiler_annotations.dart";
-abstract
- class Foo {
+abstract class Foo {
noSuchMethod(im) => 42;
}
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
returnFoo() {
(() => 42)();
return new Foo();
diff --git a/tests/language_2/closure/regress46568_test.dart b/tests/language_2/closure/regress46568_test.dart
new file mode 100644
index 0000000..1117775
--- /dev/null
+++ b/tests/language_2/closure/regress46568_test.dart
@@ -0,0 +1,42 @@
+// 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.
+
+// @dart = 2.9
+
+import 'package:expect/expect.dart';
+
+// Regression test for https://github.com/dart-lang/sdk/issues/46568.
+
+var genericTopLevelFunctionCallCount = 0;
+var genericStaticMethodCallCount = 0;
+
+T genericTopLevelFunction<T>() {
+ genericTopLevelFunctionCallCount++;
+ return null;
+}
+
+class A {
+ static T genericStaticMethod<T>() {
+ genericStaticMethodCallCount++;
+ return null;
+ }
+}
+
+const int Function() cIntTopLevelFunction1 = genericTopLevelFunction;
+const int Function() cIntStaticMethod1 = A.genericStaticMethod;
+
+void main() {
+ // Two different const generic function instantiations should not be
+ // canonicalized to the same value.
+ Expect.isFalse(identical(cIntTopLevelFunction1, cIntStaticMethod1));
+ Expect.notEquals(cIntTopLevelFunction1, cIntStaticMethod1);
+
+ cIntTopLevelFunction1();
+ Expect.equals(1, genericTopLevelFunctionCallCount);
+ Expect.equals(0, genericStaticMethodCallCount);
+
+ cIntStaticMethod1();
+ Expect.equals(1, genericTopLevelFunctionCallCount);
+ Expect.equals(1, genericStaticMethodCallCount);
+}
diff --git a/tests/language_2/compiler_annotations.dart b/tests/language_2/compiler_annotations.dart
deleted file mode 100644
index 9264514..0000000
--- a/tests/language_2/compiler_annotations.dart
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright (c) 2013, 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.
-
-// @dart = 2.9
-
-library compiler_annotations;
-
-// This library contains annotations useful for testing.
-
-// TODO(ngeoffray): Implement in dart2js.
-class DontInline {
- const DontInline();
-}
diff --git a/tests/language_2/const/constructor_mixin2_test.dart b/tests/language_2/const/constructor_mixin2_test.dart
index 5794d86..de57333 100644
--- a/tests/language_2/const/constructor_mixin2_test.dart
+++ b/tests/language_2/const/constructor_mixin2_test.dart
@@ -17,8 +17,6 @@
{
const B(foo) : super(foo);
// ^
-// [analyzer] COMPILE_TIME_ERROR.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD
-// ^
// [analyzer] COMPILE_TIME_ERROR.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD
// ^
// [cfe] A constant constructor can't call a non-constant super constructor.
diff --git a/tests/language_2/const/map2_runtime_test.dart b/tests/language_2/const/map2_runtime_test.dart
index 5ce67f2..d9a2e80 100644
--- a/tests/language_2/const/map2_runtime_test.dart
+++ b/tests/language_2/const/map2_runtime_test.dart
@@ -15,12 +15,10 @@
class B implements A {
const B();
-
-
}
confuse(x) {
- if (new DateTime.now() == 42) return confuse(2);
+ if (DateTime.now().millisecondsSinceEpoch == 42) return confuse(2);
return x;
}
diff --git a/tests/language_2/const/map2_test.dart b/tests/language_2/const/map2_test.dart
index 55f729e..216886c 100644
--- a/tests/language_2/const/map2_test.dart
+++ b/tests/language_2/const/map2_test.dart
@@ -17,7 +17,7 @@
}
confuse(x) {
- if (new DateTime.now() == 42) return confuse(2);
+ if (DateTime.now().millisecondsSinceEpoch == 42) return confuse(2);
return x;
}
diff --git a/tests/language_2/const/map5_test.dart b/tests/language_2/const/map5_test.dart
new file mode 100644
index 0000000..4827e54
--- /dev/null
+++ b/tests/language_2/const/map5_test.dart
@@ -0,0 +1,43 @@
+// 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.
+
+// Tests lookup of type literals of user-defined classes in const maps.
+
+// @dart = 2.9
+
+import 'package:expect/expect.dart';
+
+class A {}
+
+class C<T> {}
+
+typedef F = T Function<T>();
+
+const aType = A;
+const fType = F;
+
+main() {
+ final map = const {A: 42, F: 2, 'asdf': 'fdsa'};
+ Expect.equals(42, map[getValueNonOptimized(A)]);
+ Expect.equals(42, map[getValueNonOptimized(aType)]);
+ Expect.equals(2, map[getValueNonOptimized(F)]);
+ Expect.equals(2, map[getValueNonOptimized(fType)]);
+ Expect.isTrue(map.containsKey(getValueNonOptimized(A)));
+ Expect.isTrue(map.containsKey(getValueNonOptimized(aType)));
+ Expect.isTrue(map.containsKey(getValueNonOptimized(F)));
+ Expect.isTrue(map.containsKey(getValueNonOptimized(fType)));
+}
+
+/// Returns its argument.
+///
+/// Prevents static optimizations and inlining.
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
+dynamic getValueNonOptimized(dynamic x) {
+ // DateTime.now() cannot be predicted statically, never equal to 42.
+ if (DateTime.now().millisecondsSinceEpoch == 42) {
+ return getValueNonOptimized(2);
+ }
+ return x;
+}
diff --git a/tests/language_2/const/map_hashcode_override2_test.dart b/tests/language_2/const/map_hashcode_override2_test.dart
index 86ced20..a5add26 100644
--- a/tests/language_2/const/map_hashcode_override2_test.dart
+++ b/tests/language_2/const/map_hashcode_override2_test.dart
@@ -9,9 +9,13 @@
/// Returns its argument.
///
/// Prevents static optimizations and inlining.
-getValueNonOptimized(x) {
- // DateTime.now() cannot be predicted statically, never equal to ASCII 42 '*'.
- if (new DateTime.now() == 42) return getValueNonOptimized(2);
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
+dynamic getValueNonOptimized(dynamic x) {
+ // DateTime.now() cannot be predicted statically, never equal to 42.
+ if (DateTime.now().millisecondsSinceEpoch == 42) {
+ return getValueNonOptimized(2);
+ }
return x;
}
diff --git a/tests/language_2/const/map_hashcode_override_test.dart b/tests/language_2/const/map_hashcode_override_test.dart
index 47223e7..a696d36 100644
--- a/tests/language_2/const/map_hashcode_override_test.dart
+++ b/tests/language_2/const/map_hashcode_override_test.dart
@@ -9,9 +9,13 @@
/// Returns its argument.
///
/// Prevents static optimizations and inlining.
-getValueNonOptimized(x) {
- // DateTime.now() cannot be predicted statically, never equal to ASCII 42 '*'.
- if (new DateTime.now() == 42) return getValueNonOptimized(2);
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
+dynamic getValueNonOptimized(dynamic x) {
+ // DateTime.now() cannot be predicted statically, never equal to 42.
+ if (DateTime.now().millisecondsSinceEpoch == 42) {
+ return getValueNonOptimized(2);
+ }
return x;
}
diff --git a/tests/language_2/const/map_null_lookup_test.dart b/tests/language_2/const/map_null_lookup_test.dart
new file mode 100644
index 0000000..612f3ca
--- /dev/null
+++ b/tests/language_2/const/map_null_lookup_test.dart
@@ -0,0 +1,31 @@
+// 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.
+
+// Tests lookup of null in const maps.
+
+// @dart = 2.9
+
+import 'package:expect/expect.dart';
+
+main() {
+ final map1 = const {1: 42, null: 2, 'asdf': 'fdsa'};
+ Expect.equals(2, map1[getValueNonOptimized(null)]);
+ Expect.isTrue(map1.containsKey(null));
+ final map2 = const {1: 42, 2: 2, 'asdf': 'fdsa'};
+ Expect.equals(null, map2[getValueNonOptimized(null)]);
+ Expect.isFalse(map2.containsKey(null));
+}
+
+/// Returns its argument.
+///
+/// Prevents static optimizations and inlining.
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
+dynamic getValueNonOptimized(dynamic x) {
+ // DateTime.now() cannot be predicted statically, never equal to 42.
+ if (DateTime.now().millisecondsSinceEpoch == 42) {
+ return getValueNonOptimized(2);
+ }
+ return x;
+}
diff --git a/tests/language_2/const/map_test.dart b/tests/language_2/const/map_test.dart
index bbd4a8f..3ffcf7a 100644
--- a/tests/language_2/const/map_test.dart
+++ b/tests/language_2/const/map_test.dart
@@ -9,9 +9,13 @@
/// Returns its argument.
///
/// Prevents static optimizations and inlining.
-getValueNonOptimized(x) {
- // DateTime.now() cannot be predicted statically, never equal to ASCII 42 '*'.
- if (new DateTime.now() == 42) return getValueNonOptimized(2);
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
+dynamic getValueNonOptimized(dynamic x) {
+ // DateTime.now() cannot be predicted statically, never equal to 42.
+ if (DateTime.now().millisecondsSinceEpoch == 42) {
+ return getValueNonOptimized(2);
+ }
return x;
}
diff --git a/tests/language_2/const/set5_test.dart b/tests/language_2/const/set5_test.dart
new file mode 100644
index 0000000..dc0088d
--- /dev/null
+++ b/tests/language_2/const/set5_test.dart
@@ -0,0 +1,43 @@
+// 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.
+
+// Tests lookup of type literals of user-defined classes in const sets.
+
+// @dart = 2.9
+
+import 'package:expect/expect.dart';
+
+class A {}
+
+class C<T> {}
+
+typedef F = T Function<T>();
+
+const aType = A;
+const fType = F;
+
+main() {
+ final set1 = const {A, 1, 'asdf', F};
+ Expect.isTrue(set1.contains(getValueNonOptimized(A)));
+ Expect.isTrue(set1.contains(getValueNonOptimized(aType)));
+ Expect.isTrue(set1.contains(getValueNonOptimized(F)));
+ Expect.isTrue(set1.contains(getValueNonOptimized(fType)));
+ Expect.equals(A, set1.lookup(getValueNonOptimized(A)));
+ Expect.equals(A, set1.lookup(getValueNonOptimized(aType)));
+ Expect.equals(F, set1.lookup(getValueNonOptimized(F)));
+ Expect.equals(F, set1.lookup(getValueNonOptimized(fType)));
+}
+
+/// Returns its argument.
+///
+/// Prevents static optimizations and inlining.
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
+dynamic getValueNonOptimized(dynamic x) {
+ // DateTime.now() cannot be predicted statically, never equal to 42.
+ if (DateTime.now().millisecondsSinceEpoch == 42) {
+ return getValueNonOptimized(2);
+ }
+ return x;
+}
diff --git a/tests/language_2/const/set_hashcode_override2_test.dart b/tests/language_2/const/set_hashcode_override2_test.dart
index 7035373..0be2136 100644
--- a/tests/language_2/const/set_hashcode_override2_test.dart
+++ b/tests/language_2/const/set_hashcode_override2_test.dart
@@ -9,9 +9,13 @@
/// Returns its argument.
///
/// Prevents static optimizations and inlining.
-getValueNonOptimized(x) {
- // DateTime.now() cannot be predicted statically, never equal to ASCII 42 '*'.
- if (new DateTime.now() == 42) return getValueNonOptimized(2);
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
+dynamic getValueNonOptimized(dynamic x) {
+ // DateTime.now() cannot be predicted statically, never equal to 42.
+ if (DateTime.now().millisecondsSinceEpoch == 42) {
+ return getValueNonOptimized(2);
+ }
return x;
}
diff --git a/tests/language_2/const/set_null_lookup_test.dart b/tests/language_2/const/set_null_lookup_test.dart
new file mode 100644
index 0000000..1e7a09a
--- /dev/null
+++ b/tests/language_2/const/set_null_lookup_test.dart
@@ -0,0 +1,31 @@
+// 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.
+
+// Tests lookup of null in const sets.
+
+// @dart = 2.9
+
+import 'package:expect/expect.dart';
+
+main() {
+ final set1 = const {null, 1, 'asdf'};
+ Expect.isTrue(set1.contains(getValueNonOptimized(null)));
+ Expect.equals(null, set1.lookup(null));
+ final set2 = const {42, 1, 'asdf'};
+ Expect.isFalse(set2.contains(getValueNonOptimized(null)));
+ Expect.equals(null, set2.lookup(null));
+}
+
+/// Returns its argument.
+///
+/// Prevents static optimizations and inlining.
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
+dynamic getValueNonOptimized(dynamic x) {
+ // DateTime.now() cannot be predicted statically, never equal to 42.
+ if (DateTime.now().millisecondsSinceEpoch == 42) {
+ return getValueNonOptimized(2);
+ }
+ return x;
+}
diff --git a/tests/language_2/constructor/multiple_field_assignment_constructor_test.dart b/tests/language_2/constructor/multiple_field_assignment_constructor_test.dart
index 48ee8b9..6e76204 100644
--- a/tests/language_2/constructor/multiple_field_assignment_constructor_test.dart
+++ b/tests/language_2/constructor/multiple_field_assignment_constructor_test.dart
@@ -5,7 +5,6 @@
// @dart = 2.9
import "package:expect/expect.dart";
-import "../compiler_annotations.dart";
var a = [null];
@@ -13,7 +12,8 @@
var foo;
var bar;
- @DontInline()
+ @pragma('vm:never-inline')
+ @pragma('dart2js:noInline')
A() {
// Currently defeat inlining by using a closure.
bar = () => 42;
@@ -26,7 +26,8 @@
var foo;
var bar;
- @DontInline()
+ @pragma('vm:never-inline')
+ @pragma('dart2js:noInline')
B() {
// Currently defeat inlining by using a closure.
bar = () => 42;
@@ -46,7 +47,8 @@
new B();
}
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
bar() {
// Currently defeat inlining by using a closure.
Expect.throwsNoSuchMethodError(() => new A().foo + 42);
diff --git a/tests/language_2/language_2.status b/tests/language_2/language_2.status
index 4cb75ed..ad85c7e 100644
--- a/tests/language_2/language_2.status
+++ b/tests/language_2/language_2.status
@@ -45,6 +45,4 @@
[ $hot_reload || $hot_reload_rollback ]
regress/regress22780_test/01: Crash # Issue 29094
-regress/regress23244_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-vm/optimized_guarded_field_isolates_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
vm/optimized_stacktrace_test: Slow, Pass
diff --git a/tests/language_2/map/literal15_test.dart b/tests/language_2/map/literal15_test.dart
new file mode 100644
index 0000000..3ce3460
--- /dev/null
+++ b/tests/language_2/map/literal15_test.dart
@@ -0,0 +1,54 @@
+// 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.
+
+// @dart = 2.9
+
+// Test the use of `null` keys in const maps. In versions before 2.12, when
+// nullable types were introduced, types were nullable so it was legal to have
+// `null` keys in maps.
+
+library map_literal15_test;
+
+import "package:expect/expect.dart";
+
+void test1() {
+ var m1 = const <String, int>{null: 10, 'null': 20};
+ Expect.isTrue(m1.containsKey(null));
+ Expect.isTrue(m1.containsKey(undefined()));
+ Expect.equals(10, m1[null]);
+ Expect.equals(10, m1[undefined()]);
+ Expect.isTrue(m1.containsKey('null'));
+ Expect.equals(20, m1['null']);
+ // The '.keys' carry the 'String' type
+ Expect.type<Iterable<String>>(m1.keys);
+ Expect.type<Iterable<Comparable>>(m1.keys);
+ Expect.notType<Iterable<int>>(m1.keys);
+}
+
+void test2() {
+ var m2 = const <Comparable, int>{null: 10, 'null': 20};
+ Expect.isTrue(m2.containsKey(null));
+ Expect.isTrue(m2.containsKey(undefined()));
+ Expect.equals(10, m2[null]);
+ Expect.equals(10, m2[undefined()]);
+ Expect.isTrue(m2.containsKey('null'));
+ Expect.equals(20, m2['null']);
+ // The '.keys' carry the 'Comparable' type
+ Expect.notType<Iterable<String>>(m2.keys);
+ Expect.type<Iterable<Comparable>>(m2.keys);
+ Expect.notType<Iterable<int>>(m2.keys);
+}
+
+main() {
+ test1();
+ test2();
+}
+
+// Calling `undefined()` gives us a `null` that is implemented as JavaScript
+// `undefined` on dart2js.
+@pragma('dart2js:noInline')
+dynamic get undefined => _undefined;
+
+@pragma('dart2js:noInline')
+void _undefined() {}
diff --git a/tests/language_2/optimize/inferrer_constructor2_test.dart b/tests/language_2/optimize/inferrer_constructor2_test.dart
index 3b8d026..3db6e22 100644
--- a/tests/language_2/optimize/inferrer_constructor2_test.dart
+++ b/tests/language_2/optimize/inferrer_constructor2_test.dart
@@ -9,13 +9,13 @@
// inlined.
import "package:expect/expect.dart";
-import "../compiler_annotations.dart";
class A {
var foo;
var bar;
- @DontInline()
+ @pragma('vm:never-inline')
+ @pragma('dart2js:noInline')
A() {
// Currently defeat inlining by using a closure.
bar = () => 42;
@@ -35,7 +35,8 @@
class B {
var bar;
var closure;
- @DontInline()
+ @pragma('vm:never-inline')
+ @pragma('dart2js:noInline')
B() {
// Currently defeat inlining by using a closure.
closure = () => 42;
@@ -43,7 +44,8 @@
}
}
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
bar() {
// Make sure B's constructor is analyzed first by surrounding the
// body by two allocations.
@@ -54,7 +56,8 @@
new B();
}
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
codegenLast() {
// This assignment currently defeats simple type inference, but not
// the optimistic inferrer.
diff --git a/tests/language_2/optimize/inferrer_constructor3_test.dart b/tests/language_2/optimize/inferrer_constructor3_test.dart
index ab89c9d..91c5e8e 100644
--- a/tests/language_2/optimize/inferrer_constructor3_test.dart
+++ b/tests/language_2/optimize/inferrer_constructor3_test.dart
@@ -9,7 +9,6 @@
// inlined.
import "package:expect/expect.dart";
-import "../compiler_annotations.dart";
class A {
var field;
@@ -26,14 +25,16 @@
bar();
}
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
doIt() {
() => 42;
var c = new A(null);
Expect.throwsNoSuchMethodError(() => c.field + 42);
}
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
bar() {
() => 42;
return inlineLevel1();
diff --git a/tests/language_2/optimize/inferrer_named_parameter_test.dart b/tests/language_2/optimize/inferrer_named_parameter_test.dart
index a2edd32..fd95b33 100644
--- a/tests/language_2/optimize/inferrer_named_parameter_test.dart
+++ b/tests/language_2/optimize/inferrer_named_parameter_test.dart
@@ -8,9 +8,9 @@
// correctly infer optional named parameters.
import "package:expect/expect.dart";
-import "../compiler_annotations.dart";
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
foo({path}) {
() => 42;
return path;
diff --git a/tests/language_2/optimize/inferrer_synthesized_super_constructor_test.dart b/tests/language_2/optimize/inferrer_synthesized_super_constructor_test.dart
index 07db1d2..8b686ae 100644
--- a/tests/language_2/optimize/inferrer_synthesized_super_constructor_test.dart
+++ b/tests/language_2/optimize/inferrer_synthesized_super_constructor_test.dart
@@ -4,10 +4,9 @@
// @dart = 2.9
-import '../compiler_annotations.dart';
-
class A {
- @DontInline()
+ @pragma('vm:never-inline')
+ @pragma('dart2js:noInline')
A([a]) {
() => 42;
if (a != null) throw 'Test failed';
diff --git a/tests/language_2/regress/regress12284_test.dart b/tests/language_2/regress/regress12284_test.dart
index 25a91f1..4c5b0bb 100644
--- a/tests/language_2/regress/regress12284_test.dart
+++ b/tests/language_2/regress/regress12284_test.dart
@@ -5,12 +5,12 @@
// @dart = 2.9
import "package:expect/expect.dart";
-import "../compiler_annotations.dart";
class A {
int field;
- @DontInline()
+ @pragma('vm:never-inline')
+ @pragma('dart2js:noInline')
A(param) {
// Currently defeat inlining by using a closure.
var bar = () => 42;
diff --git a/tests/language_2/regress/regress12336_test.dart b/tests/language_2/regress/regress12336_test.dart
index 9c62ae0..df72870 100644
--- a/tests/language_2/regress/regress12336_test.dart
+++ b/tests/language_2/regress/regress12336_test.dart
@@ -8,7 +8,6 @@
// [foo].
import "package:expect/expect.dart";
-import "../compiler_annotations.dart";
main() {
var result = foo(1, 2);
@@ -20,7 +19,8 @@
Expect.listEquals([], result[1]);
}
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
foo(a, b) {
() => 42;
if (a is List) {
diff --git a/tests/language_2/regress/regress15720_test.dart b/tests/language_2/regress/regress15720_test.dart
index f07405e..14d5b18 100644
--- a/tests/language_2/regress/regress15720_test.dart
+++ b/tests/language_2/regress/regress15720_test.dart
@@ -9,7 +9,7 @@
class B {}
confuse(x) {
- if (new DateTime.now() == 42) return confuse(x);
+ if (DateTime.now().millisecondsSinceEpoch == 42) return confuse(x);
return x;
}
diff --git a/tests/language_2/regress/regress23244_test.dart b/tests/language_2/regress/regress23244_test.dart
index 87e244d..1fb8a80 100644
--- a/tests/language_2/regress/regress23244_test.dart
+++ b/tests/language_2/regress/regress23244_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// Regression test case for http://dartbug.com/23244
diff --git a/tests/language_2/regress/regress46550_test.dart b/tests/language_2/regress/regress46550_test.dart
new file mode 100644
index 0000000..9b609da
--- /dev/null
+++ b/tests/language_2/regress/regress46550_test.dart
@@ -0,0 +1,21 @@
+// 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.
+
+// VMOptions=--optimization_counter_threshold=100 --deterministic
+
+import "package:expect/expect.dart";
+
+typedef void test1<T extends num>();
+
+void t1<T extends int>() {
+ Expect.equals(int, T);
+}
+
+const test1 res1 = t1;
+
+main() {
+ for (int i = 0; i < 120; ++i) {
+ res1();
+ }
+}
diff --git a/tests/language_2/string/optimizations_test.dart b/tests/language_2/string/optimizations_test.dart
index 7b8ea64..5c2bb9de 100644
--- a/tests/language_2/string/optimizations_test.dart
+++ b/tests/language_2/string/optimizations_test.dart
@@ -8,15 +8,16 @@
// correctly infer optional named parameters.
import "package:expect/expect.dart";
-import "../compiler_annotations.dart";
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
foo({path}) {
() => 42;
return path.toString();
}
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
bar({path}) {
() => 42;
return path;
diff --git a/tests/language_2/unsorted/refine_receiver_null_test.dart b/tests/language_2/unsorted/refine_receiver_null_test.dart
index 46df819..df580ba 100644
--- a/tests/language_2/unsorted/refine_receiver_null_test.dart
+++ b/tests/language_2/unsorted/refine_receiver_null_test.dart
@@ -9,7 +9,6 @@
// work for Object methods.
import "package:expect/expect.dart";
-import "../compiler_annotations.dart";
main() {
var a = true ? null : 42;
@@ -17,7 +16,8 @@
foo(a);
}
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
foo(a) {
var f = () => 42;
Expect.throwsNoSuchMethodError(() => a + 42);
diff --git a/tests/language_2/vm/optimized_guarded_field_isolates_test.dart b/tests/language_2/vm/optimized_guarded_field_isolates_test.dart
index c08c957..be65d88 100644
--- a/tests/language_2/vm/optimized_guarded_field_isolates_test.dart
+++ b/tests/language_2/vm/optimized_guarded_field_isolates_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// VMOptions=--optimization_counter_threshold=100 --no-background_compilation
diff --git a/tests/language_2/vm/regress_flutter_85311_test.dart b/tests/language_2/vm/regress_flutter_85311_test.dart
new file mode 100644
index 0000000..a3458f9
--- /dev/null
+++ b/tests/language_2/vm/regress_flutter_85311_test.dart
@@ -0,0 +1,36 @@
+// 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.
+
+// @dart = 2.9
+
+// This is a regression test for the bug in
+// https://github.com/flutter/flutter/issues/51828.
+// Verifies that temporaries aren't incorrectly assigned types when they're
+// reused.
+
+import "package:expect/expect.dart";
+
+bool wasCalled = false;
+
+class Z {
+ bool operator ==(Object other) {
+ wasCalled = true;
+ return true;
+ }
+}
+
+class Y {
+ final dynamic v;
+ Y(this.v);
+}
+
+Future<bool> crash(dynamic y) async {
+ return (y.v == (await 7) || y == (await 9));
+}
+
+void main() async {
+ await crash(Y(Z()));
+
+ Expect.isTrue(wasCalled);
+}
diff --git a/tests/lib/html/js_typed_interop_lazy_test.dart b/tests/lib/html/js_typed_interop_lazy_test.dart
index 63c578d..1825174 100644
--- a/tests/lib/html/js_typed_interop_lazy_test.dart
+++ b/tests/lib/html/js_typed_interop_lazy_test.dart
@@ -142,10 +142,9 @@
expect(new Object() is! AnonClass2, isTrue);
expect(<AnonClass>[] is List<AnonClass>, isTrue);
- // TODO(jacobr): why doesn't this test pass?
- // expect(<AnonClass>[] is List<AnonClass2>, isTrue);
+ expect(<AnonClass>[] is List<AnonClass2>, isTrue);
expect(<int>[] is! List<AnonClass>, isTrue);
- expect(<AnonClass>[] is! List<LazyClass>, isTrue); //# 01: ok
+ expect(<AnonClass>[] is List<LazyClass>, isTrue);
expect(<int>[] is! List<LazyClass>, isTrue);
expect(<LazyClass>[] is List<LazyClass>, isTrue);
@@ -234,10 +233,9 @@
expect(new Object() is! AnonClass2, isTrue);
expect(<AnonClass>[] is List<AnonClass>, isTrue);
- // TODO(jacobr): why doesn't this test pass?
- // expect(<AnonClass>[] is List<AnonClass2>, isTrue);
+ expect(<AnonClass>[] is List<AnonClass2>, isTrue);
expect(<int>[] is! List<AnonClass>, isTrue);
- expect(<AnonClass>[] is! List<NestedLazyClass>, isTrue); //# 01: ok
+ expect(<AnonClass>[] is List<NestedLazyClass>, isTrue);
expect(<int>[] is! List<NestedLazyClass>, isTrue);
expect(<NestedLazyClass>[] is List<NestedLazyClass>, isTrue);
diff --git a/tests/lib/isolate/bool_from_environment_default_value_test.dart b/tests/lib/isolate/bool_from_environment_default_value_test.dart
index 65992ab..fb9d49b 100644
--- a/tests/lib/isolate/bool_from_environment_default_value_test.dart
+++ b/tests/lib/isolate/bool_from_environment_default_value_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import "dart:isolate";
diff --git a/tests/lib/isolate/capability_test.dart b/tests/lib/isolate/capability_test.dart
index 4c09118..fd6c4d3 100644
--- a/tests/lib/isolate/capability_test.dart
+++ b/tests/lib/isolate/capability_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import "dart:isolate";
diff --git a/tests/lib/isolate/compile_time_error_test.dart b/tests/lib/isolate/compile_time_error_test.dart
index 866cb3b..21197fa 100644
--- a/tests/lib/isolate/compile_time_error_test.dart
+++ b/tests/lib/isolate/compile_time_error_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// Dart test program for testing that errors thrown from isolates are
diff --git a/tests/lib/isolate/count_test.dart b/tests/lib/isolate/count_test.dart
index 2315e12..cc96b3f 100644
--- a/tests/lib/isolate/count_test.dart
+++ b/tests/lib/isolate/count_test.dart
@@ -2,7 +2,8 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
// VMOptions=--no-enable-isolate-groups
library CountTest;
diff --git a/tests/lib/isolate/cross_isolate_message_test.dart b/tests/lib/isolate/cross_isolate_message_test.dart
index 3b406cc..ede3792 100644
--- a/tests/lib/isolate/cross_isolate_message_test.dart
+++ b/tests/lib/isolate/cross_isolate_message_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// Dart test program for testing that isolates can communicate to isolates
diff --git a/tests/lib/isolate/deferred_in_isolate2_test.dart b/tests/lib/isolate/deferred_in_isolate2_test.dart
index 9eddc1c..52e5428 100644
--- a/tests/lib/isolate/deferred_in_isolate2_test.dart
+++ b/tests/lib/isolate/deferred_in_isolate2_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
library deferred_in_isolate2_test;
diff --git a/tests/lib/isolate/deferred_in_isolate_test.dart b/tests/lib/isolate/deferred_in_isolate_test.dart
index 167815b..d44f075 100644
--- a/tests/lib/isolate/deferred_in_isolate_test.dart
+++ b/tests/lib/isolate/deferred_in_isolate_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// Test that deferred libraries are supported from isolates other than the root
diff --git a/tests/lib/isolate/enum_const_test.dart b/tests/lib/isolate/enum_const_test.dart
index 3766cb5..0a57f13 100644
--- a/tests/lib/isolate/enum_const_test.dart
+++ b/tests/lib/isolate/enum_const_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import "dart:isolate";
diff --git a/tests/lib/isolate/error_at_spawn_test.dart b/tests/lib/isolate/error_at_spawn_test.dart
index dcb033b..c22f41e 100644
--- a/tests/lib/isolate/error_at_spawn_test.dart
+++ b/tests/lib/isolate/error_at_spawn_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
library error_at_spawn;
diff --git a/tests/lib/isolate/error_at_spawnuri_test.dart b/tests/lib/isolate/error_at_spawnuri_test.dart
index 2c33f11..6d0e073 100644
--- a/tests/lib/isolate/error_at_spawnuri_test.dart
+++ b/tests/lib/isolate/error_at_spawnuri_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
library error_at_spawnuri;
diff --git a/tests/lib/isolate/error_exit_at_spawn_test.dart b/tests/lib/isolate/error_exit_at_spawn_test.dart
index 7033c1f..9543025 100644
--- a/tests/lib/isolate/error_exit_at_spawn_test.dart
+++ b/tests/lib/isolate/error_exit_at_spawn_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
library error_exit_at_spawn;
diff --git a/tests/lib/isolate/error_exit_at_spawnuri_test.dart b/tests/lib/isolate/error_exit_at_spawnuri_test.dart
index 7f4f4d6..cf32b98 100644
--- a/tests/lib/isolate/error_exit_at_spawnuri_test.dart
+++ b/tests/lib/isolate/error_exit_at_spawnuri_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
library error_exit_at_spawnuri;
diff --git a/tests/lib/isolate/exit_at_spawn_test.dart b/tests/lib/isolate/exit_at_spawn_test.dart
index 3feb840..4a2574e 100644
--- a/tests/lib/isolate/exit_at_spawn_test.dart
+++ b/tests/lib/isolate/exit_at_spawn_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
library exit_at_spawn;
diff --git a/tests/lib/isolate/exit_at_spawnuri_test.dart b/tests/lib/isolate/exit_at_spawnuri_test.dart
index e77fe04..5bb9ed8 100644
--- a/tests/lib/isolate/exit_at_spawnuri_test.dart
+++ b/tests/lib/isolate/exit_at_spawnuri_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
library exit_at_spawn;
diff --git a/tests/lib/isolate/function_send1_test.dart b/tests/lib/isolate/function_send1_test.dart
index 4390735..1955c96 100644
--- a/tests/lib/isolate/function_send1_test.dart
+++ b/tests/lib/isolate/function_send1_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import "dart:isolate";
diff --git a/tests/lib/isolate/function_send_test.dart b/tests/lib/isolate/function_send_test.dart
index ea75c63..82b6123 100644
--- a/tests/lib/isolate/function_send_test.dart
+++ b/tests/lib/isolate/function_send_test.dart
@@ -2,7 +2,8 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
// VMOptions=--no-enable-isolate-groups
import "dart:isolate";
diff --git a/tests/lib/isolate/handle_error2_test.dart b/tests/lib/isolate/handle_error2_test.dart
index e3e3b66..8e36364 100644
--- a/tests/lib/isolate/handle_error2_test.dart
+++ b/tests/lib/isolate/handle_error2_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
library handle_error_test;
diff --git a/tests/lib/isolate/handle_error3_test.dart b/tests/lib/isolate/handle_error3_test.dart
index 165e210..170f130 100644
--- a/tests/lib/isolate/handle_error3_test.dart
+++ b/tests/lib/isolate/handle_error3_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
library handle_error_test;
diff --git a/tests/lib/isolate/handle_error_test.dart b/tests/lib/isolate/handle_error_test.dart
index fad1719..a453072 100644
--- a/tests/lib/isolate/handle_error_test.dart
+++ b/tests/lib/isolate/handle_error_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
library handle_error_test;
diff --git a/tests/lib/isolate/illegal_msg_function_test.dart b/tests/lib/isolate/illegal_msg_function_test.dart
index 5fcaf8a..5b5aa45 100644
--- a/tests/lib/isolate/illegal_msg_function_test.dart
+++ b/tests/lib/isolate/illegal_msg_function_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
library illegal_msg_function_test;
diff --git a/tests/lib/isolate/illegal_msg_mirror_test.dart b/tests/lib/isolate/illegal_msg_mirror_test.dart
index 7fd70ab..a15572d 100644
--- a/tests/lib/isolate/illegal_msg_mirror_test.dart
+++ b/tests/lib/isolate/illegal_msg_mirror_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
library illegal_msg_mirror_test;
diff --git a/tests/lib/isolate/int32_length_overflow_test.dart b/tests/lib/isolate/int32_length_overflow_test.dart
index b7f51cf..85e2bd7 100644
--- a/tests/lib/isolate/int32_length_overflow_test.dart
+++ b/tests/lib/isolate/int32_length_overflow_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import "dart:async";
diff --git a/tests/lib/isolate/int_from_environment_default_value_test.dart b/tests/lib/isolate/int_from_environment_default_value_test.dart
index 7bf0761..af7ccac 100644
--- a/tests/lib/isolate/int_from_environment_default_value_test.dart
+++ b/tests/lib/isolate/int_from_environment_default_value_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import "dart:isolate";
diff --git a/tests/lib/isolate/isolate_complex_messages_test.dart b/tests/lib/isolate/isolate_complex_messages_test.dart
index 606b3af..bbf728d 100644
--- a/tests/lib/isolate/isolate_complex_messages_test.dart
+++ b/tests/lib/isolate/isolate_complex_messages_test.dart
@@ -2,7 +2,8 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
// VMOptions=--no-enable-isolate-groups
// Dart test program for testing isolate communication with
diff --git a/tests/lib/isolate/isolate_current_test.dart b/tests/lib/isolate/isolate_current_test.dart
index b4b0baea..1c2f1bb 100644
--- a/tests/lib/isolate/isolate_current_test.dart
+++ b/tests/lib/isolate/isolate_current_test.dart
@@ -2,7 +2,8 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
// VMOptions=--no-enable-isolate-groups
library isolate_current_test;
diff --git a/tests/lib/isolate/isolate_import_test.dart b/tests/lib/isolate/isolate_import_test.dart
index 0438a4e..781e13c 100644
--- a/tests/lib/isolate/isolate_import_test.dart
+++ b/tests/lib/isolate/isolate_import_test.dart
@@ -2,15 +2,15 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
library IsolateImportNegativeTest;
// Omitting the following import is an error:
-/* // //# 01: runtime error, compile-time error
+/* //# 01: compile-time error
import 'dart:isolate';
-*/ // //# 01: continued
+*/ //# 01: continued
import 'package:async_helper/async_helper.dart';
void entry(msg) {}
diff --git a/tests/lib/isolate/issue_21398_parent_isolate1_test.dart b/tests/lib/isolate/issue_21398_parent_isolate1_test.dart
index 78f19d5..6a0b458 100644
--- a/tests/lib/isolate/issue_21398_parent_isolate1_test.dart
+++ b/tests/lib/isolate/issue_21398_parent_isolate1_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import 'dart:isolate';
diff --git a/tests/lib/isolate/issue_21398_parent_isolate2_test.dart b/tests/lib/isolate/issue_21398_parent_isolate2_test.dart
index d092152..feee51b 100644
--- a/tests/lib/isolate/issue_21398_parent_isolate2_test.dart
+++ b/tests/lib/isolate/issue_21398_parent_isolate2_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import 'dart:isolate';
diff --git a/tests/lib/isolate/issue_21398_parent_isolate_test.dart b/tests/lib/isolate/issue_21398_parent_isolate_test.dart
index 2dcb5c1..5264827 100644
--- a/tests/lib/isolate/issue_21398_parent_isolate_test.dart
+++ b/tests/lib/isolate/issue_21398_parent_isolate_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import 'dart:isolate';
diff --git a/tests/lib/isolate/issue_22778_test.dart b/tests/lib/isolate/issue_22778_test.dart
index 67d90a2..28107cc 100644
--- a/tests/lib/isolate/issue_22778_test.dart
+++ b/tests/lib/isolate/issue_22778_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import "dart:isolate";
diff --git a/tests/lib/isolate/issue_24243_parent_isolate_test.dart b/tests/lib/isolate/issue_24243_parent_isolate_test.dart
index 92a9549..c38e5e4 100644
--- a/tests/lib/isolate/issue_24243_parent_isolate_test.dart
+++ b/tests/lib/isolate/issue_24243_parent_isolate_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import 'dart:collection';
diff --git a/tests/lib/isolate/issue_35626_test.dart b/tests/lib/isolate/issue_35626_test.dart
index 26ee9c6..2b392ad 100644
--- a/tests/lib/isolate/issue_35626_test.dart
+++ b/tests/lib/isolate/issue_35626_test.dart
@@ -2,7 +2,8 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
// VMOptions=--no-enable-isolate-groups
// Tests that sets of enums can be set through ports.
diff --git a/tests/lib/isolate/issue_6610_test.dart b/tests/lib/isolate/issue_6610_test.dart
index 9a37e51..962955e 100644
--- a/tests/lib/isolate/issue_6610_test.dart
+++ b/tests/lib/isolate/issue_6610_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// Testing that Isolate.spawn copies the source code of the parent isolate,
diff --git a/tests/lib/isolate/kill2_test.dart b/tests/lib/isolate/kill2_test.dart
index 0c946f0..9391fc8 100644
--- a/tests/lib/isolate/kill2_test.dart
+++ b/tests/lib/isolate/kill2_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import "dart:isolate";
diff --git a/tests/lib/isolate/kill_infinite_loop_in_initializer_test.dart b/tests/lib/isolate/kill_infinite_loop_in_initializer_test.dart
new file mode 100644
index 0000000..1d41541
--- /dev/null
+++ b/tests/lib/isolate/kill_infinite_loop_in_initializer_test.dart
@@ -0,0 +1,44 @@
+// 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.
+
+// VMOptions=--enable-isolate-groups
+// VMOptions=--no-enable-isolate-groups
+
+// Regression test against out-of-band messages being blocked during lazy
+// static field initialization.
+
+import "dart:isolate";
+import "dart:async";
+import "package:expect/expect.dart";
+import "package:async_helper/async_helper.dart";
+
+dynamic staticFieldWithBadInitializer = badInitializer();
+
+badInitializer() {
+ print("badInitializer");
+ for (;;) {}
+ return 42; // Unreachable.
+}
+
+child(message) {
+ print("child");
+ RawReceivePort port = new RawReceivePort();
+ print(staticFieldWithBadInitializer);
+ port.close(); // Unreachable.
+}
+
+void main() {
+ asyncStart();
+ Isolate.spawn(child, null).then((Isolate isolate) {
+ print("spawned");
+ late RawReceivePort exitSignal;
+ exitSignal = new RawReceivePort((_) {
+ print("onExit");
+ exitSignal.close();
+ asyncEnd();
+ });
+ isolate.addOnExitListener(exitSignal.sendPort);
+ isolate.kill(priority: Isolate.immediate);
+ });
+}
diff --git a/tests/lib/isolate/kill_self_synchronously_test.dart b/tests/lib/isolate/kill_self_synchronously_test.dart
index 1cfc4ff..19f3a2e 100644
--- a/tests/lib/isolate/kill_self_synchronously_test.dart
+++ b/tests/lib/isolate/kill_self_synchronously_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import "dart:isolate";
diff --git a/tests/lib/isolate/kill_self_test.dart b/tests/lib/isolate/kill_self_test.dart
index ace983f..157b30f 100644
--- a/tests/lib/isolate/kill_self_test.dart
+++ b/tests/lib/isolate/kill_self_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import "dart:isolate";
diff --git a/tests/lib/isolate/kill_test.dart b/tests/lib/isolate/kill_test.dart
index 7c97bfd..07e0dfe8 100644
--- a/tests/lib/isolate/kill_test.dart
+++ b/tests/lib/isolate/kill_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import "dart:isolate";
diff --git a/tests/lib/isolate/large_byte_data_leak_test.dart b/tests/lib/isolate/large_byte_data_leak_test.dart
index fe2fda1..9797a54 100644
--- a/tests/lib/isolate/large_byte_data_leak_test.dart
+++ b/tests/lib/isolate/large_byte_data_leak_test.dart
@@ -2,7 +2,8 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
// VMOptions=--no-enable-isolate-groups
import "dart:async";
diff --git a/tests/lib/isolate/large_byte_data_test.dart b/tests/lib/isolate/large_byte_data_test.dart
index 3861e5c..8a78238 100644
--- a/tests/lib/isolate/large_byte_data_test.dart
+++ b/tests/lib/isolate/large_byte_data_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import "dart:async";
diff --git a/tests/lib/isolate/mandel_isolate_test.dart b/tests/lib/isolate/mandel_isolate_test.dart
index 22f7760..50d564a 100644
--- a/tests/lib/isolate/mandel_isolate_test.dart
+++ b/tests/lib/isolate/mandel_isolate_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
library MandelIsolateTest;
diff --git a/tests/lib/isolate/message2_test.dart b/tests/lib/isolate/message2_test.dart
index 422b499..fd7550c 100644
--- a/tests/lib/isolate/message2_test.dart
+++ b/tests/lib/isolate/message2_test.dart
@@ -2,7 +2,8 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
// VMOptions=--no-enable-isolate-groups
// Dart test program for testing serialization of messages.
diff --git a/tests/lib/isolate/message3_test.dart b/tests/lib/isolate/message3_test.dart
index bb8a007fa..37bf159 100644
--- a/tests/lib/isolate/message3_test.dart
+++ b/tests/lib/isolate/message3_test.dart
@@ -2,7 +2,8 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
// VMOptions=--no-enable-isolate-groups
// Dart test program for testing serialization of messages.
diff --git a/tests/lib/isolate/message4_test.dart b/tests/lib/isolate/message4_test.dart
index 3cc4641..4644ddb 100644
--- a/tests/lib/isolate/message4_test.dart
+++ b/tests/lib/isolate/message4_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// Dart test program for testing serialization of messages with static
diff --git a/tests/lib/isolate/message_const_type_arguments_1_test.dart b/tests/lib/isolate/message_const_type_arguments_1_test.dart
index 480cda5..e5133aa 100644
--- a/tests/lib/isolate/message_const_type_arguments_1_test.dart
+++ b/tests/lib/isolate/message_const_type_arguments_1_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// https://github.com/dart-lang/sdk/issues/35778
diff --git a/tests/lib/isolate/message_const_type_arguments_2_test.dart b/tests/lib/isolate/message_const_type_arguments_2_test.dart
index 8398d2b..002aa6e 100644
--- a/tests/lib/isolate/message_const_type_arguments_2_test.dart
+++ b/tests/lib/isolate/message_const_type_arguments_2_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// https://github.com/dart-lang/sdk/issues/35778
diff --git a/tests/lib/isolate/message_enum_test.dart b/tests/lib/isolate/message_enum_test.dart
index 55eb38b..801afd4d 100644
--- a/tests/lib/isolate/message_enum_test.dart
+++ b/tests/lib/isolate/message_enum_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import 'package:expect/expect.dart';
diff --git a/tests/lib/isolate/message_test.dart b/tests/lib/isolate/message_test.dart
index 5e6cd6b..8a7ec69 100644
--- a/tests/lib/isolate/message_test.dart
+++ b/tests/lib/isolate/message_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// Dart test program for testing serialization of messages.
diff --git a/tests/lib/isolate/mint_maker_test.dart b/tests/lib/isolate/mint_maker_test.dart
index f82315e..c4b25ec 100644
--- a/tests/lib/isolate/mint_maker_test.dart
+++ b/tests/lib/isolate/mint_maker_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
library MintMakerTest;
diff --git a/tests/lib/isolate/native_wrapper_message_test.dart b/tests/lib/isolate/native_wrapper_message_test.dart
index 27c294c..366a84b 100644
--- a/tests/lib/isolate/native_wrapper_message_test.dart
+++ b/tests/lib/isolate/native_wrapper_message_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import 'dart:isolate';
diff --git a/tests/lib/isolate/nested_spawn2_test.dart b/tests/lib/isolate/nested_spawn2_test.dart
index f8cf00a..d335909 100644
--- a/tests/lib/isolate/nested_spawn2_test.dart
+++ b/tests/lib/isolate/nested_spawn2_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// Dart test program for testing that isolates can spawn other isolates and
diff --git a/tests/lib/isolate/nested_spawn_test.dart b/tests/lib/isolate/nested_spawn_test.dart
index 952c192..0bc8c77 100644
--- a/tests/lib/isolate/nested_spawn_test.dart
+++ b/tests/lib/isolate/nested_spawn_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// Dart test program for testing that isolates can spawn other isolates.
diff --git a/tests/lib/isolate/non_fatal_exception_in_timer_callback_test.dart b/tests/lib/isolate/non_fatal_exception_in_timer_callback_test.dart
index 0d2e8cc..b361171 100644
--- a/tests/lib/isolate/non_fatal_exception_in_timer_callback_test.dart
+++ b/tests/lib/isolate/non_fatal_exception_in_timer_callback_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import 'dart:async';
diff --git a/tests/lib/isolate/object_leak_test.dart b/tests/lib/isolate/object_leak_test.dart
index d563786..b8b94b4 100644
--- a/tests/lib/isolate/object_leak_test.dart
+++ b/tests/lib/isolate/object_leak_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// Regression test for http://dartbug.com/18942
diff --git a/tests/lib/isolate/ondone_test.dart b/tests/lib/isolate/ondone_test.dart
index 0f11aaf..f378855 100644
--- a/tests/lib/isolate/ondone_test.dart
+++ b/tests/lib/isolate/ondone_test.dart
@@ -2,7 +2,7 @@
// for details. All rights reserved. Use of this source is governed by a
// BSD-style license that can be found in the LICENSE file.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import "dart:isolate";
diff --git a/tests/lib/isolate/package_config_test.dart b/tests/lib/isolate/package_config_test.dart
index c4119b2..a2cfece 100644
--- a/tests/lib/isolate/package_config_test.dart
+++ b/tests/lib/isolate/package_config_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// VMOptions=--trace_shutdown
import 'dart:io';
diff --git a/tests/lib/isolate/package_resolve_test.dart b/tests/lib/isolate/package_resolve_test.dart
index 99cb6f1..50686a3 100644
--- a/tests/lib/isolate/package_resolve_test.dart
+++ b/tests/lib/isolate/package_resolve_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import 'dart:io';
diff --git a/tests/lib/isolate/package_root_test.dart b/tests/lib/isolate/package_root_test.dart
index 4b3d46b..390df69 100644
--- a/tests/lib/isolate/package_root_test.dart
+++ b/tests/lib/isolate/package_root_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import 'dart:io';
diff --git a/tests/lib/isolate/pause_test.dart b/tests/lib/isolate/pause_test.dart
index 31e091d..1e97f00a 100644
--- a/tests/lib/isolate/pause_test.dart
+++ b/tests/lib/isolate/pause_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import "dart:isolate";
diff --git a/tests/lib/isolate/ping_pause_test.dart b/tests/lib/isolate/ping_pause_test.dart
index d83d55f..48ad135 100644
--- a/tests/lib/isolate/ping_pause_test.dart
+++ b/tests/lib/isolate/ping_pause_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import "dart:isolate";
diff --git a/tests/lib/isolate/ping_test.dart b/tests/lib/isolate/ping_test.dart
index e9a0d05..4371a4c0 100644
--- a/tests/lib/isolate/ping_test.dart
+++ b/tests/lib/isolate/ping_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import "dart:isolate";
diff --git a/tests/lib/isolate/port_test.dart b/tests/lib/isolate/port_test.dart
index b66fc4f..937d75e 100644
--- a/tests/lib/isolate/port_test.dart
+++ b/tests/lib/isolate/port_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// Test properties of ports.
diff --git a/tests/lib/isolate/raw_port_test.dart b/tests/lib/isolate/raw_port_test.dart
index d0b8695..6f24212 100644
--- a/tests/lib/isolate/raw_port_test.dart
+++ b/tests/lib/isolate/raw_port_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// Test RawReceivePort.
diff --git a/tests/lib/isolate/regress_34752_test.dart b/tests/lib/isolate/regress_34752_test.dart
index fc17139..ed870a6 100644
--- a/tests/lib/isolate/regress_34752_test.dart
+++ b/tests/lib/isolate/regress_34752_test.dart
@@ -2,7 +2,8 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
// VMOptions=--no-enable-isolate-groups
// Verifies that large BigInt can be passed through a message port and
diff --git a/tests/lib/isolate/regress_flutter_22796_test.dart b/tests/lib/isolate/regress_flutter_22796_test.dart
index f97ca05..1cab5f1 100644
--- a/tests/lib/isolate/regress_flutter_22796_test.dart
+++ b/tests/lib/isolate/regress_flutter_22796_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// Verifies that large typed data can be passed in a field through message port.
diff --git a/tests/lib/isolate/request_reply_test.dart b/tests/lib/isolate/request_reply_test.dart
index 3dd9274..54d4d7c 100644
--- a/tests/lib/isolate/request_reply_test.dart
+++ b/tests/lib/isolate/request_reply_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
library RequestReplyTest;
diff --git a/tests/lib/isolate/resolve_package_uri_test.dart b/tests/lib/isolate/resolve_package_uri_test.dart
index b926ccd..9ea1d03 100644
--- a/tests/lib/isolate/resolve_package_uri_test.dart
+++ b/tests/lib/isolate/resolve_package_uri_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// Regression test for faulty encoding of `Isolate.resolvePackageUri` by
diff --git a/tests/lib/isolate/scenarios/package_data_uri_spec/package_resolve_test.dart b/tests/lib/isolate/scenarios/package_data_uri_spec/package_resolve_test.dart
index 99cb6f1..50686a3 100644
--- a/tests/lib/isolate/scenarios/package_data_uri_spec/package_resolve_test.dart
+++ b/tests/lib/isolate/scenarios/package_data_uri_spec/package_resolve_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import 'dart:io';
diff --git a/tests/lib/isolate/send_private_test.dart b/tests/lib/isolate/send_private_test.dart
index 46114c8..8ed717f 100644
--- a/tests/lib/isolate/send_private_test.dart
+++ b/tests/lib/isolate/send_private_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import "dart:isolate";
diff --git a/tests/lib/isolate/simple_message_test.dart b/tests/lib/isolate/simple_message_test.dart
index 677998c..f0310af 100644
--- a/tests/lib/isolate/simple_message_test.dart
+++ b/tests/lib/isolate/simple_message_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// Dart test program for testing that isolates are spawned.
diff --git a/tests/lib/isolate/spawn_function_custom_class_test.dart b/tests/lib/isolate/spawn_function_custom_class_test.dart
index 5abcae6..0046cef 100644
--- a/tests/lib/isolate/spawn_function_custom_class_test.dart
+++ b/tests/lib/isolate/spawn_function_custom_class_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// Create a user-defined class in a new isolate.
diff --git a/tests/lib/isolate/spawn_function_test.dart b/tests/lib/isolate/spawn_function_test.dart
index 22c5c8a..bd8d1c1 100644
--- a/tests/lib/isolate/spawn_function_test.dart
+++ b/tests/lib/isolate/spawn_function_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// Example of spawning an isolate from a function.
diff --git a/tests/lib/isolate/spawn_generic_test.dart b/tests/lib/isolate/spawn_generic_test.dart
index 572f985..109f2a8 100644
--- a/tests/lib/isolate/spawn_generic_test.dart
+++ b/tests/lib/isolate/spawn_generic_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// Check that Isolate.spawn is generic.
diff --git a/tests/lib/isolate/spawn_uri_exported_main_test.dart b/tests/lib/isolate/spawn_uri_exported_main_test.dart
index 20959cd..837486e 100644
--- a/tests/lib/isolate/spawn_uri_exported_main_test.dart
+++ b/tests/lib/isolate/spawn_uri_exported_main_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import "dart:async";
diff --git a/tests/lib/isolate/spawn_uri_fail_test.dart b/tests/lib/isolate/spawn_uri_fail_test.dart
index 84d54b0..6c9dc98 100644
--- a/tests/lib/isolate/spawn_uri_fail_test.dart
+++ b/tests/lib/isolate/spawn_uri_fail_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import "dart:io";
diff --git a/tests/lib/isolate/spawn_uri_missing_from_isolate_test.dart b/tests/lib/isolate/spawn_uri_missing_from_isolate_test.dart
index 915ffa4..02521b6 100644
--- a/tests/lib/isolate/spawn_uri_missing_from_isolate_test.dart
+++ b/tests/lib/isolate/spawn_uri_missing_from_isolate_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
/// Tests that Isolate.spawnUri completes with an error when the given URI
diff --git a/tests/lib/isolate/spawn_uri_missing_test.dart b/tests/lib/isolate/spawn_uri_missing_test.dart
index 86eaf9d..19344ba 100644
--- a/tests/lib/isolate/spawn_uri_missing_test.dart
+++ b/tests/lib/isolate/spawn_uri_missing_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
/// Tests that Isolate.spanUri completes with an error when the given URI
diff --git a/tests/lib/isolate/spawn_uri_multi_test.dart b/tests/lib/isolate/spawn_uri_multi_test.dart
index 38a22ee..d5fdc46 100644
--- a/tests/lib/isolate/spawn_uri_multi_test.dart
+++ b/tests/lib/isolate/spawn_uri_multi_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// Negative test to make sure that we are reaching all assertions.
diff --git a/tests/lib/isolate/spawn_uri_nested_vm_test.dart b/tests/lib/isolate/spawn_uri_nested_vm_test.dart
index 5da7fa9..087b5fc 100644
--- a/tests/lib/isolate/spawn_uri_nested_vm_test.dart
+++ b/tests/lib/isolate/spawn_uri_nested_vm_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// Example of nested spawning of isolates from a URI
diff --git a/tests/lib/isolate/spawn_uri_test.dart b/tests/lib/isolate/spawn_uri_test.dart
index 543b627..28d7bce 100644
--- a/tests/lib/isolate/spawn_uri_test.dart
+++ b/tests/lib/isolate/spawn_uri_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// Example of spawning an isolate from a URI
diff --git a/tests/lib/isolate/spawn_uri_vm_test.dart b/tests/lib/isolate/spawn_uri_vm_test.dart
index 48d30a2..3832b42 100644
--- a/tests/lib/isolate/spawn_uri_vm_test.dart
+++ b/tests/lib/isolate/spawn_uri_vm_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// Example of spawning an isolate from a URI
diff --git a/tests/lib/isolate/start_paused_test.dart b/tests/lib/isolate/start_paused_test.dart
index 5ca7fef..c9b2b57 100644
--- a/tests/lib/isolate/start_paused_test.dart
+++ b/tests/lib/isolate/start_paused_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
library start_paused_test;
diff --git a/tests/lib/isolate/static_function_test.dart b/tests/lib/isolate/static_function_test.dart
index 92151ac..e1ece06 100644
--- a/tests/lib/isolate/static_function_test.dart
+++ b/tests/lib/isolate/static_function_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// Test starting isolate with static functions (and toplevel ones, for sanity).
diff --git a/tests/lib/isolate/string_from_environment_default_value_test.dart b/tests/lib/isolate/string_from_environment_default_value_test.dart
index 6c2adfb..78b2feb 100644
--- a/tests/lib/isolate/string_from_environment_default_value_test.dart
+++ b/tests/lib/isolate/string_from_environment_default_value_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import "dart:isolate";
diff --git a/tests/lib/isolate/timer_isolate_test.dart b/tests/lib/isolate/timer_isolate_test.dart
index b2c98d9..58e93c5 100644
--- a/tests/lib/isolate/timer_isolate_test.dart
+++ b/tests/lib/isolate/timer_isolate_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
library multiple_timer_test;
diff --git a/tests/lib/isolate/timer_multiple_isolates_test.dart b/tests/lib/isolate/timer_multiple_isolates_test.dart
index a2f5611..3f7d8f3 100644
--- a/tests/lib/isolate/timer_multiple_isolates_test.dart
+++ b/tests/lib/isolate/timer_multiple_isolates_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
library timer_multiple_isolates_test;
diff --git a/tests/lib/isolate/transferable_failed_to_send_test.dart b/tests/lib/isolate/transferable_failed_to_send_test.dart
index a8d3bcd..c1d714a 100644
--- a/tests/lib/isolate/transferable_failed_to_send_test.dart
+++ b/tests/lib/isolate/transferable_failed_to_send_test.dart
@@ -2,7 +2,8 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
// VMOptions=--no-enable-isolate-groups
import "dart:io" show ServerSocket;
diff --git a/tests/lib/isolate/transferable_test.dart b/tests/lib/isolate/transferable_test.dart
index f8888e7..2264c8c 100644
--- a/tests/lib/isolate/transferable_test.dart
+++ b/tests/lib/isolate/transferable_test.dart
@@ -2,7 +2,8 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
// VMOptions=--no-enable-isolate-groups
import "dart:async";
diff --git a/tests/lib/isolate/type_ref_message_test.dart b/tests/lib/isolate/type_ref_message_test.dart
new file mode 100644
index 0000000..1c47e35
--- /dev/null
+++ b/tests/lib/isolate/type_ref_message_test.dart
@@ -0,0 +1,31 @@
+// 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.
+
+// See https://github.com/flutter/flutter/issues/84691
+
+import "dart:async";
+import "dart:isolate";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+
+class B<T> {}
+class D<S> extends B<D> {}
+
+main() {
+ asyncStart();
+ var port;
+ port = new RawReceivePort((message) {
+ var list = message as List<D<String>>;
+ var element = list[0] as D<String>;
+
+ port.close();
+ asyncEnd();
+ });
+
+
+ var list = <D<String>>[ new D() ];
+ port.sendPort.send(list);
+}
diff --git a/tests/lib/isolate/typed_message_test.dart b/tests/lib/isolate/typed_message_test.dart
index 955204d..38e24d0 100644
--- a/tests/lib/isolate/typed_message_test.dart
+++ b/tests/lib/isolate/typed_message_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// Dart test program for testing isolate communication with
// typed objects.
diff --git a/tests/lib/isolate/unresolved_ports_test.dart b/tests/lib/isolate/unresolved_ports_test.dart
index fa41bb4..7707fab 100644
--- a/tests/lib/isolate/unresolved_ports_test.dart
+++ b/tests/lib/isolate/unresolved_ports_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// spawns multiple isolates and sends unresolved ports between them.
diff --git a/tests/lib/isolate/vm_rehash_test.dart b/tests/lib/isolate/vm_rehash_test.dart
index 6c1065c..f5a0a73 100644
--- a/tests/lib/isolate/vm_rehash_test.dart
+++ b/tests/lib/isolate/vm_rehash_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import 'dart:async';
diff --git a/tests/lib/isolate/weak_property_message_1_test.dart b/tests/lib/isolate/weak_property_message_1_test.dart
new file mode 100644
index 0000000..2f4d344
--- /dev/null
+++ b/tests/lib/isolate/weak_property_message_1_test.dart
@@ -0,0 +1,48 @@
+// 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.
+
+// See https://github.com/dart-lang/sdk/issues/25559
+
+import "dart:async";
+import "dart:isolate";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+main() {
+ asyncStart();
+ var port;
+ port = new RawReceivePort((message) {
+ var expando1 = message[0] as Expando;
+ var expando2 = message[1] as Expando;
+ var expando3 = message[2] as Expando;
+ var key1 = message[3];
+
+ var key2 = expando1[key1!];
+ Expect.isNotNull(key2);
+ var key3 = expando2[key2!];
+ Expect.isNotNull(key3);
+ var value = expando3[key3!];
+ Expect.equals(value, "value");
+
+ port.close();
+ asyncEnd();
+ });
+
+
+ var key1 = new Object();
+ var key2 = new Object();
+ var key3 = new Object();
+ var expando1 = new Expando();
+ var expando2 = new Expando();
+ var expando3 = new Expando();
+ expando1[key1] = key2;
+ expando2[key2] = key3;
+ expando3[key3] = "value";
+
+ // key1 is placed after expando1 so that its reachability is uncertain when
+ // expando1 is first encountered.
+ var message = <dynamic>[expando1, expando2, expando3, key1];
+ port.sendPort.send(message);
+}
diff --git a/tests/lib/isolate/weak_property_message_2_test.dart b/tests/lib/isolate/weak_property_message_2_test.dart
new file mode 100644
index 0000000..236bcfe3
--- /dev/null
+++ b/tests/lib/isolate/weak_property_message_2_test.dart
@@ -0,0 +1,34 @@
+// 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.
+
+// See https://github.com/dart-lang/sdk/issues/25559
+
+import "dart:async";
+import "dart:developer";
+import "dart:isolate";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+main() {
+ asyncStart();
+ var port;
+ port = new RawReceivePort((message) {
+ var expando = message as Expando;
+
+ // Sent and received without error.
+
+ port.close();
+ asyncEnd();
+ });
+
+
+ var unwrittenKey = new Object();
+ var expando = new Expando();
+ expando[unwrittenKey] = new UserTag("cant send this");
+
+ port.sendPort.send(expando);
+
+ print(unwrittenKey); // Ensure [unwrittenKey] is live during [send].
+}
diff --git a/tests/lib/js/extends_test/extends_subtyping_live_test.dart b/tests/lib/js/extends_test/extends_subtyping_live_test.dart
new file mode 100644
index 0000000..b46818e
--- /dev/null
+++ b/tests/lib/js/extends_test/extends_subtyping_live_test.dart
@@ -0,0 +1,20 @@
+// 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.
+
+// Tests inheritance subtyping relationships after making package:js types live.
+
+@JS()
+library extends_subtyping_live_test;
+
+import 'package:js/js.dart';
+import 'extends_test_util.dart';
+
+@JS()
+external dynamic get externalGetter;
+
+void main() {
+ // Call to foreign function should trigger dart2js to assume types are live.
+ externalGetter;
+ testSubtyping();
+}
diff --git a/tests/lib/js/extends_test/extends_subtyping_not_live_test.dart b/tests/lib/js/extends_test/extends_subtyping_not_live_test.dart
new file mode 100644
index 0000000..3cb0fbb
--- /dev/null
+++ b/tests/lib/js/extends_test/extends_subtyping_not_live_test.dart
@@ -0,0 +1,12 @@
+// 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.
+
+// Tests inheritance subtyping relationships without making package:js types
+// live.
+
+import 'extends_test_util.dart';
+
+void main() {
+ testSubtyping();
+}
diff --git a/tests/lib/js/extends_test/extends_test_util.dart b/tests/lib/js/extends_test/extends_test_util.dart
index e39e1b9..0698ef9 100644
--- a/tests/lib/js/extends_test/extends_test_util.dart
+++ b/tests/lib/js/extends_test/extends_test_util.dart
@@ -15,6 +15,7 @@
@JS()
class JSClass {
+ external JSClass();
external int get a;
external int getA();
external int getAOrB();
@@ -57,12 +58,10 @@
external int getAOrB();
}
+external AnonymousClass get anon;
external AnonymousExtendAnonymousClass get anonExtendAnon;
external AnonymousExtendJSClass get anonExtendJS;
-void useJSClass(JSClass js) {}
-void useAnonymousClass(AnonymousClass a) {}
-
void setUpWithoutES6Syntax() {
// Use the old way to define inheritance between JS objects.
eval(r"""
@@ -77,6 +76,7 @@
}
}
function JSClass(a) {
+ if (arguments.length == 0) a = 1;
this.a = a;
this.getA = function() {
return this.a;
@@ -109,6 +109,7 @@
return this.getB();
}
}
+ self.anon = new JSClass(1);
self.anonExtendAnon = new JSExtendAnonymousClass(1, 2);
self.anonExtendJS = new JSExtendJSClass(1, 2);
""");
@@ -119,6 +120,7 @@
eval(r"""
class JSClass {
constructor(a) {
+ if (arguments.length == 0) a = 1;
this.a = a;
}
getA() {
@@ -128,6 +130,7 @@
return this.getA();
}
}
+ self.JSClass = JSClass;
class JSExtendJSClass extends JSClass {
constructor(a, b) {
super(a);
@@ -157,16 +160,13 @@
}
}
self.JSExtendAnonymousClass = JSExtendAnonymousClass;
+ self.anon = new JSClass(1);
self.anonExtendAnon = new JSExtendAnonymousClass(1, 2);
self.anonExtendJS = new JSExtendJSClass(1, 2);
""");
}
void testInheritance() {
- // Note that for the following, there are no meaningful tests for is checks or
- // as casts, since the web compilers should return true and succeed for all JS
- // types.
-
var jsExtendJS = JSExtendJSClass(1, 2);
expect(jsExtendJS.a, 1);
expect(jsExtendJS.b, 2);
@@ -193,18 +193,86 @@
expect(anonExtendJS.getB(), 2);
expect(anonExtendJS.getAOrB(), 2);
expect((anonExtendJS as JSClass).getAOrB(), 2);
+
+ // Test type checking and casts succeeds regardless of type hierarchy.
+
+ // Test type checking at runtime by disabling inlining. We still, however, do
+ // `is` checks directly below to test those optimizations.
+ @pragma('dart2js:noInline')
+ void runtimeIsAndAs<T>(instance) {
+ expect(instance is T, true);
+ expect(() => instance as T, returnsNormally);
+ }
+
+ // Test that base JS type can be used as any subtype.
+ var js = JSClass();
+ expect(js is JSExtendJSClass, true);
+ runtimeIsAndAs<JSExtendJSClass>(js);
+ expect(js is AnonymousExtendJSClass, true);
+ runtimeIsAndAs<AnonymousExtendJSClass>(js);
+
+ // Test that base anonymous type can be use as any subtype.
+ // Conversion from external getter value to a variable is needed to coerce
+ // compile time optimization of type checks. This applies for below as well.
+ var anonVar = anon;
+ expect(anonVar is JSExtendAnonymousClass, true);
+ runtimeIsAndAs<JSExtendAnonymousClass>(anonVar);
+ expect(anonVar is AnonymousExtendAnonymousClass, true);
+ runtimeIsAndAs<AnonymousExtendAnonymousClass>(anonVar);
+
+ // Test that instance of subtypes can be used as their JS supertype.
+ expect(jsExtendJS is JSClass, true);
+ runtimeIsAndAs<JSClass>(jsExtendJS);
+ var anonExtendJSVar = anonExtendJS;
+ expect(anonExtendJSVar is JSClass, true);
+ runtimeIsAndAs<JSClass>(anonExtendJSVar);
+
+ // Test that instance of subtypes can be used as their anonymous supertype.
+ var anonExtendAnonVar = anonExtendAnon;
+ expect(anonExtendAnonVar is AnonymousClass, true);
+ runtimeIsAndAs<AnonymousClass>(anonExtendAnonVar);
+ expect(jsExtendAnon is AnonymousClass, true);
+ runtimeIsAndAs<AnonymousClass>(jsExtendAnon);
+}
+
+JSClass returnJS() => throw '';
+
+AnonymousClass returnAnon() => throw '';
+
+JSExtendJSClass returnJSExtendJS() => throw '';
+
+JSExtendAnonymousClass returnJSExtendAnon() => throw '';
+
+AnonymousExtendJSClass returnAnonExtendJS() => throw '';
+
+AnonymousExtendAnonymousClass returnAnonExtendAnon() => throw '';
+
+@pragma('dart2js:noInline')
+void isRuntimeSubtypeBothWays<T, U>() {
+ // Test T <: U and U <: T. With interop types, type checks should pass
+ // regardless of type hierarchy. Note that dart2js does these type checks at
+ // runtime. Below, we do compile-time checks using top-level functions.
+ T f1() => throw '';
+ U f2() => throw '';
+ expect(f1 is U Function(), true);
+ expect(f2 is T Function(), true);
}
void testSubtyping() {
// Test subtyping for inheritance between JS and anonymous classes.
- expect(useJSClass is void Function(JSExtendJSClass js), true);
- expect(useAnonymousClass is void Function(AnonymousExtendAnonymousClass a),
- true);
- expect(useJSClass is void Function(AnonymousExtendJSClass a), true);
- expect(useAnonymousClass is void Function(JSExtendAnonymousClass js), true);
+ expect(returnJS is JSExtendJSClass Function(), true);
+ expect(returnJSExtendJS is JSClass Function(), true);
+ isRuntimeSubtypeBothWays<JSClass, JSExtendJSClass>();
- expect(useJSClass is void Function(AnonymousExtendAnonymousClass a), false);
- expect(useAnonymousClass is void Function(JSExtendJSClass js), false);
- expect(useJSClass is void Function(JSExtendAnonymousClass js), false);
- expect(useAnonymousClass is void Function(AnonymousExtendJSClass a), false);
+ expect(returnJS is AnonymousExtendJSClass Function(), true);
+ expect(returnAnonExtendJS is JSClass Function(), true);
+ isRuntimeSubtypeBothWays<JSClass, AnonymousExtendJSClass>();
+
+ expect(returnAnon is JSExtendAnonymousClass Function(), true);
+ expect(returnJSExtendAnon is AnonymousClass Function(), true);
+ isRuntimeSubtypeBothWays<AnonymousClass, JSExtendAnonymousClass>();
+
+ expect(returnAnon is AnonymousExtendAnonymousClass Function(), true);
+ expect(returnAnonExtendAnon is AnonymousClass Function(), true);
+ isRuntimeSubtypeBothWays<AnonymousClass, AnonymousExtendAnonymousClass>();
}
diff --git a/tests/lib/js/external_nonjs_static_test.dart b/tests/lib/js/external_nonjs_static_test.dart
index 47b6252..87c4615 100644
--- a/tests/lib/js/external_nonjs_static_test.dart
+++ b/tests/lib/js/external_nonjs_static_test.dart
@@ -7,6 +7,7 @@
library external_nonjs_static_test;
+import 'dart:html';
import 'package:js/js.dart';
external var topLevelField;
@@ -98,4 +99,81 @@
// [web] Only JS interop members may be 'external'.
}
+extension ExtensionNonJS on NonJSClass {
+ external var field;
+ // ^
+ // [web] JS interop or Native class required for 'external' extension members.
+ external final finalField;
+ // ^
+ // [web] JS interop or Native class required for 'external' extension members.
+ external static var staticField;
+ // ^
+ // [web] JS interop or Native class required for 'external' extension members.
+ external static final staticFinalField;
+ // ^
+ // [web] JS interop or Native class required for 'external' extension members.
+
+ external get getter;
+ // ^
+ // [web] JS interop or Native class required for 'external' extension members.
+ external set setter(_);
+ // ^
+ // [web] JS interop or Native class required for 'external' extension members.
+
+ external static get staticGetter;
+ // ^
+ // [web] JS interop or Native class required for 'external' extension members.
+ external static set staticSetter(_);
+ // ^
+ // [web] JS interop or Native class required for 'external' extension members.
+
+ external method();
+ // ^
+ // [web] JS interop or Native class required for 'external' extension members.
+ external static staticMethod();
+ // ^
+ // [web] JS interop or Native class required for 'external' extension members.
+ external optionalParameterMethod([int? a, int b = 0]);
+ // ^
+ // [web] JS interop or Native class required for 'external' extension members.
+ external overridenMethod();
+ // ^
+ // [web] JS interop or Native class required for 'external' extension members.
+
+ nonExternalMethod() => 1;
+ static nonExternalStaticMethod() => 2;
+}
+
+class NonJSClass {
+ void overridenMethod() => 5;
+}
+
+extension ExtensionGenericNonJS<T> on GenericNonJSClass<T> {
+ external T method();
+ // ^
+ // [web] JS interop or Native class required for 'external' extension members.
+}
+
+class GenericNonJSClass<T> {}
+
+extension ExtensionNative on HtmlElement {
+ external var field;
+ external final finalField;
+ external static var staticField;
+ external static final staticFinalField;
+
+ external get getter;
+ external set setter(_);
+
+ external static get staticGetter;
+ external static set staticSetter(_);
+
+ external method();
+ external static staticMethod();
+ external optionalParameterMethod([int? a, int b = 0]);
+
+ nonExternalMethod() => 1;
+ static nonExternalStaticMethod() => 2;
+}
+
main() {}
diff --git a/tests/lib/js/external_static_test.dart b/tests/lib/js/external_static_test.dart
index 8fac26db..a455de0 100644
--- a/tests/lib/js/external_static_test.dart
+++ b/tests/lib/js/external_static_test.dart
@@ -8,6 +8,7 @@
@JS()
library external_static_test;
+import 'dart:html';
import 'package:js/js.dart';
// external top level members ok in @JS() library.
@@ -86,4 +87,167 @@
// [web] Only JS interop members may be 'external'.
}
+extension ExtensionNonJS on NonJSClass {
+ external var field;
+ // ^
+ // [web] JS interop or Native class required for 'external' extension members.
+ external final finalField;
+ // ^
+ // [web] JS interop or Native class required for 'external' extension members.
+ external static var staticField;
+ // ^
+ // [web] JS interop or Native class required for 'external' extension members.
+ external static final staticFinalField;
+ // ^
+ // [web] JS interop or Native class required for 'external' extension members.
+
+ external get getter;
+ // ^
+ // [web] JS interop or Native class required for 'external' extension members.
+ external set setter(_);
+ // ^
+ // [web] JS interop or Native class required for 'external' extension members.
+
+ external static get staticGetter;
+ // ^
+ // [web] JS interop or Native class required for 'external' extension members.
+ external static set staticSetter(_);
+ // ^
+ // [web] JS interop or Native class required for 'external' extension members.
+
+ external method();
+ // ^
+ // [web] JS interop or Native class required for 'external' extension members.
+ external static staticMethod();
+ // ^
+ // [web] JS interop or Native class required for 'external' extension members.
+ external optionalParameterMethod([int? a, int b = 0]);
+ // ^
+ // [web] JS interop or Native class required for 'external' extension members.
+ external overridenMethod();
+ // ^
+ // [web] JS interop or Native class required for 'external' extension members.
+
+ @JS('fieldAnnotation')
+ external var annotatedField;
+ // ^
+ // [web] JS interop or Native class required for 'external' extension members.
+ @JS('memberAnnotation')
+ external annotatedMethod();
+ // ^
+ // [web] JS interop or Native class required for 'external' extension members.
+
+ nonExternalMethod() => 1;
+ static nonExternalStaticMethod() => 2;
+}
+
+class NonJSClass {
+ void overridenMethod() => 5;
+}
+
+extension ExtensionGenericNonJS<T> on GenericNonJSClass<T> {
+ external T method();
+ // ^
+ // [web] JS interop or Native class required for 'external' extension members.
+}
+
+class GenericNonJSClass<T> {}
+
+extension ExtensionJS on JSClass {
+ external var field;
+ external final finalField;
+ external static var staticField;
+ external static final staticFinalField;
+
+ external get getter;
+ external set setter(_);
+
+ external static get staticGetter;
+ external static set staticSetter(_);
+
+ external method();
+ external static staticMethod();
+ external optionalParameterMethod([int? a, int b = 0]);
+
+ @JS('fieldAnnotation')
+ external var annotatedField;
+
+ @JS('memberAnnotation')
+ external annotatedMethod();
+
+ nonExternalMethod() => 1;
+ static nonExternalStaticMethod() => 2;
+}
+
+@JS()
+class JSClass {}
+
+extension ExtensionGenericJS<T> on GenericJSClass<T> {
+ external T method();
+}
+
+@JS()
+class GenericJSClass<T> {}
+
+extension ExtensionAnonymousJS on AnonymousJSClass {
+ external var field;
+ external get getter;
+ external set setter(_);
+ external method();
+}
+
+@JS()
+@anonymous
+class AnonymousJSClass {}
+
+extension ExtensionAbstractJS on AbstractJSClass {
+ external var field;
+ external get getter;
+ external set setter(_);
+ external method();
+}
+
+@JS()
+abstract class AbstractJSClass {}
+
+extension ExtensionAnnotatedJS on AnnotatedJSClass {
+ external var field;
+ external get getter;
+ external set setter(_);
+ external method();
+}
+
+@JS('Annotation')
+class AnnotatedJSClass {}
+
+extension ExtensionPrivateJS on _privateJSClass {
+ external var field;
+ external get getter;
+ external set setter(_);
+ external method();
+}
+
+@JS()
+class _privateJSClass {}
+
+extension ExtensionNative on HtmlElement {
+ external var field;
+ external final finalField;
+ external static var staticField;
+ external static final staticFinalField;
+
+ external get getter;
+ external set setter(_);
+
+ external static get staticGetter;
+ external static set staticSetter(_);
+
+ external method();
+ external static staticMethod();
+ external optionalParameterMethod([int? a, int b = 0]);
+
+ nonExternalMethod() => 1;
+ static nonExternalStaticMethod() => 2;
+}
+
main() {}
diff --git a/tests/lib/js/is_check_and_as_cast_test.dart b/tests/lib/js/is_check_and_as_cast_test.dart
index b84e625..40216d6 100644
--- a/tests/lib/js/is_check_and_as_cast_test.dart
+++ b/tests/lib/js/is_check_and_as_cast_test.dart
@@ -34,13 +34,6 @@
external int get a;
}
-@JS()
-class Baz {
- external Baz(int a, int b);
- external int get a;
- external int get b;
-}
-
// JS object literals
@JS()
@anonymous
@@ -60,6 +53,11 @@
class DartClass {}
+// Avoid static type optimization by running all tests using this.
+@pragma('dart2js:noInline')
+@pragma('dart2js:assumeDynamic')
+confuse(x) => x;
+
void main() {
eval(r"""
function Foo(a) {
@@ -68,11 +66,6 @@
function Bar(a) {
this.a = a;
}
- function Baz(a, b) {
- Foo.call(this, a);
- this.b = b;
- }
- Baz.prototype.__proto__ = Foo.prototype;
var a = {
x: 1,
};
@@ -84,6 +77,7 @@
// JS class object can be checked and casted with itself.
var foo = Foo(42);
expect(foo is Foo, isTrue);
+ expect(confuse(foo) is Foo, isTrue);
expect(() => (foo as Foo), returnsNormally);
// Try it with dynamic.
@@ -93,64 +87,73 @@
// Casts are allowed between any JS class objects.
expect(foo is Bar, isTrue);
+ expect(confuse(foo) is Bar, isTrue);
expect(d is Bar, isTrue);
expect(() => (foo as Bar), returnsNormally);
expect(() => (d as Bar), returnsNormally);
- // Type-checking and casting works regardless of the inheritance chain.
- var baz = Baz(42, 43);
- expect(baz is Foo, isTrue);
- expect(() => (baz as Foo), returnsNormally);
- expect(foo is Baz, isTrue);
- expect(() => (foo as Baz), returnsNormally);
-
// BarCopy is the same JS class as Bar.
var barCopy = BarCopy(42);
expect(barCopy is Bar, isTrue);
+ expect(confuse(barCopy) is Bar, isTrue);
expect(() => (barCopy as Bar), returnsNormally);
// JS object literal can be checked and casted with itself.
expect(a is LiteralA, isTrue);
+ expect(confuse(a) is LiteralA, isTrue);
expect(() => (a as LiteralA), returnsNormally);
// Like class objects, casts are allowed between any object literals.
expect(a is LiteralB, isTrue);
+ expect(confuse(a) is LiteralB, isTrue);
expect(() => (a as LiteralB), returnsNormally);
// Similarly, casts are allowed between any class objects and object literals.
expect(foo is LiteralB, isTrue);
+ expect(confuse(foo) is LiteralB, isTrue);
expect(() => (foo as LiteralB), returnsNormally);
expect(a is Foo, isTrue);
+ expect(confuse(a) is Foo, isTrue);
expect(() => (a as Foo), returnsNormally);
// You cannot cast between JS interop objects and Dart objects, however.
var dartClass = DartClass();
expect(dartClass is Foo, isFalse);
+ expect(confuse(dartClass) is Foo, isFalse);
expect(() => (dartClass as Foo), throws);
expect(dartClass is LiteralA, isFalse);
+ expect(confuse(dartClass) is LiteralA, isFalse);
expect(() => (dartClass as LiteralA), throws);
expect(foo is DartClass, isFalse);
+ expect(confuse(foo) is DartClass, isFalse);
expect(() => (foo as DartClass), throws);
expect(a is DartClass, isFalse);
+ expect(confuse(a) is DartClass, isFalse);
expect(() => (a as DartClass), throws);
// Test that nullability is still respected with JS types.
expect(foo is Foo?, isTrue);
+ expect(confuse(foo) is Foo?, isTrue);
expect(() => (foo as Foo?), returnsNormally);
Foo? nullableFoo = null;
expect(nullableFoo is Foo?, isTrue);
+ expect(confuse(nullableFoo) is Foo?, isTrue);
expect(() => (nullableFoo as Foo?), returnsNormally);
expect(nullableFoo is Foo, isFalse);
+ expect(confuse(nullableFoo) is Foo, isFalse);
expect(() => (nullableFoo as Foo),
hasUnsoundNullSafety ? returnsNormally : throws);
expect(a is LiteralA?, isTrue);
+ expect(confuse(a) is LiteralA?, isTrue);
expect(() => (a as LiteralA?), returnsNormally);
LiteralA? nullableA = null;
expect(nullableA is LiteralA?, isTrue);
+ expect(confuse(nullableA) is LiteralA?, isTrue);
expect(() => (nullableA as LiteralA?), returnsNormally);
expect(nullableA is LiteralA, isFalse);
+ expect(confuse(nullableA) is LiteralA, isFalse);
expect(() => (nullableA as LiteralA),
hasUnsoundNullSafety ? returnsNormally : throws);
}
diff --git a/tests/lib/js/parameters_static_test.dart b/tests/lib/js/parameters_static_test.dart
index 7fa7ddc..b6c68fe 100644
--- a/tests/lib/js/parameters_static_test.dart
+++ b/tests/lib/js/parameters_static_test.dart
@@ -58,4 +58,13 @@
// [web] Named parameters for JS interop functions are only allowed in a factory constructor of an @anonymous JS class.
}
+extension ExtensionFoo on Foo {
+ external int singleNamedArg({int? a});
+ // ^
+ // [web] Named parameters for JS interop functions are only allowed in a factory constructor of an @anonymous JS class.
+ external int mixedNamedArgs(int a, {int? b});
+ // ^
+ // [web] Named parameters for JS interop functions are only allowed in a factory constructor of an @anonymous JS class.
+}
+
main() {}
diff --git a/tests/lib/js/subtyping_test.dart b/tests/lib/js/subtyping_test.dart
deleted file mode 100644
index 2551fcd..0000000
--- a/tests/lib/js/subtyping_test.dart
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright (c) 2020, 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.
-
-// Tests subtyping relationships between JS and anonymous classes.
-
-@JS()
-library subtyping_test;
-
-import 'package:js/js.dart';
-import 'package:expect/expect.dart' show hasUnsoundNullSafety;
-import 'package:expect/minitest.dart';
-
-@JS()
-class JSClassA {}
-
-@JS()
-class JSClassB {}
-
-@JS()
-@anonymous
-class AnonymousClassA {}
-
-@JS()
-@anonymous
-class AnonymousClassB {}
-
-class DartClass {}
-
-void useJSClassA(JSClassA _) {}
-void useAnonymousClassA(AnonymousClassA _) {}
-void useDartClass(DartClass _) {}
-
-void useNullableJSClassA(JSClassA? _) {}
-void useNullableAnonymousClassA(AnonymousClassA? _) {}
-
-// Avoid static type optimization by running all tests using this.
-@pragma('dart2js:noInline')
-@pragma('dart2js:assumeDynamic')
-confuse(x) => x;
-
-void main() {
- // Checks subtyping with the same type and nullability subtyping.
- expect(useJSClassA is void Function(JSClassA), true);
- expect(useAnonymousClassA is void Function(AnonymousClassA), true);
- expect(useJSClassA is void Function(JSClassA?), hasUnsoundNullSafety);
- expect(useAnonymousClassA is void Function(AnonymousClassA?),
- hasUnsoundNullSafety);
- expect(useNullableJSClassA is void Function(JSClassA?), true);
- expect(useNullableAnonymousClassA is void Function(AnonymousClassA?), true);
- expect(useNullableJSClassA is void Function(JSClassA), true);
- expect(useNullableAnonymousClassA is void Function(AnonymousClassA), true);
-
- expect(confuse(useJSClassA) is void Function(JSClassA), true);
- expect(confuse(useAnonymousClassA) is void Function(AnonymousClassA), true);
- expect(
- confuse(useJSClassA) is void Function(JSClassA?), hasUnsoundNullSafety);
- expect(confuse(useAnonymousClassA) is void Function(AnonymousClassA?),
- hasUnsoundNullSafety);
- expect(confuse(useNullableJSClassA) is void Function(JSClassA?), true);
- expect(confuse(useNullableAnonymousClassA) is void Function(AnonymousClassA?),
- true);
- expect(confuse(useNullableJSClassA) is void Function(JSClassA), true);
- expect(confuse(useNullableAnonymousClassA) is void Function(AnonymousClassA),
- true);
-
- // No subtyping between JS and anonymous classes.
- expect(useJSClassA is void Function(AnonymousClassA), false);
- expect(useAnonymousClassA is void Function(JSClassA), false);
-
- expect(confuse(useJSClassA) is void Function(AnonymousClassA), false);
- expect(confuse(useAnonymousClassA) is void Function(JSClassA), false);
-
- // No subtyping between separate classes even if they're both JS classes or
- // anonymous classes.
- expect(useJSClassA is void Function(JSClassB), false);
- expect(useAnonymousClassA is void Function(AnonymousClassB), false);
-
- expect(confuse(useJSClassA) is void Function(JSClassB), false);
- expect(confuse(useAnonymousClassA) is void Function(AnonymousClassB), false);
-
- // No subtyping between JS/anonymous classes and Dart classes.
- expect(useJSClassA is void Function(DartClass), false);
- expect(useAnonymousClassA is void Function(DartClass), false);
-
- expect(confuse(useJSClassA) is void Function(DartClass), false);
- expect(confuse(useAnonymousClassA) is void Function(DartClass), false);
-}
diff --git a/tests/lib/js/subtyping_test/subtyping_live_test.dart b/tests/lib/js/subtyping_test/subtyping_live_test.dart
new file mode 100644
index 0000000..d137ba6
--- /dev/null
+++ b/tests/lib/js/subtyping_test/subtyping_live_test.dart
@@ -0,0 +1,20 @@
+// 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.
+
+// Tests subtyping relationships after making package:js types live.
+
+@JS()
+library subtyping_live_test;
+
+import 'package:js/js.dart';
+import 'subtyping_test_util.dart';
+
+@JS()
+external dynamic get externalGetter;
+
+void main() {
+ // Call to foreign function should trigger dart2js to assume types are live.
+ externalGetter;
+ testSubtyping();
+}
diff --git a/tests/lib/js/subtyping_test/subtyping_not_live_test.dart b/tests/lib/js/subtyping_test/subtyping_not_live_test.dart
new file mode 100644
index 0000000..5344280
--- /dev/null
+++ b/tests/lib/js/subtyping_test/subtyping_not_live_test.dart
@@ -0,0 +1,12 @@
+// 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.
+
+// Tests subtyping relationships without making package:js types live.
+
+import 'package:js/js.dart';
+import 'subtyping_test_util.dart';
+
+void main() {
+ testSubtyping();
+}
diff --git a/tests/lib/js/subtyping_test/subtyping_test_util.dart b/tests/lib/js/subtyping_test/subtyping_test_util.dart
new file mode 100644
index 0000000..c8f7740
--- /dev/null
+++ b/tests/lib/js/subtyping_test/subtyping_test_util.dart
@@ -0,0 +1,92 @@
+// 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.
+
+// Tests subtyping relationships between JS and anonymous classes.
+
+@JS()
+library subtyping_test_util;
+
+import 'package:js/js.dart';
+import 'package:expect/expect.dart' show hasUnsoundNullSafety;
+import 'package:expect/minitest.dart';
+
+@JS()
+class JSClassA {}
+
+@JS()
+class JSClassB {}
+
+@JS()
+@anonymous
+class AnonymousClassA {}
+
+@JS()
+@anonymous
+class AnonymousClassB {}
+
+class DartClass {}
+
+JSClassA returnJS() => throw '';
+JSClassA? returnNullableJS() => throw '';
+
+AnonymousClassA returnAnon() => throw '';
+AnonymousClassA? returnNullableAnon() => throw '';
+
+DartClass returnDartClass() => throw '';
+
+// Avoid static type optimization by running all tests using this.
+@pragma('dart2js:noInline')
+@pragma('dart2js:assumeDynamic')
+confuse(x) => x;
+
+void testSubtyping() {
+ // Checks subtyping with the same type and nullability subtyping.
+ expect(returnJS is JSClassA Function(), true);
+ expect(returnAnon is AnonymousClassA Function(), true);
+ expect(returnJS is JSClassA? Function(), true);
+ expect(returnAnon is AnonymousClassA? Function(), true);
+ expect(returnNullableJS is JSClassA? Function(), true);
+ expect(returnNullableAnon is AnonymousClassA? Function(), true);
+ expect(returnNullableJS is JSClassA Function(), hasUnsoundNullSafety);
+ expect(
+ returnNullableAnon is AnonymousClassA Function(), hasUnsoundNullSafety);
+
+ // Subtyping between JS and anonymous classes.
+ expect(returnJS is AnonymousClassA Function(), true);
+ expect(returnAnon is JSClassA Function(), true);
+
+ // Subtyping between same type of package:js classes.
+ expect(returnJS is JSClassB Function(), true);
+ expect(returnAnon is AnonymousClassB Function(), true);
+
+ // No subtyping between JS/anonymous classes and Dart classes.
+ expect(returnJS is DartClass Function(), false);
+ expect(returnDartClass is JSClassA Function(), false);
+ expect(returnAnon is DartClass Function(), false);
+ expect(returnDartClass is AnonymousClassA Function(), false);
+
+ // Repeat the checks but using `confuse` to coerce runtime checks instead of
+ // compile-time like above.
+ expect(confuse(returnJS) is JSClassA Function(), true);
+ expect(confuse(returnAnon) is AnonymousClassA Function(), true);
+ expect(confuse(returnJS) is JSClassA? Function(), true);
+ expect(confuse(returnAnon) is AnonymousClassA? Function(), true);
+ expect(confuse(returnNullableJS) is JSClassA? Function(), true);
+ expect(confuse(returnNullableAnon) is AnonymousClassA? Function(), true);
+ expect(
+ confuse(returnNullableJS) is JSClassA Function(), hasUnsoundNullSafety);
+ expect(confuse(returnNullableAnon) is AnonymousClassA Function(),
+ hasUnsoundNullSafety);
+
+ expect(confuse(returnJS) is AnonymousClassA Function(), true);
+ expect(confuse(returnAnon) is JSClassA Function(), true);
+
+ expect(confuse(returnJS) is JSClassB Function(), true);
+ expect(confuse(returnAnon) is AnonymousClassB Function(), true);
+
+ expect(confuse(returnJS) is DartClass Function(), false);
+ expect(confuse(returnDartClass) is JSClassA Function(), false);
+ expect(confuse(returnAnon) is DartClass Function(), false);
+ expect(confuse(returnDartClass) is AnonymousClassA Function(), false);
+}
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index b931e84..9e573fb 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -36,8 +36,12 @@
[ $csp ]
html/js_interop_constructor_name/*: SkipByDesign # Issue 42085.
isolate/deferred_in_isolate2_test: Skip # Issue 16898. Deferred loading does not work from an isolate in CSP-mode
+js/extends_test/extends_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
+js/extends_test/extends_with_es6_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
js/instanceof_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
+js/is_check_and_as_cast_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
js/js_util/async_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
+js/js_util/javascriptobject_extensions_test.dart: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
js/js_util/jsify_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
js/js_util/promise_reject_null_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
js/js_util/properties_implicit_checks_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
@@ -72,9 +76,6 @@
async/slow_consumer2_test: SkipSlow # Times out. Issue 22050
async/stream_timeout_test: SkipSlow # Times out. Issue 22050
-[ $runtime == dart_precompiled || $runtime == vm ]
-isolate/isolate_stress_test: Skip # Issue 12588: Uses dart:html. This should be able to pass when we have wrapper-less tests.
-
# It makes no sense to run any test that uses spawnURI under the simulator
# as that would involve running CFE (the front end) in simulator mode
# to compile the URI file specified in spawnURI code.
diff --git a/tests/lib/lib_vm.status b/tests/lib/lib_vm.status
index 2489080..07ece5a 100644
--- a/tests/lib/lib_vm.status
+++ b/tests/lib/lib_vm.status
@@ -2,9 +2,6 @@
# 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.
-[ $runtime == vm ]
-isolate/*: Pass, Slow # https://dartbug.com/36097: Slower while isolate groups are being gradually enabled in JIT mode.
-
[ $runtime != vm ]
isolate/native_wrapper_message_test: Skip # A VM specific test.
@@ -88,90 +85,4 @@
convert/utf85_test: SkipSlow
[ $hot_reload || $hot_reload_rollback ]
-isolate/bool_from_environment_default_value_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/capability_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/compile_time_error_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/count_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/cross_isolate_message_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/enum_const_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/error_at_spawn_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/error_at_spawnuri_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/error_exit_at_spawn_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/error_exit_at_spawnuri_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/exit_at_spawn_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/exit_at_spawnuri_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/function_send1_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/function_send_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/handle_error2_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/handle_error3_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/handle_error_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/illegal_msg_function_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/illegal_msg_mirror_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/int32_length_overflow_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/int_from_environment_default_value_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/isolate_complex_messages_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/isolate_current_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/isolate_import_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/issue_21398_parent_isolate1_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/issue_21398_parent_isolate2_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/issue_21398_parent_isolate_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/issue_22778_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/issue_35626_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/issue_6610_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/kill2_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/kill_self_synchronously_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/kill_self_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/kill_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/large_byte_data_leak_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/large_byte_data_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/mandel_isolate_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/message2_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/message3_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/message4_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/message_const_type_arguments_1_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/message_const_type_arguments_2_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/message_enum_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/message_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/mint_maker_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/native_wrapper_message_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/nested_spawn2_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/nested_spawn_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/non_fatal_exception_in_timer_callback_test/none: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/non_fatal_exception_in_timer_callback_test/sleep: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/object_leak_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/ondone_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/package_config_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/package_resolve_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/package_root_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/pause_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/ping_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/port_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/raw_port_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/regress_34752_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/regress_flutter_22796_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/request_reply_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/resolve_package_uri_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/scenarios/package_data_uri_spec/package_resolve_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/send_private_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/simple_message_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/spawn_function_custom_class_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/spawn_function_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/spawn_generic_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/spawn_uri__package_uri__test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/spawn_uri_exported_main_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/spawn_uri_fail_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/spawn_uri_missing_from_isolate_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/spawn_uri_missing_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/spawn_uri_multi_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/spawn_uri_nested_vm_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/spawn_uri_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/spawn_uri_vm_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/start_paused_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/string_from_environment_default_value_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/timer_isolate_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/timer_multiple_isolates_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/transferable_failed_to_send_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/transferable_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/typed_message_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/unresolved_ports_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/vm_rehash_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
+isolate/int32_length_overflow_test: SkipSlow # Iterates over Uint8List(1 << 30).
diff --git a/tests/lib_2/html/js_typed_interop_lazy_test.dart b/tests/lib_2/html/js_typed_interop_lazy_test.dart
index a7b49a9..918193d 100644
--- a/tests/lib_2/html/js_typed_interop_lazy_test.dart
+++ b/tests/lib_2/html/js_typed_interop_lazy_test.dart
@@ -144,10 +144,9 @@
expect(new Object() is! AnonClass2, isTrue);
expect(<AnonClass>[] is List<AnonClass>, isTrue);
- // TODO(jacobr): why doesn't this test pass?
- // expect(<AnonClass>[] is List<AnonClass2>, isTrue);
+ expect(<AnonClass>[] is List<AnonClass2>, isTrue);
expect(<int>[] is! List<AnonClass>, isTrue);
- expect(<AnonClass>[] is! List<LazyClass>, isTrue); //# 01: ok
+ expect(<AnonClass>[] is List<LazyClass>, isTrue);
expect(<int>[] is! List<LazyClass>, isTrue);
expect(<LazyClass>[] is List<LazyClass>, isTrue);
@@ -236,10 +235,9 @@
expect(new Object() is! AnonClass2, isTrue);
expect(<AnonClass>[] is List<AnonClass>, isTrue);
- // TODO(jacobr): why doesn't this test pass?
- // expect(<AnonClass>[] is List<AnonClass2>, isTrue);
+ expect(<AnonClass>[] is List<AnonClass2>, isTrue);
expect(<int>[] is! List<AnonClass>, isTrue);
- expect(<AnonClass>[] is! List<NestedLazyClass>, isTrue); //# 01: ok
+ expect(<AnonClass>[] is List<NestedLazyClass>, isTrue);
expect(<int>[] is! List<NestedLazyClass>, isTrue);
expect(<NestedLazyClass>[] is List<NestedLazyClass>, isTrue);
diff --git a/tests/lib_2/isolate/bool_from_environment_default_value_test.dart b/tests/lib_2/isolate/bool_from_environment_default_value_test.dart
index 30ea663..fe0bd39 100644
--- a/tests/lib_2/isolate/bool_from_environment_default_value_test.dart
+++ b/tests/lib_2/isolate/bool_from_environment_default_value_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import "dart:isolate";
diff --git a/tests/lib_2/isolate/capability_test.dart b/tests/lib_2/isolate/capability_test.dart
index 04c39ee..5f4ef37 100644
--- a/tests/lib_2/isolate/capability_test.dart
+++ b/tests/lib_2/isolate/capability_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import "dart:isolate";
diff --git a/tests/lib_2/isolate/compile_time_error_test.dart b/tests/lib_2/isolate/compile_time_error_test.dart
index efadcd1..da85090 100644
--- a/tests/lib_2/isolate/compile_time_error_test.dart
+++ b/tests/lib_2/isolate/compile_time_error_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// Dart test program for testing that errors thrown from isolates are
diff --git a/tests/lib_2/isolate/count_test.dart b/tests/lib_2/isolate/count_test.dart
index 0d92759..e351ef9 100644
--- a/tests/lib_2/isolate/count_test.dart
+++ b/tests/lib_2/isolate/count_test.dart
@@ -4,7 +4,8 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
// VMOptions=--no-enable-isolate-groups
library CountTest;
diff --git a/tests/lib_2/isolate/cross_isolate_message_test.dart b/tests/lib_2/isolate/cross_isolate_message_test.dart
index f24a36e..59b9ed6 100644
--- a/tests/lib_2/isolate/cross_isolate_message_test.dart
+++ b/tests/lib_2/isolate/cross_isolate_message_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// Dart test program for testing that isolates can communicate to isolates
diff --git a/tests/lib_2/isolate/deferred_in_isolate2_test.dart b/tests/lib_2/isolate/deferred_in_isolate2_test.dart
index 4a4405b..0db87c3 100644
--- a/tests/lib_2/isolate/deferred_in_isolate2_test.dart
+++ b/tests/lib_2/isolate/deferred_in_isolate2_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
library deferred_in_isolate2_test;
diff --git a/tests/lib_2/isolate/deferred_in_isolate_test.dart b/tests/lib_2/isolate/deferred_in_isolate_test.dart
index d37817d..25d9fcf4 100644
--- a/tests/lib_2/isolate/deferred_in_isolate_test.dart
+++ b/tests/lib_2/isolate/deferred_in_isolate_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// Test that deferred libraries are supported from isolates other than the root
diff --git a/tests/lib_2/isolate/enum_const_test.dart b/tests/lib_2/isolate/enum_const_test.dart
index 5ce5c9b..b93202d 100644
--- a/tests/lib_2/isolate/enum_const_test.dart
+++ b/tests/lib_2/isolate/enum_const_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import "dart:isolate";
diff --git a/tests/lib_2/isolate/error_at_spawn_test.dart b/tests/lib_2/isolate/error_at_spawn_test.dart
index 9af087d..7eab826 100644
--- a/tests/lib_2/isolate/error_at_spawn_test.dart
+++ b/tests/lib_2/isolate/error_at_spawn_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
library error_at_spawn;
diff --git a/tests/lib_2/isolate/error_at_spawnuri_test.dart b/tests/lib_2/isolate/error_at_spawnuri_test.dart
index 66de296..8d7254d 100644
--- a/tests/lib_2/isolate/error_at_spawnuri_test.dart
+++ b/tests/lib_2/isolate/error_at_spawnuri_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
library error_at_spawnuri;
diff --git a/tests/lib_2/isolate/error_exit_at_spawn_test.dart b/tests/lib_2/isolate/error_exit_at_spawn_test.dart
index 1c493ef..17f5cd6 100644
--- a/tests/lib_2/isolate/error_exit_at_spawn_test.dart
+++ b/tests/lib_2/isolate/error_exit_at_spawn_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
library error_exit_at_spawn;
diff --git a/tests/lib_2/isolate/error_exit_at_spawnuri_test.dart b/tests/lib_2/isolate/error_exit_at_spawnuri_test.dart
index 29330ec..8b43578 100644
--- a/tests/lib_2/isolate/error_exit_at_spawnuri_test.dart
+++ b/tests/lib_2/isolate/error_exit_at_spawnuri_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
library error_exit_at_spawnuri;
diff --git a/tests/lib_2/isolate/exit_at_spawn_test.dart b/tests/lib_2/isolate/exit_at_spawn_test.dart
index d737c29..ca8cfa5 100644
--- a/tests/lib_2/isolate/exit_at_spawn_test.dart
+++ b/tests/lib_2/isolate/exit_at_spawn_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
library exit_at_spawn;
diff --git a/tests/lib_2/isolate/exit_at_spawnuri_test.dart b/tests/lib_2/isolate/exit_at_spawnuri_test.dart
index 3813adf..f6f4919 100644
--- a/tests/lib_2/isolate/exit_at_spawnuri_test.dart
+++ b/tests/lib_2/isolate/exit_at_spawnuri_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
library exit_at_spawn;
diff --git a/tests/lib_2/isolate/function_send1_test.dart b/tests/lib_2/isolate/function_send1_test.dart
index a706600..2acd91b 100644
--- a/tests/lib_2/isolate/function_send1_test.dart
+++ b/tests/lib_2/isolate/function_send1_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import "dart:isolate";
diff --git a/tests/lib_2/isolate/function_send_test.dart b/tests/lib_2/isolate/function_send_test.dart
index 8d24312..e5e72cf 100644
--- a/tests/lib_2/isolate/function_send_test.dart
+++ b/tests/lib_2/isolate/function_send_test.dart
@@ -4,7 +4,8 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
// VMOptions=--no-enable-isolate-groups
import "dart:isolate";
diff --git a/tests/lib_2/isolate/handle_error2_test.dart b/tests/lib_2/isolate/handle_error2_test.dart
index dd3b113..0a09262 100644
--- a/tests/lib_2/isolate/handle_error2_test.dart
+++ b/tests/lib_2/isolate/handle_error2_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
library handle_error_test;
diff --git a/tests/lib_2/isolate/handle_error3_test.dart b/tests/lib_2/isolate/handle_error3_test.dart
index 0f86863..4d4db96 100644
--- a/tests/lib_2/isolate/handle_error3_test.dart
+++ b/tests/lib_2/isolate/handle_error3_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
library handle_error_test;
diff --git a/tests/lib_2/isolate/handle_error_test.dart b/tests/lib_2/isolate/handle_error_test.dart
index 6c414db..cbc707f 100644
--- a/tests/lib_2/isolate/handle_error_test.dart
+++ b/tests/lib_2/isolate/handle_error_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
library handle_error_test;
diff --git a/tests/lib_2/isolate/illegal_msg_function_test.dart b/tests/lib_2/isolate/illegal_msg_function_test.dart
index f61432c..5ea24f0 100644
--- a/tests/lib_2/isolate/illegal_msg_function_test.dart
+++ b/tests/lib_2/isolate/illegal_msg_function_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
library illegal_msg_function_test;
diff --git a/tests/lib_2/isolate/illegal_msg_mirror_test.dart b/tests/lib_2/isolate/illegal_msg_mirror_test.dart
index c2fab94..ada58e9 100644
--- a/tests/lib_2/isolate/illegal_msg_mirror_test.dart
+++ b/tests/lib_2/isolate/illegal_msg_mirror_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
library illegal_msg_mirror_test;
diff --git a/tests/lib_2/isolate/int32_length_overflow_test.dart b/tests/lib_2/isolate/int32_length_overflow_test.dart
index 5d0273c..9d97252 100644
--- a/tests/lib_2/isolate/int32_length_overflow_test.dart
+++ b/tests/lib_2/isolate/int32_length_overflow_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import "dart:async";
diff --git a/tests/lib_2/isolate/int_from_environment_default_value_test.dart b/tests/lib_2/isolate/int_from_environment_default_value_test.dart
index 4733aaf..fdf1c67 100644
--- a/tests/lib_2/isolate/int_from_environment_default_value_test.dart
+++ b/tests/lib_2/isolate/int_from_environment_default_value_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import "dart:isolate";
diff --git a/tests/lib_2/isolate/isolate_complex_messages_test.dart b/tests/lib_2/isolate/isolate_complex_messages_test.dart
index 30322a1..6599829 100644
--- a/tests/lib_2/isolate/isolate_complex_messages_test.dart
+++ b/tests/lib_2/isolate/isolate_complex_messages_test.dart
@@ -4,7 +4,8 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
// VMOptions=--no-enable-isolate-groups
// Dart test program for testing isolate communication with
diff --git a/tests/lib_2/isolate/isolate_current_test.dart b/tests/lib_2/isolate/isolate_current_test.dart
index 3850591..c5d1432 100644
--- a/tests/lib_2/isolate/isolate_current_test.dart
+++ b/tests/lib_2/isolate/isolate_current_test.dart
@@ -4,7 +4,8 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
// VMOptions=--no-enable-isolate-groups
library isolate_current_test;
diff --git a/tests/lib_2/isolate/isolate_import_test.dart b/tests/lib_2/isolate/isolate_import_test.dart
index ff80fcb..02f5276 100644
--- a/tests/lib_2/isolate/isolate_import_test.dart
+++ b/tests/lib_2/isolate/isolate_import_test.dart
@@ -4,15 +4,15 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
library IsolateImportNegativeTest;
// Omitting the following import is an error:
-/* // //# 01: runtime error, compile-time error
+/* //# 01: compile-time error
import 'dart:isolate';
-*/ // //# 01: continued
+*/ //# 01: continued
import 'package:async_helper/async_helper.dart';
void entry(msg) {}
diff --git a/tests/lib_2/isolate/isolate_stress_test.dart b/tests/lib_2/isolate/isolate_stress_test.dart
deleted file mode 100644
index 81eb41b..0000000
--- a/tests/lib_2/isolate/isolate_stress_test.dart
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright (c) 2013, 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.
-
-// @dart = 2.9
-
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
-// VMOptions=--no-enable-isolate-groups
-
-// This test creates a lot of isolates. This is meant to exhaust
-// resources if the isolates aren't closed correctly (which happened
-// in dart2js).
-
-import 'dart:async';
-import 'dart:isolate';
-
-// TODO(12588): Remove this import when we have wrapper-less testing.
-import 'dart:html';
-
-worker(SendPort replyTo) {
- replyTo.send('Hello from Worker');
-}
-
-main() {
- try {
- // Create a Worker to confuse broken isolate implementation in dart2js.
- new Worker('data:application/javascript,').terminate();
- } catch (e) {
- // Ignored.
- }
- var doneClosure;
- int isolateCount = 0;
- spawnMany(reply) {
- if (reply != 'Hello from Worker') {
- throw new Exception('Unexpected reply from worker: $reply');
- }
- if (++isolateCount > 200) {
- window.postMessage('unittest-suite-success', '*');
- return;
- }
- ReceivePort response = new ReceivePort();
- var remote = Isolate.spawn(worker, response.sendPort);
- remote.then((_) => response.first).then(spawnMany);
- print('isolateCount = $isolateCount');
- }
-
- spawnMany('Hello from Worker');
- window.postMessage('unittest-suite-wait-for-done', '*');
-}
diff --git a/tests/lib_2/isolate/issue_21398_parent_isolate1_test.dart b/tests/lib_2/isolate/issue_21398_parent_isolate1_test.dart
index 4207c21..314d563 100644
--- a/tests/lib_2/isolate/issue_21398_parent_isolate1_test.dart
+++ b/tests/lib_2/isolate/issue_21398_parent_isolate1_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import 'dart:isolate';
diff --git a/tests/lib_2/isolate/issue_21398_parent_isolate2_test.dart b/tests/lib_2/isolate/issue_21398_parent_isolate2_test.dart
index b072fa3..a22fcb5 100644
--- a/tests/lib_2/isolate/issue_21398_parent_isolate2_test.dart
+++ b/tests/lib_2/isolate/issue_21398_parent_isolate2_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import 'dart:isolate';
diff --git a/tests/lib_2/isolate/issue_21398_parent_isolate_test.dart b/tests/lib_2/isolate/issue_21398_parent_isolate_test.dart
index 9459d31..86f28b4 100644
--- a/tests/lib_2/isolate/issue_21398_parent_isolate_test.dart
+++ b/tests/lib_2/isolate/issue_21398_parent_isolate_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import 'dart:isolate';
diff --git a/tests/lib_2/isolate/issue_22778_test.dart b/tests/lib_2/isolate/issue_22778_test.dart
index 05df46b..6675134 100644
--- a/tests/lib_2/isolate/issue_22778_test.dart
+++ b/tests/lib_2/isolate/issue_22778_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import "dart:isolate";
diff --git a/tests/lib_2/isolate/issue_24243_parent_isolate_test.dart b/tests/lib_2/isolate/issue_24243_parent_isolate_test.dart
index a991a25..7def95e 100644
--- a/tests/lib_2/isolate/issue_24243_parent_isolate_test.dart
+++ b/tests/lib_2/isolate/issue_24243_parent_isolate_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import 'dart:collection';
diff --git a/tests/lib_2/isolate/issue_35626_test.dart b/tests/lib_2/isolate/issue_35626_test.dart
index 9e9dbfe..83c371c 100644
--- a/tests/lib_2/isolate/issue_35626_test.dart
+++ b/tests/lib_2/isolate/issue_35626_test.dart
@@ -4,7 +4,8 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
// VMOptions=--no-enable-isolate-groups
// Tests that sets of enums can be set through ports.
diff --git a/tests/lib_2/isolate/kill2_test.dart b/tests/lib_2/isolate/kill2_test.dart
index 9918c9f..e363a3d 100644
--- a/tests/lib_2/isolate/kill2_test.dart
+++ b/tests/lib_2/isolate/kill2_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import "dart:isolate";
diff --git a/tests/lib_2/isolate/kill_infinite_loop_in_initializer_test.dart b/tests/lib_2/isolate/kill_infinite_loop_in_initializer_test.dart
new file mode 100644
index 0000000..591b187
--- /dev/null
+++ b/tests/lib_2/isolate/kill_infinite_loop_in_initializer_test.dart
@@ -0,0 +1,46 @@
+// 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.
+
+// @dart = 2.9
+
+// VMOptions=--enable-isolate-groups
+// VMOptions=--no-enable-isolate-groups
+
+// Regression test against out-of-band messages being blocked during lazy
+// static field initialization.
+
+import "dart:isolate";
+import "dart:async";
+import "package:expect/expect.dart";
+import "package:async_helper/async_helper.dart";
+
+dynamic staticFieldWithBadInitializer = badInitializer();
+
+badInitializer() {
+ print("badInitializer");
+ for (;;) {}
+ return 42; // Unreachable.
+}
+
+child(message) {
+ print("child");
+ RawReceivePort port = new RawReceivePort();
+ print(staticFieldWithBadInitializer);
+ port.close(); // Unreachable.
+}
+
+void main() {
+ asyncStart();
+ Isolate.spawn(child, null).then((Isolate isolate) {
+ print("spawned");
+ RawReceivePort exitSignal;
+ exitSignal = new RawReceivePort((_) {
+ print("onExit");
+ exitSignal.close();
+ asyncEnd();
+ });
+ isolate.addOnExitListener(exitSignal.sendPort);
+ isolate.kill(priority: Isolate.immediate);
+ });
+}
diff --git a/tests/lib_2/isolate/kill_self_synchronously_test.dart b/tests/lib_2/isolate/kill_self_synchronously_test.dart
index 3ddb461..74edac1 100644
--- a/tests/lib_2/isolate/kill_self_synchronously_test.dart
+++ b/tests/lib_2/isolate/kill_self_synchronously_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import "dart:isolate";
diff --git a/tests/lib_2/isolate/kill_self_test.dart b/tests/lib_2/isolate/kill_self_test.dart
index e78cb5e..0ea47b5 100644
--- a/tests/lib_2/isolate/kill_self_test.dart
+++ b/tests/lib_2/isolate/kill_self_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import "dart:isolate";
diff --git a/tests/lib_2/isolate/kill_test.dart b/tests/lib_2/isolate/kill_test.dart
index 0e695cf..dd53477 100644
--- a/tests/lib_2/isolate/kill_test.dart
+++ b/tests/lib_2/isolate/kill_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import "dart:isolate";
diff --git a/tests/lib_2/isolate/large_byte_data_leak_test.dart b/tests/lib_2/isolate/large_byte_data_leak_test.dart
index 7db4ff5..76fafd5 100644
--- a/tests/lib_2/isolate/large_byte_data_leak_test.dart
+++ b/tests/lib_2/isolate/large_byte_data_leak_test.dart
@@ -4,7 +4,8 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
// VMOptions=--no-enable-isolate-groups
import "dart:async";
diff --git a/tests/lib_2/isolate/large_byte_data_test.dart b/tests/lib_2/isolate/large_byte_data_test.dart
index 16811fa..ff55e0a 100644
--- a/tests/lib_2/isolate/large_byte_data_test.dart
+++ b/tests/lib_2/isolate/large_byte_data_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import "dart:async";
diff --git a/tests/lib_2/isolate/mandel_isolate_test.dart b/tests/lib_2/isolate/mandel_isolate_test.dart
index c7da8a9..1d75cb2 100644
--- a/tests/lib_2/isolate/mandel_isolate_test.dart
+++ b/tests/lib_2/isolate/mandel_isolate_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
library MandelIsolateTest;
diff --git a/tests/lib_2/isolate/message2_test.dart b/tests/lib_2/isolate/message2_test.dart
index ccb33b33..81892d4 100644
--- a/tests/lib_2/isolate/message2_test.dart
+++ b/tests/lib_2/isolate/message2_test.dart
@@ -4,7 +4,8 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
// VMOptions=--no-enable-isolate-groups
// Dart test program for testing serialization of messages.
diff --git a/tests/lib_2/isolate/message3_test.dart b/tests/lib_2/isolate/message3_test.dart
index b9813bd..f5c436d 100644
--- a/tests/lib_2/isolate/message3_test.dart
+++ b/tests/lib_2/isolate/message3_test.dart
@@ -4,7 +4,8 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
// VMOptions=--no-enable-isolate-groups
// Dart test program for testing serialization of messages.
diff --git a/tests/lib_2/isolate/message4_test.dart b/tests/lib_2/isolate/message4_test.dart
index 2d53736..045cde1 100644
--- a/tests/lib_2/isolate/message4_test.dart
+++ b/tests/lib_2/isolate/message4_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// Dart test program for testing serialization of messages with static
diff --git a/tests/lib_2/isolate/message_const_type_arguments_1_test.dart b/tests/lib_2/isolate/message_const_type_arguments_1_test.dart
index f4ffd0e..8e3144e 100644
--- a/tests/lib_2/isolate/message_const_type_arguments_1_test.dart
+++ b/tests/lib_2/isolate/message_const_type_arguments_1_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// https://github.com/dart-lang/sdk/issues/35778
diff --git a/tests/lib_2/isolate/message_const_type_arguments_2_test.dart b/tests/lib_2/isolate/message_const_type_arguments_2_test.dart
index 46d76d4..87c76ab 100644
--- a/tests/lib_2/isolate/message_const_type_arguments_2_test.dart
+++ b/tests/lib_2/isolate/message_const_type_arguments_2_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// https://github.com/dart-lang/sdk/issues/35778
diff --git a/tests/lib_2/isolate/message_enum_test.dart b/tests/lib_2/isolate/message_enum_test.dart
index e0fef28..5487f73 100644
--- a/tests/lib_2/isolate/message_enum_test.dart
+++ b/tests/lib_2/isolate/message_enum_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import 'package:expect/expect.dart';
diff --git a/tests/lib_2/isolate/message_test.dart b/tests/lib_2/isolate/message_test.dart
index b2cdf5a..7ca930a 100644
--- a/tests/lib_2/isolate/message_test.dart
+++ b/tests/lib_2/isolate/message_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// Dart test program for testing serialization of messages.
diff --git a/tests/lib_2/isolate/mint_maker_test.dart b/tests/lib_2/isolate/mint_maker_test.dart
index 7fd3650..9b1b15c 100644
--- a/tests/lib_2/isolate/mint_maker_test.dart
+++ b/tests/lib_2/isolate/mint_maker_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
library MintMakerTest;
diff --git a/tests/lib_2/isolate/native_wrapper_message_test.dart b/tests/lib_2/isolate/native_wrapper_message_test.dart
index 814a581..4c91d647 100644
--- a/tests/lib_2/isolate/native_wrapper_message_test.dart
+++ b/tests/lib_2/isolate/native_wrapper_message_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import 'dart:isolate';
diff --git a/tests/lib_2/isolate/nested_spawn2_test.dart b/tests/lib_2/isolate/nested_spawn2_test.dart
index 6a955ba..5c0c8be 100644
--- a/tests/lib_2/isolate/nested_spawn2_test.dart
+++ b/tests/lib_2/isolate/nested_spawn2_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// Dart test program for testing that isolates can spawn other isolates and
diff --git a/tests/lib_2/isolate/nested_spawn_test.dart b/tests/lib_2/isolate/nested_spawn_test.dart
index 095f790..050f383 100644
--- a/tests/lib_2/isolate/nested_spawn_test.dart
+++ b/tests/lib_2/isolate/nested_spawn_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// Dart test program for testing that isolates can spawn other isolates.
diff --git a/tests/lib_2/isolate/non_fatal_exception_in_timer_callback_test.dart b/tests/lib_2/isolate/non_fatal_exception_in_timer_callback_test.dart
index 352827f..03db0b8 100644
--- a/tests/lib_2/isolate/non_fatal_exception_in_timer_callback_test.dart
+++ b/tests/lib_2/isolate/non_fatal_exception_in_timer_callback_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import 'dart:async';
diff --git a/tests/lib_2/isolate/object_leak_test.dart b/tests/lib_2/isolate/object_leak_test.dart
index aee8af3..719b8d8 100644
--- a/tests/lib_2/isolate/object_leak_test.dart
+++ b/tests/lib_2/isolate/object_leak_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// Regression test for http://dartbug.com/18942
diff --git a/tests/lib_2/isolate/ondone_test.dart b/tests/lib_2/isolate/ondone_test.dart
index 2ca9592..bc5d363 100644
--- a/tests/lib_2/isolate/ondone_test.dart
+++ b/tests/lib_2/isolate/ondone_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import "dart:isolate";
diff --git a/tests/lib_2/isolate/package_config_test.dart b/tests/lib_2/isolate/package_config_test.dart
index 25b7b48..264aba2 100644
--- a/tests/lib_2/isolate/package_config_test.dart
+++ b/tests/lib_2/isolate/package_config_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// VMOptions=--trace_shutdown
import 'dart:io';
diff --git a/tests/lib_2/isolate/package_resolve_test.dart b/tests/lib_2/isolate/package_resolve_test.dart
index efb4fd6..c36c430 100644
--- a/tests/lib_2/isolate/package_resolve_test.dart
+++ b/tests/lib_2/isolate/package_resolve_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import 'dart:io';
diff --git a/tests/lib_2/isolate/package_root_test.dart b/tests/lib_2/isolate/package_root_test.dart
index e29f99b..a8ef249 100644
--- a/tests/lib_2/isolate/package_root_test.dart
+++ b/tests/lib_2/isolate/package_root_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import 'dart:io';
diff --git a/tests/lib_2/isolate/pause_test.dart b/tests/lib_2/isolate/pause_test.dart
index 20a588b..240229e 100644
--- a/tests/lib_2/isolate/pause_test.dart
+++ b/tests/lib_2/isolate/pause_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import "dart:isolate";
diff --git a/tests/lib_2/isolate/ping_pause_test.dart b/tests/lib_2/isolate/ping_pause_test.dart
index b96b0b1..2c14c4f 100644
--- a/tests/lib_2/isolate/ping_pause_test.dart
+++ b/tests/lib_2/isolate/ping_pause_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import "dart:isolate";
diff --git a/tests/lib_2/isolate/ping_test.dart b/tests/lib_2/isolate/ping_test.dart
index 79cad0e..8f191b5 100644
--- a/tests/lib_2/isolate/ping_test.dart
+++ b/tests/lib_2/isolate/ping_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import "dart:isolate";
diff --git a/tests/lib_2/isolate/port_test.dart b/tests/lib_2/isolate/port_test.dart
index 1493048..b46a048 100644
--- a/tests/lib_2/isolate/port_test.dart
+++ b/tests/lib_2/isolate/port_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// Test properties of ports.
diff --git a/tests/lib_2/isolate/raw_port_test.dart b/tests/lib_2/isolate/raw_port_test.dart
index cd9c7c2..08c1cc9 100644
--- a/tests/lib_2/isolate/raw_port_test.dart
+++ b/tests/lib_2/isolate/raw_port_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// Test RawReceivePort.
diff --git a/tests/lib_2/isolate/regress_34752_test.dart b/tests/lib_2/isolate/regress_34752_test.dart
index 7390247..8fe3c74 100644
--- a/tests/lib_2/isolate/regress_34752_test.dart
+++ b/tests/lib_2/isolate/regress_34752_test.dart
@@ -4,7 +4,8 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
// VMOptions=--no-enable-isolate-groups
// Verifies that large BigInt can be passed through a message port and
diff --git a/tests/lib_2/isolate/regress_flutter_22796_test.dart b/tests/lib_2/isolate/regress_flutter_22796_test.dart
index 1fe759b..72200b8 100644
--- a/tests/lib_2/isolate/regress_flutter_22796_test.dart
+++ b/tests/lib_2/isolate/regress_flutter_22796_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// Verifies that large typed data can be passed in a field through message port.
diff --git a/tests/lib_2/isolate/request_reply_test.dart b/tests/lib_2/isolate/request_reply_test.dart
index 3802b40..a2a0f53 100644
--- a/tests/lib_2/isolate/request_reply_test.dart
+++ b/tests/lib_2/isolate/request_reply_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
library RequestReplyTest;
diff --git a/tests/lib_2/isolate/resolve_package_uri_test.dart b/tests/lib_2/isolate/resolve_package_uri_test.dart
index 2cab226..ce53991 100644
--- a/tests/lib_2/isolate/resolve_package_uri_test.dart
+++ b/tests/lib_2/isolate/resolve_package_uri_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// Regression test for faulty encoding of `Isolate.resolvePackageUri` by
diff --git a/tests/lib_2/isolate/scenarios/package_data_uri_spec/package_resolve_test.dart b/tests/lib_2/isolate/scenarios/package_data_uri_spec/package_resolve_test.dart
index efb4fd6..c36c430 100644
--- a/tests/lib_2/isolate/scenarios/package_data_uri_spec/package_resolve_test.dart
+++ b/tests/lib_2/isolate/scenarios/package_data_uri_spec/package_resolve_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import 'dart:io';
diff --git a/tests/lib_2/isolate/send_private_test.dart b/tests/lib_2/isolate/send_private_test.dart
index f8481ec..645c12b 100644
--- a/tests/lib_2/isolate/send_private_test.dart
+++ b/tests/lib_2/isolate/send_private_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import "dart:isolate";
diff --git a/tests/lib_2/isolate/simple_message_test.dart b/tests/lib_2/isolate/simple_message_test.dart
index bb549cb..f5a394c 100644
--- a/tests/lib_2/isolate/simple_message_test.dart
+++ b/tests/lib_2/isolate/simple_message_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// Dart test program for testing that isolates are spawned.
diff --git a/tests/lib_2/isolate/spawn_function_custom_class_test.dart b/tests/lib_2/isolate/spawn_function_custom_class_test.dart
index 45151be..0e9ad2b 100644
--- a/tests/lib_2/isolate/spawn_function_custom_class_test.dart
+++ b/tests/lib_2/isolate/spawn_function_custom_class_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// Create a user-defined class in a new isolate.
diff --git a/tests/lib_2/isolate/spawn_function_test.dart b/tests/lib_2/isolate/spawn_function_test.dart
index b8b7659..b12246e 100644
--- a/tests/lib_2/isolate/spawn_function_test.dart
+++ b/tests/lib_2/isolate/spawn_function_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// Example of spawning an isolate from a function.
diff --git a/tests/lib_2/isolate/spawn_generic_test.dart b/tests/lib_2/isolate/spawn_generic_test.dart
index f73b711..05ea808 100644
--- a/tests/lib_2/isolate/spawn_generic_test.dart
+++ b/tests/lib_2/isolate/spawn_generic_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// Check that Isolate.spawn is generic.
diff --git a/tests/lib_2/isolate/spawn_uri_exported_main_test.dart b/tests/lib_2/isolate/spawn_uri_exported_main_test.dart
index ba704e8..463181f 100644
--- a/tests/lib_2/isolate/spawn_uri_exported_main_test.dart
+++ b/tests/lib_2/isolate/spawn_uri_exported_main_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import "dart:async";
diff --git a/tests/lib_2/isolate/spawn_uri_fail_test.dart b/tests/lib_2/isolate/spawn_uri_fail_test.dart
index 06b6bf5..9b5346f 100644
--- a/tests/lib_2/isolate/spawn_uri_fail_test.dart
+++ b/tests/lib_2/isolate/spawn_uri_fail_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import "dart:io";
diff --git a/tests/lib_2/isolate/spawn_uri_missing_from_isolate_test.dart b/tests/lib_2/isolate/spawn_uri_missing_from_isolate_test.dart
index a7f9e7a..204fa9c 100644
--- a/tests/lib_2/isolate/spawn_uri_missing_from_isolate_test.dart
+++ b/tests/lib_2/isolate/spawn_uri_missing_from_isolate_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
/// Tests that Isolate.spawnUri completes with an error when the given URI
diff --git a/tests/lib_2/isolate/spawn_uri_missing_test.dart b/tests/lib_2/isolate/spawn_uri_missing_test.dart
index 83aa2e9..fe27ff0 100644
--- a/tests/lib_2/isolate/spawn_uri_missing_test.dart
+++ b/tests/lib_2/isolate/spawn_uri_missing_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
/// Tests that Isolate.spanUri completes with an error when the given URI
diff --git a/tests/lib_2/isolate/spawn_uri_multi_test.dart b/tests/lib_2/isolate/spawn_uri_multi_test.dart
index 83eb117..dc50328 100644
--- a/tests/lib_2/isolate/spawn_uri_multi_test.dart
+++ b/tests/lib_2/isolate/spawn_uri_multi_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// Negative test to make sure that we are reaching all assertions.
diff --git a/tests/lib_2/isolate/spawn_uri_nested_vm_test.dart b/tests/lib_2/isolate/spawn_uri_nested_vm_test.dart
index 6ecabb1..423821d 100644
--- a/tests/lib_2/isolate/spawn_uri_nested_vm_test.dart
+++ b/tests/lib_2/isolate/spawn_uri_nested_vm_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// Example of nested spawning of isolates from a URI
diff --git a/tests/lib_2/isolate/spawn_uri_test.dart b/tests/lib_2/isolate/spawn_uri_test.dart
index 1698d46..88e99bf 100644
--- a/tests/lib_2/isolate/spawn_uri_test.dart
+++ b/tests/lib_2/isolate/spawn_uri_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// Example of spawning an isolate from a URI
diff --git a/tests/lib_2/isolate/spawn_uri_vm_test.dart b/tests/lib_2/isolate/spawn_uri_vm_test.dart
index e64db64..536b912 100644
--- a/tests/lib_2/isolate/spawn_uri_vm_test.dart
+++ b/tests/lib_2/isolate/spawn_uri_vm_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// Example of spawning an isolate from a URI
diff --git a/tests/lib_2/isolate/start_paused_test.dart b/tests/lib_2/isolate/start_paused_test.dart
index 3005918..7ee4993 100644
--- a/tests/lib_2/isolate/start_paused_test.dart
+++ b/tests/lib_2/isolate/start_paused_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
library start_paused_test;
diff --git a/tests/lib_2/isolate/static_function_test.dart b/tests/lib_2/isolate/static_function_test.dart
index e213876..17f18e5 100644
--- a/tests/lib_2/isolate/static_function_test.dart
+++ b/tests/lib_2/isolate/static_function_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// Test starting isolate with static functions (and toplevel ones, for sanity).
diff --git a/tests/lib_2/isolate/string_from_environment_default_value_test.dart b/tests/lib_2/isolate/string_from_environment_default_value_test.dart
index 46c48a5..f920f65 100644
--- a/tests/lib_2/isolate/string_from_environment_default_value_test.dart
+++ b/tests/lib_2/isolate/string_from_environment_default_value_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import "dart:isolate";
diff --git a/tests/lib_2/isolate/timer_isolate_test.dart b/tests/lib_2/isolate/timer_isolate_test.dart
index 972f592..07485a6 100644
--- a/tests/lib_2/isolate/timer_isolate_test.dart
+++ b/tests/lib_2/isolate/timer_isolate_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
library multiple_timer_test;
diff --git a/tests/lib_2/isolate/timer_multiple_isolates_test.dart b/tests/lib_2/isolate/timer_multiple_isolates_test.dart
index 29bab19..0321a8b 100644
--- a/tests/lib_2/isolate/timer_multiple_isolates_test.dart
+++ b/tests/lib_2/isolate/timer_multiple_isolates_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
library timer_multiple_isolates_test;
diff --git a/tests/lib_2/isolate/transferable_failed_to_send_test.dart b/tests/lib_2/isolate/transferable_failed_to_send_test.dart
index 8ee6226..8f339585 100644
--- a/tests/lib_2/isolate/transferable_failed_to_send_test.dart
+++ b/tests/lib_2/isolate/transferable_failed_to_send_test.dart
@@ -4,7 +4,8 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
// VMOptions=--no-enable-isolate-groups
import "dart:io" show ServerSocket;
diff --git a/tests/lib_2/isolate/transferable_test.dart b/tests/lib_2/isolate/transferable_test.dart
index aef8d97..26cb2e0 100644
--- a/tests/lib_2/isolate/transferable_test.dart
+++ b/tests/lib_2/isolate/transferable_test.dart
@@ -4,7 +4,8 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups --no-enable-fast-object-copy
+// VMOptions=--enable-isolate-groups --enable-fast-object-copy
// VMOptions=--no-enable-isolate-groups
import "dart:async";
diff --git a/tests/lib_2/isolate/type_ref_message_test.dart b/tests/lib_2/isolate/type_ref_message_test.dart
new file mode 100644
index 0000000..8dd2a79
--- /dev/null
+++ b/tests/lib_2/isolate/type_ref_message_test.dart
@@ -0,0 +1,33 @@
+// 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.
+
+// See https://github.com/flutter/flutter/issues/84691
+
+// @dart = 2.9
+
+import "dart:async";
+import "dart:isolate";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+
+class B<T> {}
+class D<S> extends B<D> {}
+
+main() {
+ asyncStart();
+ var port;
+ port = new RawReceivePort((message) {
+ var list = message as List<D<String>>;
+ var element = list[0] as D<String>;
+
+ port.close();
+ asyncEnd();
+ });
+
+
+ var list = <D<String>>[ new D() ];
+ port.sendPort.send(list);
+}
diff --git a/tests/lib_2/isolate/typed_message_test.dart b/tests/lib_2/isolate/typed_message_test.dart
index 0700261..3b30415 100644
--- a/tests/lib_2/isolate/typed_message_test.dart
+++ b/tests/lib_2/isolate/typed_message_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// Dart test program for testing isolate communication with
// typed objects.
diff --git a/tests/lib_2/isolate/unresolved_ports_test.dart b/tests/lib_2/isolate/unresolved_ports_test.dart
index e930123..408a26e 100644
--- a/tests/lib_2/isolate/unresolved_ports_test.dart
+++ b/tests/lib_2/isolate/unresolved_ports_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
// spawns multiple isolates and sends unresolved ports between them.
diff --git a/tests/lib_2/isolate/vm_rehash_test.dart b/tests/lib_2/isolate/vm_rehash_test.dart
index b854343..3813b67 100644
--- a/tests/lib_2/isolate/vm_rehash_test.dart
+++ b/tests/lib_2/isolate/vm_rehash_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import 'dart:async';
diff --git a/tests/lib_2/isolate/weak_property_message_1_test.dart b/tests/lib_2/isolate/weak_property_message_1_test.dart
new file mode 100644
index 0000000..fa8a6d1
--- /dev/null
+++ b/tests/lib_2/isolate/weak_property_message_1_test.dart
@@ -0,0 +1,50 @@
+// 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.
+
+// See https://github.com/dart-lang/sdk/issues/25559
+
+// @dart = 2.9
+
+import "dart:async";
+import "dart:isolate";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+main() {
+ asyncStart();
+ var port;
+ port = new RawReceivePort((message) {
+ var expando1 = message[0] as Expando;
+ var expando2 = message[1] as Expando;
+ var expando3 = message[2] as Expando;
+ var key1 = message[3];
+
+ var key2 = expando1[key1];
+ Expect.isNotNull(key2);
+ var key3 = expando2[key2];
+ Expect.isNotNull(key3);
+ var value = expando3[key3];
+ Expect.equals(value, "value");
+
+ port.close();
+ asyncEnd();
+ });
+
+
+ var key1 = new Object();
+ var key2 = new Object();
+ var key3 = new Object();
+ var expando1 = new Expando();
+ var expando2 = new Expando();
+ var expando3 = new Expando();
+ expando1[key1] = key2;
+ expando2[key2] = key3;
+ expando3[key3] = "value";
+
+ // key1 is placed after expando1 so that its reachability is uncertain when
+ // expando1 is first encountered.
+ var message = <dynamic>[expando1, expando2, expando3, key1];
+ port.sendPort.send(message);
+}
diff --git a/tests/lib_2/isolate/weak_property_message_2_test.dart b/tests/lib_2/isolate/weak_property_message_2_test.dart
new file mode 100644
index 0000000..7b5ad95
--- /dev/null
+++ b/tests/lib_2/isolate/weak_property_message_2_test.dart
@@ -0,0 +1,36 @@
+// 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.
+
+// See https://github.com/dart-lang/sdk/issues/25559
+
+// @dart = 2.9
+
+import "dart:async";
+import "dart:developer";
+import "dart:isolate";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+main() {
+ asyncStart();
+ var port;
+ port = new RawReceivePort((message) {
+ var expando = message as Expando;
+
+ // Sent and received without error.
+
+ port.close();
+ asyncEnd();
+ });
+
+
+ var unwrittenKey = new Object();
+ var expando = new Expando();
+ expando[unwrittenKey] = new UserTag("cant send this");
+
+ port.sendPort.send(expando);
+
+ print(unwrittenKey); // Ensure [unwrittenKey] is live during [send].
+}
diff --git a/tests/lib_2/js/extends_test/extends_subtyping_live_test.dart b/tests/lib_2/js/extends_test/extends_subtyping_live_test.dart
new file mode 100644
index 0000000..b46818e
--- /dev/null
+++ b/tests/lib_2/js/extends_test/extends_subtyping_live_test.dart
@@ -0,0 +1,20 @@
+// 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.
+
+// Tests inheritance subtyping relationships after making package:js types live.
+
+@JS()
+library extends_subtyping_live_test;
+
+import 'package:js/js.dart';
+import 'extends_test_util.dart';
+
+@JS()
+external dynamic get externalGetter;
+
+void main() {
+ // Call to foreign function should trigger dart2js to assume types are live.
+ externalGetter;
+ testSubtyping();
+}
diff --git a/tests/lib_2/js/extends_test/extends_subtyping_not_live_test.dart b/tests/lib_2/js/extends_test/extends_subtyping_not_live_test.dart
new file mode 100644
index 0000000..3cb0fbb
--- /dev/null
+++ b/tests/lib_2/js/extends_test/extends_subtyping_not_live_test.dart
@@ -0,0 +1,12 @@
+// 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.
+
+// Tests inheritance subtyping relationships without making package:js types
+// live.
+
+import 'extends_test_util.dart';
+
+void main() {
+ testSubtyping();
+}
diff --git a/tests/lib/js/extends_test/extends_subtyping_test.dart b/tests/lib_2/js/extends_test/extends_test.dart
similarity index 72%
rename from tests/lib/js/extends_test/extends_subtyping_test.dart
rename to tests/lib_2/js/extends_test/extends_test.dart
index 76dc51e..4286838 100644
--- a/tests/lib/js/extends_test/extends_subtyping_test.dart
+++ b/tests/lib_2/js/extends_test/extends_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// 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.
@@ -6,5 +6,5 @@
void main() {
setUpWithoutES6Syntax();
- testSubtyping();
+ testInheritance();
}
diff --git a/tests/lib_2/js/extends_test/extends_test_util.dart b/tests/lib_2/js/extends_test/extends_test_util.dart
new file mode 100644
index 0000000..9a21c51
--- /dev/null
+++ b/tests/lib_2/js/extends_test/extends_test_util.dart
@@ -0,0 +1,278 @@
+// 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.
+
+// Tests inheritance relationships between `JS` and `anonymous` classes/objects.
+
+@JS()
+library extends_test;
+
+import 'package:expect/minitest.dart';
+import 'package:js/js.dart';
+
+@JS()
+external void eval(String code);
+
+@JS()
+class JSClass {
+ external JSClass();
+ external int get a;
+ external int getA();
+ external int getAOrB();
+}
+
+@JS()
+@anonymous
+class AnonymousClass {
+ external int get a;
+ external int getA();
+}
+
+@JS()
+class JSExtendJSClass extends JSClass {
+ external JSExtendJSClass(int a, int b);
+ external int get b;
+ external int getB();
+ external int getAOrB();
+}
+
+@JS()
+class JSExtendAnonymousClass extends AnonymousClass {
+ external JSExtendAnonymousClass(int a, int b);
+ external int get b;
+ external int getB();
+}
+
+@JS()
+@anonymous
+class AnonymousExtendAnonymousClass extends AnonymousClass {
+ external int get b;
+ external int getB();
+}
+
+@JS()
+@anonymous
+class AnonymousExtendJSClass extends JSClass {
+ external int get b;
+ external int getB();
+ external int getAOrB();
+}
+
+external AnonymousClass get anon;
+external AnonymousExtendAnonymousClass get anonExtendAnon;
+external AnonymousExtendJSClass get anonExtendJS;
+
+void setUpWithoutES6Syntax() {
+ // Use the old way to define inheritance between JS objects.
+ eval(r"""
+ function inherits(child, parent) {
+ if (child.prototype.__proto__) {
+ child.prototype.__proto__ = parent.prototype;
+ } else {
+ function tmp() {};
+ tmp.prototype = parent.prototype;
+ child.prototype = new tmp();
+ child.prototype.constructor = child;
+ }
+ }
+ function JSClass(a) {
+ if (arguments.length == 0) a = 1;
+ this.a = a;
+ this.getA = function() {
+ return this.a;
+ }
+ this.getAOrB = function() {
+ return this.getA();
+ }
+ }
+ function JSExtendJSClass(a, b) {
+ JSClass.call(this, a);
+ this.b = b;
+ this.getB = function() {
+ return this.b;
+ }
+ this.getAOrB = function() {
+ return this.getB();
+ }
+ }
+ inherits(JSExtendJSClass, JSClass);
+ function JSExtendAnonymousClass(a, b) {
+ this.a = a;
+ this.b = b;
+ this.getA = function() {
+ return this.a;
+ }
+ this.getB = function() {
+ return this.b;
+ }
+ this.getAOrB = function() {
+ return this.getB();
+ }
+ }
+ self.anon = new JSClass(1);
+ self.anonExtendAnon = new JSExtendAnonymousClass(1, 2);
+ self.anonExtendJS = new JSExtendJSClass(1, 2);
+ """);
+}
+
+void setUpWithES6Syntax() {
+ // Use the ES6 syntax for classes to make inheritance easier.
+ eval(r"""
+ class JSClass {
+ constructor(a) {
+ if (arguments.length == 0) a = 1;
+ this.a = a;
+ }
+ getA() {
+ return this.a;
+ }
+ getAOrB() {
+ return this.getA();
+ }
+ }
+ self.JSClass = JSClass;
+ class JSExtendJSClass extends JSClass {
+ constructor(a, b) {
+ super(a);
+ this.b = b;
+ }
+ getB() {
+ return this.b;
+ }
+ getAOrB() {
+ return this.getB();
+ }
+ }
+ self.JSExtendJSClass = JSExtendJSClass;
+ class JSExtendAnonymousClass {
+ constructor(a, b) {
+ this.a = a;
+ this.b = b;
+ }
+ getA() {
+ return this.a;
+ }
+ getB() {
+ return this.b;
+ }
+ getAOrB() {
+ return this.getB();
+ }
+ }
+ self.JSExtendAnonymousClass = JSExtendAnonymousClass;
+ self.anon = new JSClass(1);
+ self.anonExtendAnon = new JSExtendAnonymousClass(1, 2);
+ self.anonExtendJS = new JSExtendJSClass(1, 2);
+ """);
+}
+
+void testInheritance() {
+ var jsExtendJS = JSExtendJSClass(1, 2);
+ expect(jsExtendJS.a, 1);
+ expect(jsExtendJS.b, 2);
+ expect(jsExtendJS.getA(), 1);
+ expect(jsExtendJS.getB(), 2);
+ // Test method overrides.
+ expect(jsExtendJS.getAOrB(), 2);
+ expect((jsExtendJS as JSClass).getAOrB(), 2);
+
+ var jsExtendAnon = JSExtendAnonymousClass(1, 2);
+ expect(jsExtendAnon.a, 1);
+ expect(jsExtendAnon.b, 2);
+ expect(jsExtendAnon.getA(), 1);
+ expect(jsExtendAnon.getB(), 2);
+
+ expect(anonExtendAnon.a, 1);
+ expect(anonExtendAnon.b, 2);
+ expect(anonExtendAnon.getA(), 1);
+ expect(anonExtendAnon.getB(), 2);
+
+ expect(anonExtendJS.a, 1);
+ expect(anonExtendJS.b, 2);
+ expect(anonExtendJS.getA(), 1);
+ expect(anonExtendJS.getB(), 2);
+ expect(anonExtendJS.getAOrB(), 2);
+ expect((anonExtendJS as JSClass).getAOrB(), 2);
+
+ // Test type checking and casts succeeds regardless of type hierarchy.
+
+ // Test type checking at runtime by disabling inlining. We still, however, do
+ // `is` checks directly below to test those optimizations.
+ @pragma('dart2js:noInline')
+ void runtimeIsAndAs<T>(instance) {
+ expect(instance is T, true);
+ expect(() => instance as T, returnsNormally);
+ }
+
+ // Test that base JS type can be used as any subtype.
+ var js = JSClass();
+ expect(js is JSExtendJSClass, true);
+ runtimeIsAndAs<JSExtendJSClass>(js);
+ expect(js is AnonymousExtendJSClass, true);
+ runtimeIsAndAs<AnonymousExtendJSClass>(js);
+
+ // Test that base anonymous type can be use as any subtype.
+ // Conversion from external getter value to a variable is needed to coerce
+ // compile time optimization of type checks. This applies for below as well.
+ var anonVar = anon;
+ expect(anonVar is JSExtendAnonymousClass, true);
+ runtimeIsAndAs<JSExtendAnonymousClass>(anonVar);
+ expect(anonVar is AnonymousExtendAnonymousClass, true);
+ runtimeIsAndAs<AnonymousExtendAnonymousClass>(anonVar);
+
+ // Test that instance of subtypes can be used as their JS supertype.
+ expect(jsExtendJS is JSClass, true);
+ runtimeIsAndAs<JSClass>(jsExtendJS);
+ var anonExtendJSVar = anonExtendJS;
+ expect(anonExtendJSVar is JSClass, true);
+ runtimeIsAndAs<JSClass>(anonExtendJSVar);
+
+ // Test that instance of subtypes can be used as their anonymous supertype.
+ var anonExtendAnonVar = anonExtendAnon;
+ expect(anonExtendAnonVar is AnonymousClass, true);
+ runtimeIsAndAs<AnonymousClass>(anonExtendAnonVar);
+ expect(jsExtendAnon is AnonymousClass, true);
+ runtimeIsAndAs<AnonymousClass>(jsExtendAnon);
+}
+
+JSClass returnJS() => throw '';
+
+AnonymousClass returnAnon() => throw '';
+
+JSExtendJSClass returnJSExtendJS() => throw '';
+
+JSExtendAnonymousClass returnJSExtendAnon() => throw '';
+
+AnonymousExtendJSClass returnAnonExtendJS() => throw '';
+
+AnonymousExtendAnonymousClass returnAnonExtendAnon() => throw '';
+
+@pragma('dart2js:noInline')
+void isRuntimeSubtypeBothWays<T, U>() {
+ // Test T <: U and U <: T. With interop types, type checks should pass
+ // regardless of type hierarchy. Note that dart2js does these type checks at
+ // runtime. Below, we do compile-time checks using top-level functions.
+ T f1() => throw '';
+ U f2() => throw '';
+ expect(f1 is U Function(), true);
+ expect(f2 is T Function(), true);
+}
+
+void testSubtyping() {
+ // Test subtyping for inheritance between JS and anonymous classes.
+ expect(returnJS is JSExtendJSClass Function(), true);
+ expect(returnJSExtendJS is JSClass Function(), true);
+ isRuntimeSubtypeBothWays<JSClass, JSExtendJSClass>();
+
+ expect(returnJS is AnonymousExtendJSClass Function(), true);
+ expect(returnAnonExtendJS is JSClass Function(), true);
+ isRuntimeSubtypeBothWays<JSClass, AnonymousExtendJSClass>();
+
+ expect(returnAnon is JSExtendAnonymousClass Function(), true);
+ expect(returnJSExtendAnon is AnonymousClass Function(), true);
+ isRuntimeSubtypeBothWays<AnonymousClass, JSExtendAnonymousClass>();
+
+ expect(returnAnon is AnonymousExtendAnonymousClass Function(), true);
+ expect(returnAnonExtendAnon is AnonymousClass Function(), true);
+ isRuntimeSubtypeBothWays<AnonymousClass, AnonymousExtendAnonymousClass>();
+}
diff --git a/tests/lib/js/extends_test/extends_with_es6_subtyping_test.dart b/tests/lib_2/js/extends_test/extends_with_es6_test.dart
similarity index 72%
rename from tests/lib/js/extends_test/extends_with_es6_subtyping_test.dart
rename to tests/lib_2/js/extends_test/extends_with_es6_test.dart
index e6185da..e0ed10d 100644
--- a/tests/lib/js/extends_test/extends_with_es6_subtyping_test.dart
+++ b/tests/lib_2/js/extends_test/extends_with_es6_test.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// 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.
@@ -6,5 +6,5 @@
void main() {
setUpWithES6Syntax();
- testSubtyping();
+ testInheritance();
}
diff --git a/tests/lib_2/js/external_nonjs_static_test.dart b/tests/lib_2/js/external_nonjs_static_test.dart
index 6635d27..d0fa7df 100644
--- a/tests/lib_2/js/external_nonjs_static_test.dart
+++ b/tests/lib_2/js/external_nonjs_static_test.dart
@@ -9,6 +9,7 @@
library external_nonjs_static_test;
+import 'dart:html';
import 'package:js/js.dart';
external get topLevelGetter;
@@ -72,4 +73,63 @@
// [web] Only JS interop members may be 'external'.
}
+extension ExtensionNonJS on NonJSClass {
+ external get getter;
+ // ^
+ // [web] JS interop or Native class required for 'external' extension members.
+ external set setter(_);
+ // ^
+ // [web] JS interop or Native class required for 'external' extension members.
+
+ external static get staticGetter;
+ // ^
+ // [web] JS interop or Native class required for 'external' extension members.
+ external static set staticSetter(_);
+ // ^
+ // [web] JS interop or Native class required for 'external' extension members.
+
+ external method();
+ // ^
+ // [web] JS interop or Native class required for 'external' extension members.
+ external static staticMethod();
+ // ^
+ // [web] JS interop or Native class required for 'external' extension members.
+ external optionalParameterMethod([int a, int b = 0]);
+ // ^
+ // [web] JS interop or Native class required for 'external' extension members.
+ external overridenMethod();
+ // ^
+ // [web] JS interop or Native class required for 'external' extension members.
+
+ nonExternalMethod() => 1;
+ static nonExternalStaticMethod() => 2;
+}
+
+class NonJSClass {
+ void overridenMethod() => 5;
+}
+
+extension ExtensionGenericNonJS<T> on GenericNonJSClass<T> {
+ external T method();
+ // ^
+ // [web] JS interop or Native class required for 'external' extension members.
+}
+
+class GenericNonJSClass<T> {}
+
+extension ExtensionNative on HtmlElement {
+ external get getter;
+ external set setter(_);
+
+ external static get staticGetter;
+ external static set staticSetter(_);
+
+ external method();
+ external static staticMethod();
+ external optionalParameterMethod([int a, int b = 0]);
+
+ nonExternalMethod() => 1;
+ static nonExternalStaticMethod() => 2;
+}
+
main() {}
diff --git a/tests/lib_2/js/external_static_test.dart b/tests/lib_2/js/external_static_test.dart
index 8ac09be..8084a72 100644
--- a/tests/lib_2/js/external_static_test.dart
+++ b/tests/lib_2/js/external_static_test.dart
@@ -10,6 +10,7 @@
@JS()
library external_static_test;
+import 'dart:html';
import 'package:js/js.dart';
// external top level members ok in @JS() library.
@@ -66,4 +67,133 @@
// [web] Only JS interop members may be 'external'.
}
+extension ExtensionNonJS on NonJSClass {
+ external get getter;
+ // ^
+ // [web] JS interop or Native class required for 'external' extension members.
+ external set setter(_);
+ // ^
+ // [web] JS interop or Native class required for 'external' extension members.
+
+ external static get staticGetter;
+ // ^
+ // [web] JS interop or Native class required for 'external' extension members.
+ external static set staticSetter(_);
+ // ^
+ // [web] JS interop or Native class required for 'external' extension members.
+
+ external method();
+ // ^
+ // [web] JS interop or Native class required for 'external' extension members.
+ external static staticMethod();
+ // ^
+ // [web] JS interop or Native class required for 'external' extension members.
+ external optionalParameterMethod([int a, int b = 0]);
+ // ^
+ // [web] JS interop or Native class required for 'external' extension members.
+ external overridenMethod();
+ // ^
+ // [web] JS interop or Native class required for 'external' extension members.
+
+ @JS('memberAnnotation')
+ external annotatedMethod();
+ // ^
+ // [web] JS interop or Native class required for 'external' extension members.
+
+ nonExternalMethod() => 1;
+ static nonExternalStaticMethod() => 2;
+}
+
+class NonJSClass {
+ void overridenMethod() => 5;
+}
+
+extension ExtensionGenericNonJS<T> on GenericNonJSClass<T> {
+ external T method();
+ // ^
+ // [web] JS interop or Native class required for 'external' extension members.
+}
+
+class GenericNonJSClass<T> {}
+
+extension ExtensionJS on JSClass {
+ external get getter;
+ external set setter(_);
+
+ external static get staticGetter;
+ external static set staticSetter(_);
+
+ external method();
+ external static staticMethod();
+ external optionalParameterMethod([int a, int b = 0]);
+
+ @JS('memberAnnotation')
+ external annotatedMethod();
+
+ nonExternalMethod() => 1;
+ static nonExternalStaticMethod() => 2;
+}
+
+@JS()
+class JSClass {}
+
+extension ExtensionGenericJS<T> on GenericJSClass<T> {
+ external T method();
+}
+
+@JS()
+class GenericJSClass<T> {}
+
+extension ExtensionAnonymousJS on AnonymousJSClass {
+ external get getter;
+ external set setter(_);
+ external method();
+}
+
+@JS()
+@anonymous
+class AnonymousJSClass {}
+
+extension ExtensionAbstractJS on AbstractJSClass {
+ external get getter;
+ external set setter(_);
+ external method();
+}
+
+@JS()
+abstract class AbstractJSClass {}
+
+extension ExtensionAnnotatedJS on AnnotatedJSClass {
+ external get getter;
+ external set setter(_);
+ external method();
+}
+
+@JS('Annotation')
+class AnnotatedJSClass {}
+
+extension ExtensionPrivateJS on _privateJSClass {
+ external get getter;
+ external set setter(_);
+ external method();
+}
+
+@JS()
+class _privateJSClass {}
+
+extension ExtensionNative on HtmlElement {
+ external get getter;
+ external set setter(_);
+
+ external static get staticGetter;
+ external static set staticSetter(_);
+
+ external method();
+ external static staticMethod();
+ external optionalParameterMethod([int a, int b = 0]);
+
+ nonExternalMethod() => 1;
+ static nonExternalStaticMethod() => 2;
+}
+
main() {}
diff --git a/tests/lib_2/js/is_check_and_as_cast_test.dart b/tests/lib_2/js/is_check_and_as_cast_test.dart
new file mode 100644
index 0000000..fe11da5
--- /dev/null
+++ b/tests/lib_2/js/is_check_and_as_cast_test.dart
@@ -0,0 +1,133 @@
+// 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.
+
+// Tests `is` checks and `as` casts between various JS objects. Currently, all
+// checks and casts should be allowed between JS objects.
+
+@JS()
+library is_check_and_as_cast_test;
+
+import 'package:js/js.dart';
+import 'package:expect/minitest.dart';
+
+@JS()
+external void eval(String code);
+
+@JS()
+class Foo {
+ external Foo(int a);
+ external int get a;
+}
+
+// Class with same structure as Foo but separate JS class.
+@JS()
+class Bar {
+ external Bar(int a);
+ external int get a;
+}
+
+@JS('Bar')
+class BarCopy {
+ external BarCopy(int a);
+ external int get a;
+}
+
+// JS object literals
+@JS()
+@anonymous
+class LiteralA {
+ external int get x;
+}
+
+@JS()
+@anonymous
+class LiteralB {
+ external int get y;
+}
+
+// Library is annotated with JS so we don't need the annotation here.
+external LiteralA get a;
+external LiteralB get b;
+
+class DartClass {}
+
+// Avoid static type optimization by running all tests using this.
+@pragma('dart2js:noInline')
+@pragma('dart2js:assumeDynamic')
+confuse(x) => x;
+
+void main() {
+ eval(r"""
+ function Foo(a) {
+ this.a = a;
+ }
+ function Bar(a) {
+ this.a = a;
+ }
+ var a = {
+ x: 1,
+ };
+ var b = {
+ y: 2,
+ };
+ """);
+
+ // JS class object can be checked and casted with itself.
+ var foo = Foo(42);
+ expect(foo is Foo, isTrue);
+ expect(confuse(foo) is Foo, isTrue);
+ expect(() => (foo as Foo), returnsNormally);
+
+ // Try it with dynamic.
+ dynamic d = Foo(42);
+ expect(d is Foo, isTrue);
+ expect(() => (d as Foo), returnsNormally);
+
+ // Casts are allowed between any JS class objects.
+ expect(foo is Bar, isTrue);
+ expect(confuse(foo) is Bar, isTrue);
+ expect(d is Bar, isTrue);
+ expect(() => (foo as Bar), returnsNormally);
+ expect(() => (d as Bar), returnsNormally);
+
+ // BarCopy is the same JS class as Bar.
+ var barCopy = BarCopy(42);
+ expect(barCopy is Bar, isTrue);
+ expect(confuse(barCopy) is Bar, isTrue);
+ expect(() => (barCopy as Bar), returnsNormally);
+
+ // JS object literal can be checked and casted with itself.
+ expect(a is LiteralA, isTrue);
+ expect(confuse(a) is LiteralA, isTrue);
+ expect(() => (a as LiteralA), returnsNormally);
+
+ // Like class objects, casts are allowed between any object literals.
+ expect(a is LiteralB, isTrue);
+ expect(confuse(a) is LiteralB, isTrue);
+ expect(() => (a as LiteralB), returnsNormally);
+
+ // Similarly, casts are allowed between any class objects and object literals.
+ expect(foo is LiteralB, isTrue);
+ expect(confuse(foo) is LiteralB, isTrue);
+ expect(() => (foo as LiteralB), returnsNormally);
+ expect(a is Foo, isTrue);
+ expect(confuse(a) is Foo, isTrue);
+ expect(() => (a as Foo), returnsNormally);
+
+ // You cannot cast between JS interop objects and Dart objects, however.
+ var dartClass = DartClass();
+ expect(dartClass is Foo, isFalse);
+ expect(confuse(dartClass) is Foo, isFalse);
+ expect(() => (dartClass as Foo), throws);
+ expect(dartClass is LiteralA, isFalse);
+ expect(confuse(dartClass) is LiteralA, isFalse);
+ expect(() => (dartClass as LiteralA), throws);
+
+ expect(foo is DartClass, isFalse);
+ expect(confuse(foo) is DartClass, isFalse);
+ expect(() => (foo as DartClass), throws);
+ expect(a is DartClass, isFalse);
+ expect(confuse(a) is DartClass, isFalse);
+ expect(() => (a as DartClass), throws);
+}
diff --git a/tests/lib_2/js/subtyping_test/subtyping_live_test.dart b/tests/lib_2/js/subtyping_test/subtyping_live_test.dart
new file mode 100644
index 0000000..d137ba6
--- /dev/null
+++ b/tests/lib_2/js/subtyping_test/subtyping_live_test.dart
@@ -0,0 +1,20 @@
+// 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.
+
+// Tests subtyping relationships after making package:js types live.
+
+@JS()
+library subtyping_live_test;
+
+import 'package:js/js.dart';
+import 'subtyping_test_util.dart';
+
+@JS()
+external dynamic get externalGetter;
+
+void main() {
+ // Call to foreign function should trigger dart2js to assume types are live.
+ externalGetter;
+ testSubtyping();
+}
diff --git a/tests/lib_2/js/subtyping_test/subtyping_not_live_test.dart b/tests/lib_2/js/subtyping_test/subtyping_not_live_test.dart
new file mode 100644
index 0000000..5344280
--- /dev/null
+++ b/tests/lib_2/js/subtyping_test/subtyping_not_live_test.dart
@@ -0,0 +1,12 @@
+// 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.
+
+// Tests subtyping relationships without making package:js types live.
+
+import 'package:js/js.dart';
+import 'subtyping_test_util.dart';
+
+void main() {
+ testSubtyping();
+}
diff --git a/tests/lib_2/js/subtyping_test/subtyping_test_util.dart b/tests/lib_2/js/subtyping_test/subtyping_test_util.dart
new file mode 100644
index 0000000..a39efb9
--- /dev/null
+++ b/tests/lib_2/js/subtyping_test/subtyping_test_util.dart
@@ -0,0 +1,74 @@
+// 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.
+
+// Tests subtyping relationships between JS and anonymous classes.
+
+@JS()
+library subtyping_test_util;
+
+import 'package:js/js.dart';
+import 'package:expect/minitest.dart';
+
+@JS()
+class JSClassA {}
+
+@JS()
+class JSClassB {}
+
+@JS()
+@anonymous
+class AnonymousClassA {}
+
+@JS()
+@anonymous
+class AnonymousClassB {}
+
+class DartClass {}
+
+JSClassA returnJS() => throw '';
+
+AnonymousClassA returnAnon() => throw '';
+
+DartClass returnDartClass() => throw '';
+
+// Avoid static type optimization by running all tests using this.
+@pragma('dart2js:noInline')
+@pragma('dart2js:assumeDynamic')
+confuse(x) => x;
+
+void testSubtyping() {
+ // Checks subtyping with the same type.
+ expect(returnJS is JSClassA Function(), true);
+ expect(returnAnon is AnonymousClassA Function(), true);
+
+ // Subtyping between JS and anonymous classes.
+ expect(returnJS is AnonymousClassA Function(), true);
+ expect(returnAnon is JSClassA Function(), true);
+
+ // Subtyping between same type of package:js classes.
+ expect(returnJS is JSClassB Function(), true);
+ expect(returnAnon is AnonymousClassB Function(), true);
+
+ // No subtyping between JS/anonymous classes and Dart classes.
+ expect(returnJS is DartClass Function(), false);
+ expect(returnDartClass is JSClassA Function(), false);
+ expect(returnAnon is DartClass Function(), false);
+ expect(returnDartClass is AnonymousClassA Function(), false);
+
+ // Repeat the checks but using `confuse` to coerce runtime checks instead of
+ // compile-time like above.
+ expect(confuse(returnJS) is JSClassA Function(), true);
+ expect(confuse(returnAnon) is AnonymousClassA Function(), true);
+
+ expect(confuse(returnJS) is AnonymousClassA Function(), true);
+ expect(confuse(returnAnon) is JSClassA Function(), true);
+
+ expect(confuse(returnJS) is JSClassB Function(), true);
+ expect(confuse(returnAnon) is AnonymousClassB Function(), true);
+
+ expect(confuse(returnJS) is DartClass Function(), false);
+ expect(confuse(returnDartClass) is JSClassA Function(), false);
+ expect(confuse(returnAnon) is DartClass Function(), false);
+ expect(confuse(returnDartClass) is AnonymousClassA Function(), false);
+}
diff --git a/tests/lib_2/lib_2.status b/tests/lib_2/lib_2.status
index 7fbd5a0..fb8a8bf 100644
--- a/tests/lib_2/lib_2.status
+++ b/tests/lib_2/lib_2.status
@@ -36,8 +36,12 @@
[ $csp ]
html/js_interop_constructor_name/*: SkipByDesign # Issue 42085.
isolate/deferred_in_isolate2_test: Skip # Issue 16898. Deferred loading does not work from an isolate in CSP-mode
+js/extends_test/extends_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
+js/extends_test/extends_with_es6_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
js/instanceof_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
+js/is_check_and_as_cast_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
js/js_util/async_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
+js/js_util/javascriptobject_extensions_test.dart: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
js/js_util/jsify_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
js/js_util/promise_reject_null_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
js/js_util/properties_implicit_checks_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
@@ -72,9 +76,6 @@
async/slow_consumer2_test: SkipSlow # Times out. Issue 22050
async/stream_timeout_test: SkipSlow # Times out. Issue 22050
-[ $runtime == dart_precompiled || $runtime == vm ]
-isolate/isolate_stress_test: Skip # Issue 12588: Uses dart:html. This should be able to pass when we have wrapper-less tests.
-
# It makes no sense to run any test that uses spawnURI under the simulator
# as that would involve running CFE (the front end) in simulator mode
# to compile the URI file specified in spawnURI code.
diff --git a/tests/lib_2/lib_2_vm.status b/tests/lib_2/lib_2_vm.status
index 0cdb365..c2e26f4 100644
--- a/tests/lib_2/lib_2_vm.status
+++ b/tests/lib_2/lib_2_vm.status
@@ -2,9 +2,6 @@
# 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.
-[ $runtime == vm ]
-isolate/*: Pass, Slow # https://dartbug.com/36097: Slower while isolate groups are being gradually enabled in JIT mode.
-
[ $runtime != vm ]
isolate/native_wrapper_message_test: Skip # A VM specific test.
@@ -69,96 +66,10 @@
mirrors/library_uri_io_test: RuntimeError
mirrors/library_uri_package_test: RuntimeError
-[ $arch == simarm || $arch == simarm64 || $arch ==simarm64c || $hot_reload || $hot_reload_rollback ]
+[ $arch == simarm || $arch == simarm64 || $arch == simarm64c || $hot_reload || $hot_reload_rollback ]
convert/chunked_conversion_utf88_test: SkipSlow
convert/streamed_conversion_json_utf8_decode_test: SkipSlow
convert/utf85_test: SkipSlow
[ $hot_reload || $hot_reload_rollback ]
-isolate/bool_from_environment_default_value_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/capability_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/compile_time_error_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/count_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/cross_isolate_message_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/enum_const_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/error_at_spawn_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/error_at_spawnuri_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/error_exit_at_spawn_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/error_exit_at_spawnuri_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/exit_at_spawn_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/exit_at_spawnuri_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/function_send1_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/function_send_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/handle_error2_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/handle_error3_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/handle_error_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/illegal_msg_function_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/illegal_msg_mirror_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/int32_length_overflow_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/int_from_environment_default_value_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/isolate_complex_messages_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/isolate_current_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/isolate_import_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/issue_21398_parent_isolate1_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/issue_21398_parent_isolate2_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/issue_21398_parent_isolate_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/issue_22778_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/issue_35626_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/issue_6610_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/kill2_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/kill_self_synchronously_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/kill_self_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/kill_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/large_byte_data_leak_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/large_byte_data_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/mandel_isolate_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/message2_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/message3_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/message4_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/message_const_type_arguments_1_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/message_const_type_arguments_2_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/message_enum_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/message_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/mint_maker_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/native_wrapper_message_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/nested_spawn2_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/nested_spawn_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/non_fatal_exception_in_timer_callback_test/none: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/non_fatal_exception_in_timer_callback_test/sleep: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/object_leak_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/ondone_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/package_config_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/package_resolve_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/package_root_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/pause_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/ping_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/port_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/raw_port_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/regress_34752_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/regress_flutter_22796_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/request_reply_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/resolve_package_uri_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/scenarios/package_data_uri_spec/package_resolve_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/send_private_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/simple_message_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/spawn_function_custom_class_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/spawn_function_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/spawn_generic_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/spawn_uri__package_uri__test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/spawn_uri_exported_main_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/spawn_uri_fail_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/spawn_uri_missing_from_isolate_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/spawn_uri_missing_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/spawn_uri_multi_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/spawn_uri_nested_vm_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/spawn_uri_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/spawn_uri_vm_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/start_paused_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/string_from_environment_default_value_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/timer_isolate_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/timer_multiple_isolates_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/transferable_failed_to_send_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/transferable_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/typed_message_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/unresolved_ports_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-isolate/vm_rehash_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
+isolate/int32_length_overflow_test: SkipSlow # Iterates over Uint8List(1 << 30).
diff --git a/tests/standalone/io/directory_list_sync_test.dart b/tests/standalone/io/directory_list_sync_test.dart
index 0df5081..6e3b257 100644
--- a/tests/standalone/io/directory_list_sync_test.dart
+++ b/tests/standalone/io/directory_list_sync_test.dart
@@ -4,10 +4,11 @@
import 'dart:io';
+import 'package:path/path.dart' as path;
+
void testList() {
- File script = new File.fromUri(Platform.script);
- // tests/standalone/io/../..
- Directory startingDir = script.parent.parent.parent;
+ final startingDir =
+ Directory(path.normalize(path.join(Platform.executable, '../../../')));
print("Recursively listing entries in directory ${startingDir.path} ...");
List<FileSystemEntity> each =
startingDir.listSync(recursive: true, followLinks: false);
diff --git a/tests/standalone/io/echo_server_stream_test.dart b/tests/standalone/io/echo_server_stream_test.dart
index 18dc94a..6da8ca2 100644
--- a/tests/standalone/io/echo_server_stream_test.dart
+++ b/tests/standalone/io/echo_server_stream_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
//
// Echo server test program to test socket streams.
diff --git a/tests/standalone/io/file_fuzz_test.dart b/tests/standalone/io/file_fuzz_test.dart
index f7f89c8..bfcb7c9 100644
--- a/tests/standalone/io/file_fuzz_test.dart
+++ b/tests/standalone/io/file_fuzz_test.dart
@@ -10,113 +10,122 @@
import 'dart:io';
import 'fuzz_support.dart';
+import 'file_write_only_test.dart' show withTempDir, withTempDirSync;
import "package:async_helper/async_helper.dart";
fuzzSyncMethods() {
- typeMapping.forEach((k, v) {
- File? file;
- doItSync(() => file = new File(v as String));
- if (file == null) return;
- final f = file!;
- doItSync(f.existsSync);
- doItSync(f.createSync);
- doItSync(f.deleteSync);
- doItSync(f.lengthSync);
- doItSync(f.lastModifiedSync);
- doItSync(() => f.path);
- doItSync(() => f.openRead().listen((_) {}, onError: (e) {}));
- doItSync(f.readAsBytesSync);
- doItSync(f.readAsStringSync);
- doItSync(f.readAsLinesSync);
- typeMapping.forEach((k2, v2) {
- doItSync(() => f.openSync(mode: v2 as FileMode));
- doItSync(() => f.openWrite(mode: v2 as FileMode));
- doItSync(() => f.readAsStringSync(encoding: v2 as Encoding));
- doItSync(() => f.readAsLinesSync(encoding: v2 as Encoding));
+ withTempDirSync('dart_file_fuzz', (temp) {
+ typeMapping.forEach((k, v) {
+ File? file;
+ doItSync(() => file = new File('${temp.path}/${v as String}'));
+ if (file == null) return;
+ final f = file!;
+ doItSync(f.existsSync);
+ doItSync(f.createSync);
+ doItSync(f.deleteSync);
+ doItSync(f.lengthSync);
+ doItSync(f.lastModifiedSync);
+ doItSync(() => f.path);
+ doItSync(() => f.openRead().listen((_) {}, onError: (e) {}));
+ doItSync(f.readAsBytesSync);
+ doItSync(f.readAsStringSync);
+ doItSync(f.readAsLinesSync);
+ typeMapping.forEach((k2, v2) {
+ doItSync(() => f.openSync(mode: v2 as FileMode));
+ doItSync(() => f.openWrite(mode: v2 as FileMode));
+ doItSync(() => f.readAsStringSync(encoding: v2 as Encoding));
+ doItSync(() => f.readAsLinesSync(encoding: v2 as Encoding));
+ });
});
});
}
-fuzzAsyncMethods() {
+fuzzAsyncMethods() async {
asyncStart();
- var futures = <Future>[];
- typeMapping.forEach((k, v) {
- File? file;
- doItSync(() => file = new File(v as String));
- if (file == null) return;
- final f = file!;
- futures.add(doItAsync(f.exists));
- futures.add(doItAsync(f.delete));
- futures.add(doItAsync(() => f.parent));
- futures.add(doItAsync(f.length));
- futures.add(doItAsync(f.lastModified));
- futures.add(doItAsync(f.open));
- futures.add(doItAsync(() => f.path));
- futures.add(doItAsync(f.readAsBytes));
- futures.add(doItAsync(f.readAsLines));
- futures.add(doItAsync(f.readAsString));
- typeMapping.forEach((k2, v2) {
- futures.add(doItAsync(() => f.open(mode: v2 as FileMode)));
- futures.add(doItAsync(() => f.readAsString(encoding: v2 as Encoding)));
- futures.add(doItAsync(() => f.readAsLines(encoding: v2 as Encoding)));
+ withTempDir('dart_file_fuzz', (temp) async {
+ final futures = <Future>[];
+ typeMapping.forEach((k, v) {
+ File? file;
+ doItSync(() => file = new File('${temp.path}/${v as String}'));
+ if (file == null) return;
+ final f = file!;
+ futures.add(doItAsync(f.exists));
+ futures.add(doItAsync(f.delete));
+ futures.add(doItAsync(() => f.parent));
+ futures.add(doItAsync(f.length));
+ futures.add(doItAsync(f.lastModified));
+ futures.add(doItAsync(f.open));
+ futures.add(doItAsync(() => f.path));
+ futures.add(doItAsync(f.readAsBytes));
+ futures.add(doItAsync(f.readAsLines));
+ futures.add(doItAsync(f.readAsString));
+ typeMapping.forEach((k2, v2) {
+ futures.add(doItAsync(() => f.open(mode: v2 as FileMode)));
+ futures.add(doItAsync(() => f.readAsString(encoding: v2 as Encoding)));
+ futures.add(doItAsync(() => f.readAsLines(encoding: v2 as Encoding)));
+ });
+ });
+ await Future.wait(futures).then((_) {
+ asyncEnd();
});
});
- Future.wait(futures).then((_) => asyncEnd());
}
fuzzSyncRandomAccessMethods() {
- var temp = Directory.systemTemp.createTempSync('dart_file_fuzz');
- var file = new File('${temp.path}/x');
- file.createSync();
- var modes = [FileMode.read, FileMode.write, FileMode.append];
- for (var m in modes) {
- var opened = file.openSync(mode: m);
- typeMapping.forEach((k, v) {
- doItSync(() => opened.setPositionSync(v as int));
- doItSync(() => opened.truncateSync(v as int));
- doItSync(() => opened.writeByteSync(v as int));
- });
- for (var p in typePermutations(2)) {
- doItSync(() => opened.writeStringSync(p[0], encoding: p[1]));
- }
- for (var p in typePermutations(3)) {
- doItSync(() => opened.readIntoSync(p[0], p[1], p[2]));
- doItSync(() => opened.writeFromSync(p[0], p[1], p[2]));
- }
- opened.closeSync();
- }
- temp.deleteSync(recursive: true);
-}
-
-fuzzAsyncRandomAccessMethods() {
- var temp = Directory.systemTemp.createTempSync('dart_file_fuzz');
- var file = new File('${temp.path}/x');
- file.createSync();
- var modes = [FileMode.read, FileMode.write, FileMode.append];
- var futures = <Future>[];
- var openedFiles = [];
- for (var m in modes) {
- var opened = file.openSync(mode: m);
- openedFiles.add(opened);
- typeMapping.forEach((k, v) {
- futures.add(doItAsync(() => opened.setPosition(v as int)));
- futures.add(doItAsync(() => opened.truncate(v as int)));
- futures.add(doItAsync(() => opened.writeByte(v as int)));
- });
- for (var p in typePermutations(2)) {
- futures.add(doItAsync(() => opened.writeString(p[0], encoding: p[1])));
- }
- for (var p in typePermutations(3)) {
- futures.add(doItAsync(() => opened.readInto(p[0], p[1], p[2])));
- futures.add(doItAsync(() => opened.writeFrom(p[0], p[1], p[2])));
- }
- }
- Future.wait(futures).then((ignore) {
- for (var opened in openedFiles) {
+ withTempDirSync('dart_file_fuzz', (temp) {
+ var file = new File('${temp.path}/x');
+ file.createSync();
+ var modes = [FileMode.read, FileMode.write, FileMode.append];
+ for (var m in modes) {
+ var opened = file.openSync(mode: m);
+ typeMapping.forEach((k, v) {
+ doItSync(() => opened.setPositionSync(v as int));
+ doItSync(() => opened.truncateSync(v as int));
+ doItSync(() => opened.writeByteSync(v as int));
+ });
+ for (var p in typePermutations(2)) {
+ doItSync(() => opened.writeStringSync(p[0], encoding: p[1]));
+ }
+ for (var p in typePermutations(3)) {
+ doItSync(() => opened.readIntoSync(p[0], p[1], p[2]));
+ doItSync(() => opened.writeFromSync(p[0], p[1], p[2]));
+ }
opened.closeSync();
}
- temp.deleteSync(recursive: true);
+ });
+}
+
+fuzzAsyncRandomAccessMethods() async {
+ asyncStart();
+ await withTempDir('dart_file_fuzz', (temp) async {
+ var file = new File('${temp.path}/x');
+ file.createSync();
+ var modes = [FileMode.read, FileMode.write, FileMode.append];
+ var futures = <Future>[];
+ var openedFiles = [];
+ for (var m in modes) {
+ var opened = file.openSync(mode: m);
+ openedFiles.add(opened);
+ typeMapping.forEach((k, v) {
+ futures.add(doItAsync(() => opened.setPosition(v as int)));
+ futures.add(doItAsync(() => opened.truncate(v as int)));
+ futures.add(doItAsync(() => opened.writeByte(v as int)));
+ });
+ for (var p in typePermutations(2)) {
+ futures.add(doItAsync(() => opened.writeString(p[0], encoding: p[1])));
+ }
+ for (var p in typePermutations(3)) {
+ futures.add(doItAsync(() => opened.readInto(p[0], p[1], p[2])));
+ futures.add(doItAsync(() => opened.writeFrom(p[0], p[1], p[2])));
+ }
+ }
+ await Future.wait(futures).then((ignore) {
+ for (var opened in openedFiles) {
+ opened.closeSync();
+ }
+ asyncEnd();
+ });
});
}
diff --git a/tests/standalone/io/file_system_watcher_large_set_test.dart b/tests/standalone/io/file_system_watcher_large_set_test.dart
index 0f010cf..2a4ed9d 100644
--- a/tests/standalone/io/file_system_watcher_large_set_test.dart
+++ b/tests/standalone/io/file_system_watcher_large_set_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--delayed-filewatch-callback --enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--delayed-filewatch-callback --enable-isolate-groups
// VMOptions=--delayed-filewatch-callback --no-enable-isolate-groups
// Verifies that cancelling subscription from inside of the event handler
diff --git a/tests/standalone/io/file_system_watcher_test.dart b/tests/standalone/io/file_system_watcher_test.dart
index e10bf9d..dae7f9d 100644
--- a/tests/standalone/io/file_system_watcher_test.dart
+++ b/tests/standalone/io/file_system_watcher_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import "dart:async";
diff --git a/tests/standalone/io/http_advanced_test.dart b/tests/standalone/io/http_advanced_test.dart
index 0ee5d65..87553d9 100644
--- a/tests/standalone/io/http_advanced_test.dart
+++ b/tests/standalone/io/http_advanced_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
//
// VMOptions=
diff --git a/tests/standalone/io/http_basic_test.dart b/tests/standalone/io/http_basic_test.dart
index 54e1a35..acc6eb5 100644
--- a/tests/standalone/io/http_basic_test.dart
+++ b/tests/standalone/io/http_basic_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
//
// VMOptions=--trace_shutdown
diff --git a/tests/standalone/io/http_read_test.dart b/tests/standalone/io/http_read_test.dart
index af75740..b6f4a7e 100644
--- a/tests/standalone/io/http_read_test.dart
+++ b/tests/standalone/io/http_read_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
//
// VMOptions=
diff --git a/tests/standalone/io/issue_30687_test.dart b/tests/standalone/io/issue_30687_test.dart
index 96b514d..e994f09 100644
--- a/tests/standalone/io/issue_30687_test.dart
+++ b/tests/standalone/io/issue_30687_test.dart
@@ -5,40 +5,41 @@
import 'dart:io';
import 'package:expect/expect.dart';
+import 'package:path/path.dart' as path;
+
+import 'unix_socket_test.dart' show withTempDir;
main() async {
- Link link1 = new Link(
- Directory.systemTemp.path + Platform.pathSeparator + 'link1.lnk');
- Link link2 = new Link(
- Directory.systemTemp.path + Platform.pathSeparator + 'link2.lnk');
+ await withTempDir('issue_30687', (Directory tempDir) async {
+ final link1 = Link(tempDir.path + Platform.pathSeparator + 'link1.lnk');
+ final link2 = Link(tempDir.path + Platform.pathSeparator + 'link2.lnk');
- Directory target1 = new Directory(
- Directory.systemTemp.path + Platform.pathSeparator + 'target1');
- Directory target2 = new Directory(
- Directory.systemTemp.path + Platform.pathSeparator + 'target2');
+ final target1 = Directory(path.join(tempDir.path, 'target1'));
+ final target2 = Directory(path.join(tempDir.path, 'target2'));
- target1.createSync();
- target2.createSync();
+ target1.createSync();
+ target2.createSync();
- Expect.isTrue(target1.existsSync());
- Expect.isTrue(target2.existsSync());
+ Expect.isTrue(target1.existsSync());
+ Expect.isTrue(target2.existsSync());
- link1.createSync(target1.path);
- link2.createSync(target2.path);
- Expect.isTrue(link1.existsSync());
- Expect.isTrue(link2.existsSync());
+ link1.createSync(target1.path);
+ link2.createSync(target2.path);
+ Expect.isTrue(link1.existsSync());
+ Expect.isTrue(link2.existsSync());
- try {
- Link renamed = await link1.rename(link2.path);
- Expect.isFalse(link1.existsSync());
- Expect.isTrue(renamed.existsSync());
- Expect.equals(renamed.path, link2.path);
- } finally {
- target1.delete();
- target2.delete();
- link2.delete();
- if (link1.existsSync()) {
- link1.delete();
+ try {
+ Link renamed = await link1.rename(link2.path);
+ Expect.isFalse(link1.existsSync());
+ Expect.isTrue(renamed.existsSync());
+ Expect.equals(renamed.path, link2.path);
+ } finally {
+ target1.deleteSync();
+ target2.deleteSync();
+ link2.deleteSync();
+ if (link1.existsSync()) {
+ link1.deleteSync();
+ }
}
- }
+ });
}
diff --git a/tests/standalone/io/pipe_server_test.dart b/tests/standalone/io/pipe_server_test.dart
index ab6b8e1..52d93b6 100644
--- a/tests/standalone/io/pipe_server_test.dart
+++ b/tests/standalone/io/pipe_server_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
//
// OtherResources=readline_test1.dat
diff --git a/tests/standalone/io/platform_test.dart b/tests/standalone/io/platform_test.dart
index adea57e..ace9d85 100644
--- a/tests/standalone/io/platform_test.dart
+++ b/tests/standalone/io/platform_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import "dart:async";
diff --git a/tests/standalone/io/raw_datagram_read_all_test.dart b/tests/standalone/io/raw_datagram_read_all_test.dart
index 73d11c4..225da8e 100644
--- a/tests/standalone/io/raw_datagram_read_all_test.dart
+++ b/tests/standalone/io/raw_datagram_read_all_test.dart
@@ -29,7 +29,7 @@
var datagram = receiver.receive()!;
Expect.listEquals([0], datagram.data);
if (timer != null) timer.cancel();
- timer = new Timer(const Duration(milliseconds: 200), () {
+ timer = new Timer(const Duration(seconds: 1), () {
Expect.isNull(receiver.receive());
receiver.close();
asyncEnd();
diff --git a/tests/standalone/io/raw_synchronous_socket_test.dart b/tests/standalone/io/raw_synchronous_socket_test.dart
index 180c6bd..50cb0f2 100644
--- a/tests/standalone/io/raw_synchronous_socket_test.dart
+++ b/tests/standalone/io/raw_synchronous_socket_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import "dart:async";
diff --git a/tests/standalone/io/shared_socket_test.dart b/tests/standalone/io/shared_socket_test.dart
index 15dac09..3195b63 100644
--- a/tests/standalone/io/shared_socket_test.dart
+++ b/tests/standalone/io/shared_socket_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import 'dart:async';
diff --git a/tests/standalone/io/socket_close_test.dart b/tests/standalone/io/socket_close_test.dart
index 41fa8ac..72a15de 100644
--- a/tests/standalone/io/socket_close_test.dart
+++ b/tests/standalone/io/socket_close_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
//
// VMOptions=
diff --git a/tests/standalone/io/socket_finalizer_test.dart b/tests/standalone/io/socket_finalizer_test.dart
index 94c9bcc..c82be22 100644
--- a/tests/standalone/io/socket_finalizer_test.dart
+++ b/tests/standalone/io/socket_finalizer_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
//
// This test checks that sockets belonging to an isolate are properly cleaned up
diff --git a/tests/standalone/io/socket_many_connections_test.dart b/tests/standalone/io/socket_many_connections_test.dart
index 6b73038..0140df7 100644
--- a/tests/standalone/io/socket_many_connections_test.dart
+++ b/tests/standalone/io/socket_many_connections_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
//
// Test creating a large number of socket connections.
diff --git a/tests/standalone/io/stdio_socket_finalizer_test.dart b/tests/standalone/io/stdio_socket_finalizer_test.dart
index 46b4231..c33da51 100644
--- a/tests/standalone/io/stdio_socket_finalizer_test.dart
+++ b/tests/standalone/io/stdio_socket_finalizer_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
//
// This test checks that stdin is *not* closed when an Isolate leaks it.
diff --git a/tests/standalone/io/unix_socket_regress_46634_test.dart b/tests/standalone/io/unix_socket_regress_46634_test.dart
new file mode 100644
index 0000000..31bce79
--- /dev/null
+++ b/tests/standalone/io/unix_socket_regress_46634_test.dart
@@ -0,0 +1,20 @@
+// 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.
+
+import 'dart:io';
+
+import 'unix_socket_test.dart' show withTempDir, testListenCloseListenClose;
+
+void main() async {
+ if (!Platform.isMacOS && !Platform.isLinux && !Platform.isAndroid) {
+ return;
+ }
+ final futures = <Future>[];
+ for (int i = 0; i < 10; ++i) {
+ futures.add(withTempDir('unix_socket_test', (Directory dir) async {
+ await testListenCloseListenClose('${dir.path}');
+ }));
+ }
+ await Future.wait(futures);
+}
diff --git a/tests/standalone/io/unix_socket_test.dart b/tests/standalone/io/unix_socket_test.dart
index 0553e6a..d510fb6 100644
--- a/tests/standalone/io/unix_socket_test.dart
+++ b/tests/standalone/io/unix_socket_test.dart
@@ -3,8 +3,8 @@
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
-import 'dart:io';
import 'dart:convert';
+import 'dart:io';
import 'package:expect/expect.dart';
@@ -12,8 +12,6 @@
var address = InternetAddress('$name/sock', type: InternetAddressType.unix);
var server = await ServerSocket.bind(address, 0);
- var type = FileSystemEntity.typeSync(address.address);
-
var client = await Socket.connect(address, server.port);
var completer = Completer<void>();
server.listen((socket) async {
@@ -58,22 +56,23 @@
}
testBind(String name) async {
- var address = InternetAddress('$name/sock', type: InternetAddressType.unix);
- var server = await ServerSocket.bind(address, 0, shared: false);
+ final address = InternetAddress('$name/sock', type: InternetAddressType.unix);
+ final server = await ServerSocket.bind(address, 0, shared: false);
Expect.isTrue(server.address.toString().contains(name));
// Unix domain socket does not have a valid port number.
Expect.equals(server.port, 0);
- var type = FileSystemEntity.typeSync(address.address);
-
- var sub;
- sub = server.listen((s) {
- sub.cancel();
- server.close();
+ final serverContinue = Completer();
+ final clientContinue = Completer();
+ server.listen((s) async {
+ await serverContinue.future;
+ clientContinue.complete();
});
- var socket = await Socket.connect(address, server.port);
+ final socket = await Socket.connect(address, server.port);
socket.write(" socket content");
+ serverContinue.complete();
+ await clientContinue.future;
socket.destroy();
await server.close();
@@ -89,8 +88,6 @@
// test if it is working correctly.
await socket.close();
- var type = FileSystemEntity.typeSync(address.address);
-
// For robustness we ignore any clients unrelated to this test.
List<int> sendData = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
socket2.listen((Socket client) async {
@@ -127,8 +124,6 @@
completer.complete();
});
- var type = FileSystemEntity.typeSync(address.address);
-
Socket client =
await Socket.connect(address, server.port, sourceAddress: localAddress);
Expect.equals(client.remoteAddress.address, address.address);
@@ -138,12 +133,12 @@
await server.close();
}
-Future testAbstractAddress() async {
+Future testAbstractAddress(String uniqueName) async {
if (!Platform.isLinux && !Platform.isAndroid) {
return;
}
var serverAddress =
- InternetAddress('@temp.sock', type: InternetAddressType.unix);
+ InternetAddress('@temp.sock.$uniqueName', type: InternetAddressType.unix);
ServerSocket server = await ServerSocket.bind(serverAddress, 0);
final completer = Completer<void>();
final content = 'random string';
@@ -171,7 +166,7 @@
return buffer.toString();
}
-Future testShortAbstractAddress() async {
+Future testShortAbstractAddress(String uniqueName) async {
if (!Platform.isLinux && !Platform.isAndroid) {
return;
}
@@ -181,7 +176,7 @@
Future? stdoutFuture;
Future? stderrFuture;
try {
- var socketAddress = '@hidden';
+ var socketAddress = '@temp.sock.$uniqueName';
var abstractSocketServer = getAbstractSocketTestFileName();
// check if the executable exists, some build configurations do not
// build it (e.g: precompiled simarm/simarm64)
@@ -189,7 +184,7 @@
return;
}
- // Start up a subprocess that listens on '@hidden'.
+ // Start up a subprocess that listens on [socketAddress].
process = await Process.start(abstractSocketServer, [socketAddress]);
stdoutFuture = process.stdout
.transform(const Utf8Decoder(allowMalformed: true))
@@ -453,10 +448,10 @@
void main() async {
try {
await withTempDir('unix_socket_test', (Directory dir) async {
- await testBind('${dir.path}');
+ await testAddress('${dir.path}');
});
await withTempDir('unix_socket_test', (Directory dir) async {
- await testAddress('${dir.path}');
+ await testBind('${dir.path}');
});
await withTempDir('unix_socket_test', (Directory dir) async {
await testBindShared('${dir.path}');
@@ -467,7 +462,9 @@
await withTempDir('unix_socket_test', (Directory dir) async {
await testSourceAddressConnect('${dir.path}');
});
- await testAbstractAddress();
+ await withTempDir('unix_socket_test', (Directory dir) async {
+ await testAbstractAddress(dir.uri.pathSegments.last);
+ });
await withTempDir('unix_socket_test', (Directory dir) async {
await testExistingFile('${dir.path}');
});
@@ -477,7 +474,9 @@
await withTempDir('unix_socket_test', (Directory dir) async {
await testHttpServer('${dir.path}');
});
- await testShortAbstractAddress();
+ await withTempDir('unix_socket_test', (Directory dir) async {
+ await testShortAbstractAddress(dir.uri.pathSegments.last);
+ });
} catch (e) {
if (Platform.isMacOS || Platform.isLinux || Platform.isAndroid) {
Expect.fail("Unexpected exception $e is thrown");
diff --git a/tests/standalone/io/wait_for_event_isolate_test.dart b/tests/standalone/io/wait_for_event_isolate_test.dart
index 15b970f..ce624e2 100644
--- a/tests/standalone/io/wait_for_event_isolate_test.dart
+++ b/tests/standalone/io/wait_for_event_isolate_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import 'dart:async';
diff --git a/tests/standalone/packages_file_test.dart b/tests/standalone/packages_file_test.dart
index d39c6dc..99c2ab5 100644
--- a/tests/standalone/packages_file_test.dart
+++ b/tests/standalone/packages_file_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import "dart:async";
diff --git a/tests/standalone/regress_26031_test.dart b/tests/standalone/regress_26031_test.dart
index 25e9490..60dd89b 100644
--- a/tests/standalone/regress_26031_test.dart
+++ b/tests/standalone/regress_26031_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import 'dart:io';
diff --git a/tests/standalone/regress_28854_1_test.dart b/tests/standalone/regress_28854_1_test.dart
index 2517e30..30b304a 100644
--- a/tests/standalone/regress_28854_1_test.dart
+++ b/tests/standalone/regress_28854_1_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
library regress;
diff --git a/tests/standalone/regress_28854_2_test.dart b/tests/standalone/regress_28854_2_test.dart
index e528d34..21395c1 100644
--- a/tests/standalone/regress_28854_2_test.dart
+++ b/tests/standalone/regress_28854_2_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
library regress;
diff --git a/tests/standalone/standalone_vm.status b/tests/standalone/standalone_vm.status
index 6a36f12..86c5c3c 100644
--- a/tests/standalone/standalone_vm.status
+++ b/tests/standalone/standalone_vm.status
@@ -7,9 +7,6 @@
link_natives_lazily_test: SkipByDesign # Not supported.
no_allow_absolute_addresses_test: SkipByDesign # Not supported.
-[ $runtime == vm ]
-typed_data_isolate_test: Pass, Slow # https://dartbug.com/36097: Slower while isolate groups are being gradually enabled in JIT mode.
-
[ $system == android ]
io/file_stat_test: Skip # Issue 26376
io/file_system_watcher_test: Skip # Issue 26376
diff --git a/tests/standalone/typed_array_int64_uint64_test.dart b/tests/standalone/typed_array_int64_uint64_test.dart
index fb6bd2d..7b57986 100644
--- a/tests/standalone/typed_array_int64_uint64_test.dart
+++ b/tests/standalone/typed_array_int64_uint64_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
//
// Dart test program for testing native typed arrays, int64 and uint64 only.
diff --git a/tests/standalone/typed_array_test.dart b/tests/standalone/typed_array_test.dart
index d443da9..6e4c6c3 100644
--- a/tests/standalone/typed_array_test.dart
+++ b/tests/standalone/typed_array_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
//
// Dart test program for testing native float and int arrays. 64-bit int arrays
diff --git a/tests/standalone/typed_data_isolate_test.dart b/tests/standalone/typed_data_isolate_test.dart
index 80efe40..2573ada 100644
--- a/tests/standalone/typed_data_isolate_test.dart
+++ b/tests/standalone/typed_data_isolate_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
//
// Dart test program for testing typed data.
diff --git a/tests/standalone_2/io/directory_list_sync_test.dart b/tests/standalone_2/io/directory_list_sync_test.dart
index ec63715..b148ffd 100644
--- a/tests/standalone_2/io/directory_list_sync_test.dart
+++ b/tests/standalone_2/io/directory_list_sync_test.dart
@@ -6,10 +6,11 @@
import 'dart:io';
+import 'package:path/path.dart' as path;
+
void testList() {
- File script = new File.fromUri(Platform.script);
- // tests/standalone/io/../..
- Directory startingDir = script.parent.parent.parent;
+ final startingDir =
+ Directory(path.normalize(path.join(Platform.executable, '../../../')));
print("Recursively listing entries in directory ${startingDir.path} ...");
List<FileSystemEntity> each =
startingDir.listSync(recursive: true, followLinks: false);
diff --git a/tests/standalone_2/io/echo_server_stream_test.dart b/tests/standalone_2/io/echo_server_stream_test.dart
index 6b0b6c7..e0449a3 100644
--- a/tests/standalone_2/io/echo_server_stream_test.dart
+++ b/tests/standalone_2/io/echo_server_stream_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
//
// Echo server test program to test socket streams.
diff --git a/tests/standalone_2/io/file_fuzz_test.dart b/tests/standalone_2/io/file_fuzz_test.dart
index 60a7e5b..32ce6aa 100644
--- a/tests/standalone_2/io/file_fuzz_test.dart
+++ b/tests/standalone_2/io/file_fuzz_test.dart
@@ -11,111 +11,120 @@
import 'dart:io';
import 'fuzz_support.dart';
+import 'file_write_only_test.dart' show withTempDir, withTempDirSync;
import "package:async_helper/async_helper.dart";
fuzzSyncMethods() {
- typeMapping.forEach((k, v) {
- File f;
- doItSync(() => f = new File(v));
- if (f == null) return;
- doItSync(f.existsSync);
- doItSync(f.createSync);
- doItSync(f.deleteSync);
- doItSync(f.lengthSync);
- doItSync(f.lastModifiedSync);
- doItSync(() => f.path);
- doItSync(() => f.openRead().listen((_) {}, onError: (e) {}));
- doItSync(f.readAsBytesSync);
- doItSync(f.readAsStringSync);
- doItSync(f.readAsLinesSync);
- typeMapping.forEach((k2, v2) {
- doItSync(() => f.openSync(mode: v2));
- doItSync(() => f.openWrite(mode: v2));
- doItSync(() => f.readAsStringSync(encoding: v2));
- doItSync(() => f.readAsLinesSync(encoding: v2));
+ withTempDirSync('dart_file_fuzz', (temp) {
+ typeMapping.forEach((k, v) {
+ File f;
+ doItSync(() => f = new File('${temp.path}/$v'));
+ if (f == null) return;
+ doItSync(f.existsSync);
+ doItSync(f.createSync);
+ doItSync(f.deleteSync);
+ doItSync(f.lengthSync);
+ doItSync(f.lastModifiedSync);
+ doItSync(() => f.path);
+ doItSync(() => f.openRead().listen((_) {}, onError: (e) {}));
+ doItSync(f.readAsBytesSync);
+ doItSync(f.readAsStringSync);
+ doItSync(f.readAsLinesSync);
+ typeMapping.forEach((k2, v2) {
+ doItSync(() => f.openSync(mode: v2));
+ doItSync(() => f.openWrite(mode: v2));
+ doItSync(() => f.readAsStringSync(encoding: v2));
+ doItSync(() => f.readAsLinesSync(encoding: v2));
+ });
});
});
}
fuzzAsyncMethods() {
asyncStart();
- var futures = <Future>[];
- typeMapping.forEach((k, v) {
- File f;
- doItSync(() => f = new File(v));
- if (f == null) return;
- futures.add(doItAsync(f.exists));
- futures.add(doItAsync(f.delete));
- futures.add(doItAsync(() => f.parent));
- futures.add(doItAsync(f.length));
- futures.add(doItAsync(f.lastModified));
- futures.add(doItAsync(f.open));
- futures.add(doItAsync(() => f.path));
- futures.add(doItAsync(f.readAsBytes));
- futures.add(doItAsync(f.readAsLines));
- futures.add(doItAsync(f.readAsString));
- typeMapping.forEach((k2, v2) {
- futures.add(doItAsync(() => f.open(mode: v2)));
- futures.add(doItAsync(() => f.readAsString(encoding: v2)));
- futures.add(doItAsync(() => f.readAsLines(encoding: v2)));
+ withTempDir('dart_file_fuzz', (temp) async {
+ var futures = <Future>[];
+ typeMapping.forEach((k, v) {
+ File f;
+ doItSync(() => f = new File('${temp.path}/$v'));
+ if (f == null) return;
+ futures.add(doItAsync(f.exists));
+ futures.add(doItAsync(f.delete));
+ futures.add(doItAsync(() => f.parent));
+ futures.add(doItAsync(f.length));
+ futures.add(doItAsync(f.lastModified));
+ futures.add(doItAsync(f.open));
+ futures.add(doItAsync(() => f.path));
+ futures.add(doItAsync(f.readAsBytes));
+ futures.add(doItAsync(f.readAsLines));
+ futures.add(doItAsync(f.readAsString));
+ typeMapping.forEach((k2, v2) {
+ futures.add(doItAsync(() => f.open(mode: v2)));
+ futures.add(doItAsync(() => f.readAsString(encoding: v2)));
+ futures.add(doItAsync(() => f.readAsLines(encoding: v2)));
+ });
+ });
+ await Future.wait(futures).then((_) {
+ asyncEnd();
});
});
- Future.wait(futures).then((_) => asyncEnd());
}
fuzzSyncRandomAccessMethods() {
- var temp = Directory.systemTemp.createTempSync('dart_file_fuzz');
- var file = new File('${temp.path}/x');
- file.createSync();
- var modes = [FileMode.read, FileMode.write, FileMode.append];
- for (var m in modes) {
- var opened = file.openSync(mode: m);
- typeMapping.forEach((k, v) {
- doItSync(() => opened.setPositionSync(v));
- doItSync(() => opened.truncateSync(v));
- doItSync(() => opened.writeByteSync(v));
- });
- for (var p in typePermutations(2)) {
- doItSync(() => opened.writeStringSync(p[0], encoding: p[1]));
- }
- for (var p in typePermutations(3)) {
- doItSync(() => opened.readIntoSync(p[0], p[1], p[2]));
- doItSync(() => opened.writeFromSync(p[0], p[1], p[2]));
- }
- opened.closeSync();
- }
- temp.deleteSync(recursive: true);
-}
-
-fuzzAsyncRandomAccessMethods() {
- var temp = Directory.systemTemp.createTempSync('dart_file_fuzz');
- var file = new File('${temp.path}/x');
- file.createSync();
- var modes = [FileMode.read, FileMode.write, FileMode.append];
- var futures = <Future>[];
- var openedFiles = [];
- for (var m in modes) {
- var opened = file.openSync(mode: m);
- openedFiles.add(opened);
- typeMapping.forEach((k, v) {
- futures.add(doItAsync(() => opened.setPosition(v)));
- futures.add(doItAsync(() => opened.truncate(v)));
- futures.add(doItAsync(() => opened.writeByte(v)));
- });
- for (var p in typePermutations(2)) {
- futures.add(doItAsync(() => opened.writeString(p[0], encoding: p[1])));
- }
- for (var p in typePermutations(3)) {
- futures.add(doItAsync(() => opened.readInto(p[0], p[1], p[2])));
- futures.add(doItAsync(() => opened.writeFrom(p[0], p[1], p[2])));
- }
- }
- Future.wait(futures).then((ignore) {
- for (var opened in openedFiles) {
+ withTempDirSync('dart_file_fuzz', (temp) {
+ var file = new File('${temp.path}/x');
+ file.createSync();
+ var modes = [FileMode.read, FileMode.write, FileMode.append];
+ for (var m in modes) {
+ var opened = file.openSync(mode: m);
+ typeMapping.forEach((k, v) {
+ doItSync(() => opened.setPositionSync(v));
+ doItSync(() => opened.truncateSync(v));
+ doItSync(() => opened.writeByteSync(v));
+ });
+ for (var p in typePermutations(2)) {
+ doItSync(() => opened.writeStringSync(p[0], encoding: p[1]));
+ }
+ for (var p in typePermutations(3)) {
+ doItSync(() => opened.readIntoSync(p[0], p[1], p[2]));
+ doItSync(() => opened.writeFromSync(p[0], p[1], p[2]));
+ }
opened.closeSync();
}
- temp.deleteSync(recursive: true);
+ });
+}
+
+fuzzAsyncRandomAccessMethods() async {
+ asyncStart();
+ await withTempDir('dart_file_fuzz', (temp) async {
+ var file = new File('${temp.path}/x');
+ file.createSync();
+ var modes = [FileMode.read, FileMode.write, FileMode.append];
+ var futures = <Future>[];
+ var openedFiles = [];
+ for (var m in modes) {
+ var opened = file.openSync(mode: m);
+ openedFiles.add(opened);
+ typeMapping.forEach((k, v) {
+ futures.add(doItAsync(() => opened.setPosition(v)));
+ futures.add(doItAsync(() => opened.truncate(v)));
+ futures.add(doItAsync(() => opened.writeByte(v)));
+ });
+ for (var p in typePermutations(2)) {
+ futures.add(doItAsync(() => opened.writeString(p[0], encoding: p[1])));
+ }
+ for (var p in typePermutations(3)) {
+ futures.add(doItAsync(() => opened.readInto(p[0], p[1], p[2])));
+ futures.add(doItAsync(() => opened.writeFrom(p[0], p[1], p[2])));
+ }
+ }
+ await Future.wait(futures).then((ignore) {
+ for (var opened in openedFiles) {
+ opened.closeSync();
+ }
+ asyncEnd();
+ });
});
}
diff --git a/tests/standalone_2/io/file_system_watcher_large_set_test.dart b/tests/standalone_2/io/file_system_watcher_large_set_test.dart
index 9b3e290..326d201 100644
--- a/tests/standalone_2/io/file_system_watcher_large_set_test.dart
+++ b/tests/standalone_2/io/file_system_watcher_large_set_test.dart
@@ -2,7 +2,7 @@
// 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.
-// VMOptions=--delayed-filewatch-callback --enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--delayed-filewatch-callback --enable-isolate-groups
// VMOptions=--delayed-filewatch-callback --no-enable-isolate-groups
// Verifies that cancelling subscription from inside of the event handler
diff --git a/tests/standalone_2/io/file_system_watcher_test.dart b/tests/standalone_2/io/file_system_watcher_test.dart
index 478f7077..bde35ce 100644
--- a/tests/standalone_2/io/file_system_watcher_test.dart
+++ b/tests/standalone_2/io/file_system_watcher_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import "dart:async";
diff --git a/tests/standalone_2/io/http_advanced_test.dart b/tests/standalone_2/io/http_advanced_test.dart
index c188870..10b6a5b 100644
--- a/tests/standalone_2/io/http_advanced_test.dart
+++ b/tests/standalone_2/io/http_advanced_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
//
// VMOptions=
diff --git a/tests/standalone_2/io/http_basic_test.dart b/tests/standalone_2/io/http_basic_test.dart
index 4356479..1cae05b 100644
--- a/tests/standalone_2/io/http_basic_test.dart
+++ b/tests/standalone_2/io/http_basic_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
//
// VMOptions=--trace_shutdown
diff --git a/tests/standalone_2/io/http_read_test.dart b/tests/standalone_2/io/http_read_test.dart
index 0cc4575..120e9ff 100644
--- a/tests/standalone_2/io/http_read_test.dart
+++ b/tests/standalone_2/io/http_read_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
//
// VMOptions=
diff --git a/tests/standalone_2/io/issue_30687_test.dart b/tests/standalone_2/io/issue_30687_test.dart
index 1392012..71ee6fd 100644
--- a/tests/standalone_2/io/issue_30687_test.dart
+++ b/tests/standalone_2/io/issue_30687_test.dart
@@ -7,40 +7,41 @@
import 'dart:io';
import 'package:expect/expect.dart';
+import 'package:path/path.dart' as path;
+
+import 'unix_socket_test.dart' show withTempDir;
main() async {
- Link link1 = new Link(
- Directory.systemTemp.path + Platform.pathSeparator + 'link1.lnk');
- Link link2 = new Link(
- Directory.systemTemp.path + Platform.pathSeparator + 'link2.lnk');
+ await withTempDir('issue_30687', (Directory tempDir) async {
+ final link1 = Link(tempDir.path + Platform.pathSeparator + 'link1.lnk');
+ final link2 = Link(tempDir.path + Platform.pathSeparator + 'link2.lnk');
- Directory target1 = new Directory(
- Directory.systemTemp.path + Platform.pathSeparator + 'target1');
- Directory target2 = new Directory(
- Directory.systemTemp.path + Platform.pathSeparator + 'target2');
+ final target1 = Directory(path.join(tempDir.path, 'target1'));
+ final target2 = Directory(path.join(tempDir.path, 'target2'));
- target1.createSync();
- target2.createSync();
+ target1.createSync();
+ target2.createSync();
- Expect.isTrue(target1.existsSync());
- Expect.isTrue(target2.existsSync());
+ Expect.isTrue(target1.existsSync());
+ Expect.isTrue(target2.existsSync());
- link1.createSync(target1.path);
- link2.createSync(target2.path);
- Expect.isTrue(link1.existsSync());
- Expect.isTrue(link2.existsSync());
+ link1.createSync(target1.path);
+ link2.createSync(target2.path);
+ Expect.isTrue(link1.existsSync());
+ Expect.isTrue(link2.existsSync());
- try {
- Link renamed = await link1.rename(link2.path);
- Expect.isFalse(link1.existsSync());
- Expect.isTrue(renamed.existsSync());
- Expect.equals(renamed.path, link2.path);
- } finally {
- target1.delete();
- target2.delete();
- link2.delete();
- if (link1.existsSync()) {
- link1.delete();
+ try {
+ Link renamed = await link1.rename(link2.path);
+ Expect.isFalse(link1.existsSync());
+ Expect.isTrue(renamed.existsSync());
+ Expect.equals(renamed.path, link2.path);
+ } finally {
+ target1.deleteSync();
+ target2.deleteSync();
+ link2.deleteSync();
+ if (link1.existsSync()) {
+ link1.deleteSync();
+ }
}
- }
+ });
}
diff --git a/tests/standalone_2/io/pipe_server_test.dart b/tests/standalone_2/io/pipe_server_test.dart
index 56253d5..4628c69 100644
--- a/tests/standalone_2/io/pipe_server_test.dart
+++ b/tests/standalone_2/io/pipe_server_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
//
// OtherResources=readline_test1.dat
diff --git a/tests/standalone_2/io/platform_test.dart b/tests/standalone_2/io/platform_test.dart
index c91fdb5..2ddc45d 100644
--- a/tests/standalone_2/io/platform_test.dart
+++ b/tests/standalone_2/io/platform_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import "dart:async";
diff --git a/tests/standalone_2/io/raw_datagram_read_all_test.dart b/tests/standalone_2/io/raw_datagram_read_all_test.dart
index d8f9fab..8b7a7d7 100644
--- a/tests/standalone_2/io/raw_datagram_read_all_test.dart
+++ b/tests/standalone_2/io/raw_datagram_read_all_test.dart
@@ -31,7 +31,7 @@
var datagram = receiver.receive();
Expect.listEquals([0], datagram.data);
if (timer != null) timer.cancel();
- timer = new Timer(const Duration(milliseconds: 200), () {
+ timer = new Timer(const Duration(seconds: 1), () {
Expect.isNull(receiver.receive());
receiver.close();
asyncEnd();
diff --git a/tests/standalone_2/io/raw_synchronous_socket_test.dart b/tests/standalone_2/io/raw_synchronous_socket_test.dart
index 1aa56d8..9e5b6bb 100644
--- a/tests/standalone_2/io/raw_synchronous_socket_test.dart
+++ b/tests/standalone_2/io/raw_synchronous_socket_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import "dart:async";
diff --git a/tests/standalone_2/io/shared_socket_test.dart b/tests/standalone_2/io/shared_socket_test.dart
index e4248bd..6a12132 100644
--- a/tests/standalone_2/io/shared_socket_test.dart
+++ b/tests/standalone_2/io/shared_socket_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import 'dart:async';
diff --git a/tests/standalone_2/io/socket_close_test.dart b/tests/standalone_2/io/socket_close_test.dart
index 16a285a..f9ad2d0 100644
--- a/tests/standalone_2/io/socket_close_test.dart
+++ b/tests/standalone_2/io/socket_close_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
//
// VMOptions=
diff --git a/tests/standalone_2/io/socket_finalizer_test.dart b/tests/standalone_2/io/socket_finalizer_test.dart
index a0cf894..ecd8de3 100644
--- a/tests/standalone_2/io/socket_finalizer_test.dart
+++ b/tests/standalone_2/io/socket_finalizer_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
//
// This test checks that sockets belonging to an isolate are properly cleaned up
diff --git a/tests/standalone_2/io/socket_many_connections_test.dart b/tests/standalone_2/io/socket_many_connections_test.dart
index 0f53fe2..0e665dc 100644
--- a/tests/standalone_2/io/socket_many_connections_test.dart
+++ b/tests/standalone_2/io/socket_many_connections_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
//
// Test creating a large number of socket connections.
diff --git a/tests/standalone_2/io/stdio_socket_finalizer_test.dart b/tests/standalone_2/io/stdio_socket_finalizer_test.dart
index b42a023..7cc1b64 100644
--- a/tests/standalone_2/io/stdio_socket_finalizer_test.dart
+++ b/tests/standalone_2/io/stdio_socket_finalizer_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
//
// This test checks that stdin is *not* closed when an Isolate leaks it.
diff --git a/tests/standalone_2/io/unix_socket_regress_46634_test.dart b/tests/standalone_2/io/unix_socket_regress_46634_test.dart
new file mode 100644
index 0000000..8920965
--- /dev/null
+++ b/tests/standalone_2/io/unix_socket_regress_46634_test.dart
@@ -0,0 +1,21 @@
+// 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.
+
+// @dart = 2.9
+import 'dart:io';
+
+import 'unix_socket_test.dart' show withTempDir, testListenCloseListenClose;
+
+void main() async {
+ if (!Platform.isMacOS && !Platform.isLinux && !Platform.isAndroid) {
+ return;
+ }
+ final futures = <Future>[];
+ for (int i = 0; i < 10; ++i) {
+ futures.add(withTempDir('unix_socket_test', (Directory dir) async {
+ await testListenCloseListenClose('${dir.path}');
+ }));
+ }
+ await Future.wait(futures);
+}
diff --git a/tests/standalone_2/io/unix_socket_test.dart b/tests/standalone_2/io/unix_socket_test.dart
index e63b9d8..a82a155 100644
--- a/tests/standalone_2/io/unix_socket_test.dart
+++ b/tests/standalone_2/io/unix_socket_test.dart
@@ -14,8 +14,6 @@
var address = InternetAddress('$name/sock', type: InternetAddressType.unix);
var server = await ServerSocket.bind(address, 0);
- var type = FileSystemEntity.typeSync(address.address);
-
var client = await Socket.connect(address, server.port);
var completer = Completer<void>();
server.listen((socket) async {
@@ -60,22 +58,23 @@
}
testBind(String name) async {
- var address = InternetAddress('$name/sock', type: InternetAddressType.unix);
- var server = await ServerSocket.bind(address, 0, shared: false);
+ final address = InternetAddress('$name/sock', type: InternetAddressType.unix);
+ final server = await ServerSocket.bind(address, 0, shared: false);
Expect.isTrue(server.address.toString().contains(name));
// Unix domain socket does not have a valid port number.
Expect.equals(server.port, 0);
- var type = FileSystemEntity.typeSync(address.address);
-
- var sub;
- sub = server.listen((s) {
- sub.cancel();
- server.close();
+ final serverContinue = Completer();
+ final clientContinue = Completer();
+ server.listen((s) async {
+ await serverContinue.future;
+ clientContinue.complete();
});
- var socket = await Socket.connect(address, server.port);
+ final socket = await Socket.connect(address, server.port);
socket.write(" socket content");
+ serverContinue.complete();
+ await clientContinue.future;
socket.destroy();
await server.close();
@@ -91,8 +90,6 @@
// test if it is working correctly.
await socket.close();
- var type = FileSystemEntity.typeSync(address.address);
-
// For robustness we ignore any clients unrelated to this test.
List<int> sendData = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
socket2.listen((Socket client) async {
@@ -129,8 +126,6 @@
completer.complete();
});
- var type = FileSystemEntity.typeSync(address.address);
-
Socket client =
await Socket.connect(address, server.port, sourceAddress: localAddress);
Expect.equals(client.remoteAddress.address, address.address);
@@ -140,12 +135,12 @@
await server.close();
}
-Future testAbstractAddress() async {
+Future testAbstractAddress(String uniqueName) async {
if (!Platform.isLinux && !Platform.isAndroid) {
return;
}
var serverAddress =
- InternetAddress('@temp.sock', type: InternetAddressType.unix);
+ InternetAddress('@temp.sock.$uniqueName', type: InternetAddressType.unix);
ServerSocket server = await ServerSocket.bind(serverAddress, 0);
final completer = Completer<void>();
final content = 'random string';
@@ -173,7 +168,7 @@
return buffer.toString();
}
-Future testShortAbstractAddress() async {
+Future testShortAbstractAddress(String uniqueName) async {
if (!Platform.isLinux && !Platform.isAndroid) {
return;
}
@@ -183,7 +178,7 @@
var stdoutFuture;
var stderrFuture;
try {
- var socketAddress = '@hidden';
+ var socketAddress = '@temp.sock.$uniqueName';
var abstractSocketServer = getAbstractSocketTestFileName();
// check if the executable exists, some build configurations do not
// build it (e.g: precompiled simarm/simarm64)
@@ -191,7 +186,7 @@
return;
}
- // Start up a subprocess that listens on '@hidden'.
+ // Start up a subprocess that listens on [socketAddress].
process = await Process.start(abstractSocketServer, [socketAddress]);
stdoutFuture = process.stdout
.transform(const Utf8Decoder(allowMalformed: true))
@@ -469,7 +464,9 @@
await withTempDir('unix_socket_test', (Directory dir) async {
await testSourceAddressConnect('${dir.path}');
});
- await testAbstractAddress();
+ await withTempDir('unix_socket_test', (Directory dir) async {
+ await testAbstractAddress(dir.uri.pathSegments.last);
+ });
await withTempDir('unix_socket_test', (Directory dir) async {
await testExistingFile('${dir.path}');
});
@@ -479,7 +476,9 @@
await withTempDir('unix_socket_test', (Directory dir) async {
await testHttpServer('${dir.path}');
});
- await testShortAbstractAddress();
+ await withTempDir('unix_socket_test', (Directory dir) async {
+ await testShortAbstractAddress(dir.uri.pathSegments.last);
+ });
} catch (e) {
if (Platform.isMacOS || Platform.isLinux || Platform.isAndroid) {
Expect.fail("Unexpected exception $e is thrown");
diff --git a/tests/standalone_2/io/wait_for_event_isolate_test.dart b/tests/standalone_2/io/wait_for_event_isolate_test.dart
index f3638ec..a22ce25 100644
--- a/tests/standalone_2/io/wait_for_event_isolate_test.dart
+++ b/tests/standalone_2/io/wait_for_event_isolate_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import 'dart:async';
diff --git a/tests/standalone_2/packages_file_test.dart b/tests/standalone_2/packages_file_test.dart
index 94132d6..a527ab4 100644
--- a/tests/standalone_2/packages_file_test.dart
+++ b/tests/standalone_2/packages_file_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import "dart:async";
diff --git a/tests/standalone_2/regress_26031_test.dart b/tests/standalone_2/regress_26031_test.dart
index fc161c8..933f5b9 100644
--- a/tests/standalone_2/regress_26031_test.dart
+++ b/tests/standalone_2/regress_26031_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
import 'dart:io';
diff --git a/tests/standalone_2/regress_28854_1_test.dart b/tests/standalone_2/regress_28854_1_test.dart
index 7b35e32..fdc3cc1 100644
--- a/tests/standalone_2/regress_28854_1_test.dart
+++ b/tests/standalone_2/regress_28854_1_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
library regress;
diff --git a/tests/standalone_2/regress_28854_2_test.dart b/tests/standalone_2/regress_28854_2_test.dart
index 23c26eb..d05b294 100644
--- a/tests/standalone_2/regress_28854_2_test.dart
+++ b/tests/standalone_2/regress_28854_2_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
library regress;
diff --git a/tests/standalone_2/standalone_2_vm.status b/tests/standalone_2/standalone_2_vm.status
index 4d8d63c..86c5c3c 100644
--- a/tests/standalone_2/standalone_2_vm.status
+++ b/tests/standalone_2/standalone_2_vm.status
@@ -7,9 +7,6 @@
link_natives_lazily_test: SkipByDesign # Not supported.
no_allow_absolute_addresses_test: SkipByDesign # Not supported.
-[ $runtime == vm ]
-typed_data_isolate_test: Pass, Slow # https://dartbug.com/36097: Slower while isolate groups are being gradually enabled in JIT mode.
-
[ $system == android ]
io/file_stat_test: Skip # Issue 26376
io/file_system_watcher_test: Skip # Issue 26376
@@ -78,19 +75,3 @@
io/dart_std_io_pipe_test: Timeout, Pass
io/http_client_stays_alive_test: Skip # Spawns process in Dart2 mode.
io/process_sync_test: Timeout, Pass
-
-[ $hot_reload || $hot_reload_rollback ]
-io/file_system_watcher_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-io/platform_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-io/raw_synchronous_socket_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-io/shared_socket_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-io/socket_finalizer_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-io/socket_many_connections_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-io/stdio_socket_finalizer_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-io/wait_for_event_isolate_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-regress_26031_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-regress_28854_1_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-regress_28854_2_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-typed_array_int64_uint64_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-typed_array_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
-typed_data_isolate_test: Skip # https://dartbug.com/36097: Ongoing concurrency work.
diff --git a/tests/standalone_2/typed_array_int64_uint64_test.dart b/tests/standalone_2/typed_array_int64_uint64_test.dart
index 3153df9..3eb3833 100644
--- a/tests/standalone_2/typed_array_int64_uint64_test.dart
+++ b/tests/standalone_2/typed_array_int64_uint64_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
//
// Dart test program for testing native typed arrays, int64 and uint64 only.
diff --git a/tests/standalone_2/typed_array_test.dart b/tests/standalone_2/typed_array_test.dart
index 0f08a80..94be7ec 100644
--- a/tests/standalone_2/typed_array_test.dart
+++ b/tests/standalone_2/typed_array_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
//
// Dart test program for testing native float and int arrays. 64-bit int arrays
diff --git a/tests/standalone_2/typed_data_isolate_test.dart b/tests/standalone_2/typed_data_isolate_test.dart
index bf2eaa4..0868696 100644
--- a/tests/standalone_2/typed_data_isolate_test.dart
+++ b/tests/standalone_2/typed_data_isolate_test.dart
@@ -4,7 +4,7 @@
// @dart = 2.9
-// VMOptions=--enable-isolate-groups --experimental-enable-isolate-groups-jit
+// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
//
// Dart test program for testing typed data.
diff --git a/tests/web/inferrer_is_int_test.dart b/tests/web/inferrer_is_int_test.dart
index f544578..59813ff 100644
--- a/tests/web/inferrer_is_int_test.dart
+++ b/tests/web/inferrer_is_int_test.dart
@@ -6,16 +6,17 @@
// literal might become an int at runtime.
import "package:expect/expect.dart";
-import '../language/compiler_annotations.dart';
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
callWithStringAndDouble(value) {
() => 42;
if (value is! int) throw new ArgumentError(value);
return 42;
}
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
callWithDouble(value) {
() => 42;
if (value is! int) throw new ArgumentError(value);
diff --git a/tests/web/internal/javascriptobject_extensions_test.dart b/tests/web/internal/javascriptobject_extensions_test.dart
new file mode 100644
index 0000000..4edd79d
--- /dev/null
+++ b/tests/web/internal/javascriptobject_extensions_test.dart
@@ -0,0 +1,197 @@
+// 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.
+
+// Tests that JS objects can be referred to as extensions of JavaScriptObject.
+
+@JS()
+library javascriptobject_extensions_test;
+
+import 'package:js/js.dart';
+import 'package:js/js_util.dart';
+import 'package:expect/expect.dart' show hasUnsoundNullSafety;
+import 'package:expect/minitest.dart';
+
+import 'dart:typed_data';
+import 'dart:_interceptors'
+ show JavaScriptObject, UnknownJavaScriptObject, JSObject;
+
+@JS()
+external void eval(String code);
+
+class InterfaceClass {}
+
+@JS('JSClass')
+class JSClass implements InterfaceClass {
+ external JSClass();
+ external String get name;
+}
+
+class ImplementationClass implements JSClass {
+ String get name => 'ImplementationClass';
+}
+
+@JS()
+@anonymous
+class AnonymousClass {
+ external String get name;
+}
+
+class DartClass {}
+
+external AnonymousClass get anonymousObj;
+
+external ByteBuffer get arrayBuffer;
+
+@JS('arrayBuffer')
+external dynamic get arrayBufferDynamic;
+
+// Extension on JavaScriptObject. In the future, when extension types are
+// introduced, this will be explicitly disallowed.
+extension JavaScriptObjectExtension on JavaScriptObject {
+ // Use `className` instead so there's no ambiguity on what method is called.
+ String get className => getProperty(this, 'name');
+}
+
+// Test runtime type checks and casts.
+@pragma('dart2js:noInline')
+void runtimeIsAndAs<T>(instance, [bool expectation = true]) {
+ expect(instance is T, expectation);
+ expect(() => instance as T, expectation ? returnsNormally : throws);
+}
+
+@pragma('dart2js:noInline')
+@pragma('dart2js:assumeDynamic')
+confuse(x) => x;
+
+JavaScriptObject returnJavaScriptObject() => throw '';
+
+JavaScriptObject? returnNullableJavaScriptObject() => throw '';
+
+JSClass returnJS() => throw '';
+
+AnonymousClass returnAnon() => throw '';
+
+UnknownJavaScriptObject returnUnknownJavaScriptObject() => throw '';
+
+ImplementationClass returnImpl() => throw '';
+
+main() {
+ eval(r'''
+ function JSClass() {
+ this.name = 'JSClass';
+ }
+ self.anonymousObj = {
+ name: 'AnonymousClass',
+ };
+ self.arrayBuffer = new ArrayBuffer();
+ ''');
+
+ // Instances of JS classes can be casted to JavaScriptObject and back.
+ var jsObj = JSClass();
+ expect(jsObj is JavaScriptObject, true);
+ runtimeIsAndAs<JavaScriptObject>(jsObj);
+ var javaScriptObject = jsObj as JavaScriptObject;
+ expect(javaScriptObject.className == 'JSClass', true);
+ expect(javaScriptObject is JSClass, true);
+ runtimeIsAndAs<JSClass>(javaScriptObject);
+
+ // Object literals can be casted to JavaScriptObject and back.
+ expect(anonymousObj is JavaScriptObject, true);
+ runtimeIsAndAs<JavaScriptObject>(anonymousObj);
+ javaScriptObject = anonymousObj as JavaScriptObject;
+ expect(javaScriptObject.className == 'AnonymousClass', true);
+ expect(javaScriptObject is AnonymousClass, true);
+ runtimeIsAndAs<AnonymousClass>(javaScriptObject);
+
+ // Dart objects that don't implement a JS type cannot be casted to or from
+ // JavaScriptObject.
+ var dartObj = DartClass();
+ expect(dartObj is JavaScriptObject, false);
+ runtimeIsAndAs<JavaScriptObject>(dartObj, false);
+ expect(javaScriptObject is DartClass, false);
+ runtimeIsAndAs<DartClass>(javaScriptObject, false);
+
+ // Native objects cannot be casted to or from JavaScriptObject.
+ expect(arrayBuffer is JavaScriptObject, false);
+ runtimeIsAndAs<JavaScriptObject>(arrayBuffer, false);
+ expect(javaScriptObject is ByteBuffer, false);
+ runtimeIsAndAs<ByteBuffer>(javaScriptObject, false);
+
+ // Dynamic native objects are intercepted and cannot be casted to
+ // JavaScriptObject.
+ runtimeIsAndAs<JavaScriptObject>(arrayBufferDynamic, false);
+
+ // Make sure `Object` methods work with JavaScriptObject like they do with JS
+ // interop objects.
+ expect(anonymousObj == javaScriptObject, true);
+ expect(javaScriptObject.hashCode, isNotNull);
+ expect(javaScriptObject.toString, isNotNull);
+ expect(javaScriptObject.noSuchMethod, isNotNull);
+ expect(javaScriptObject.runtimeType, isNotNull);
+
+ // Test that nullability works as expected.
+ expect(null is JavaScriptObject?, true);
+ runtimeIsAndAs<JavaScriptObject?>(null);
+ expect(null is JavaScriptObject, false);
+ runtimeIsAndAs<JavaScriptObject>(null, hasUnsoundNullSafety);
+
+ // Transitive is and as.
+ // JS type <: JavaScriptObject <: JSObject
+ expect(jsObj is JSObject, true);
+ runtimeIsAndAs<JSObject>(jsObj);
+ // JavaScriptObject <: JS type <: Dart interface
+ expect(javaScriptObject is InterfaceClass, true);
+ runtimeIsAndAs<InterfaceClass>(javaScriptObject);
+ // Dart implementation <: JS type <: JavaScriptObject
+ var impl = ImplementationClass();
+ expect(impl is JavaScriptObject, true);
+ runtimeIsAndAs<JavaScriptObject>(impl);
+ // Dart implementation <: JS type <: JavaScriptObject <: JSObject
+ expect(impl is JSObject, true);
+ runtimeIsAndAs<JSObject>(impl);
+
+ // Test that subtyping with nullability works as expected.
+ expect(returnJavaScriptObject is JavaScriptObject? Function(), true);
+ expect(returnNullableJavaScriptObject is JavaScriptObject Function(),
+ hasUnsoundNullSafety);
+
+ // Test that JavaScriptObject can be used in place of package:js types in
+ // function types, and vice versa.
+ expect(returnJavaScriptObject is JSClass Function(), true);
+ expect(returnJS is JavaScriptObject Function(), true);
+ expect(returnJavaScriptObject is AnonymousClass Function(), true);
+ expect(returnAnon is JavaScriptObject Function(), true);
+
+ // Transitive subtyping.
+ // UnknownJavaScriptObject <: JavaScriptObject <: JS type
+ expect(returnUnknownJavaScriptObject is JSClass Function(), true);
+ // JS type <: JavaScriptObject <: JSObject
+ expect(returnJS is JSObject Function(), true);
+ // JavaScriptObject <: JS type <: Dart interface
+ expect(returnJavaScriptObject is InterfaceClass Function(), true);
+ // Dart implementation <: JS type <: JavaScriptObject
+ expect(returnImpl is JavaScriptObject Function(), true);
+ // UnknownJavaScriptObject <: JavaScriptObject <: JS type <: Dart interface
+ expect(returnUnknownJavaScriptObject is InterfaceClass Function(), true);
+ // Dart implementation <: JS type <: JavaScriptObject <: JSObject
+ expect(returnImpl is JSObject Function(), true);
+
+ // Run above subtype checks but at runtime.
+ expect(confuse(returnJavaScriptObject) is JavaScriptObject? Function(), true);
+ expect(confuse(returnNullableJavaScriptObject) is JavaScriptObject Function(),
+ hasUnsoundNullSafety);
+
+ expect(confuse(returnJavaScriptObject) is JSClass Function(), true);
+ expect(confuse(returnJS) is JavaScriptObject Function(), true);
+ expect(confuse(returnJavaScriptObject) is AnonymousClass Function(), true);
+ expect(confuse(returnAnon) is JavaScriptObject Function(), true);
+
+ expect(confuse(returnUnknownJavaScriptObject) is JSClass Function(), true);
+ expect(confuse(returnJS) is JSObject Function(), true);
+ expect(confuse(returnJavaScriptObject) is InterfaceClass Function(), true);
+ expect(confuse(returnImpl) is JavaScriptObject Function(), true);
+ expect(confuse(returnUnknownJavaScriptObject) is InterfaceClass Function(),
+ true);
+ expect(confuse(returnImpl) is JSObject Function(), true);
+}
diff --git a/tests/web/regress/46589_test.dart b/tests/web/regress/46589_test.dart
new file mode 100644
index 0000000..c4070d5
--- /dev/null
+++ b/tests/web/regress/46589_test.dart
@@ -0,0 +1,16 @@
+// 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.
+
+import 'package:expect/expect.dart';
+
+typedef MyVoid = void;
+
+bool isVoid<X>() {
+ return X == MyVoid;
+}
+
+void main() {
+ Expect.isFalse(isVoid<int>());
+ Expect.isTrue(isVoid<void>());
+}
diff --git a/tests/web_2/inferrer_is_int_test.dart b/tests/web_2/inferrer_is_int_test.dart
index 4aa7717..0f58deb 100644
--- a/tests/web_2/inferrer_is_int_test.dart
+++ b/tests/web_2/inferrer_is_int_test.dart
@@ -8,16 +8,17 @@
// literal might become an int at runtime.
import "package:expect/expect.dart";
-import '../language_2/compiler_annotations.dart';
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
callWithStringAndDouble(value) {
() => 42;
if (value is! int) throw new ArgumentError(value);
return 42;
}
-@DontInline()
+@pragma('vm:never-inline')
+@pragma('dart2js:noInline')
callWithDouble(value) {
() => 42;
if (value is! int) throw new ArgumentError(value);
diff --git a/tests/web_2/internal/javascriptobject_extensions_test.dart b/tests/web_2/internal/javascriptobject_extensions_test.dart
new file mode 100644
index 0000000..6189667
--- /dev/null
+++ b/tests/web_2/internal/javascriptobject_extensions_test.dart
@@ -0,0 +1,179 @@
+// 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.
+
+// Tests that JS objects can be referred to as extensions of JavaScriptObject.
+
+@JS()
+library javascriptobject_extensions_test;
+
+import 'package:js/js.dart';
+import 'package:js/js_util.dart';
+import 'package:expect/minitest.dart';
+
+import 'dart:typed_data';
+import 'dart:_interceptors'
+ show JavaScriptObject, UnknownJavaScriptObject, JSObject;
+
+@JS()
+external void eval(String code);
+
+class InterfaceClass {}
+
+@JS('JSClass')
+class JSClass implements InterfaceClass {
+ external JSClass();
+ external String get name;
+}
+
+class ImplementationClass implements JSClass {
+ String get name => 'ImplementationClass';
+}
+
+@JS()
+@anonymous
+class AnonymousClass {
+ external String get name;
+}
+
+class DartClass {}
+
+external AnonymousClass get anonymousObj;
+
+external ByteBuffer get arrayBuffer;
+
+@JS('arrayBuffer')
+external dynamic get arrayBufferDynamic;
+
+// Extension on JavaScriptObject. In the future, when extension types are
+// introduced, this will be explicitly disallowed.
+extension JavaScriptObjectExtension on JavaScriptObject {
+ // Use `className` instead so there's no ambiguity on what method is called.
+ String get className => getProperty(this, 'name');
+}
+
+// Test runtime type checks and casts.
+@pragma('dart2js:noInline')
+void runtimeIsAndAs<T>(instance, [bool expectation = true]) {
+ expect(instance is T, expectation);
+ expect(() => instance as T, expectation ? returnsNormally : throws);
+}
+
+@pragma('dart2js:noInline')
+@pragma('dart2js:assumeDynamic')
+confuse(x) => x;
+
+JavaScriptObject returnJavaScriptObject() => throw '';
+
+JSClass returnJS() => throw '';
+
+AnonymousClass returnAnon() => throw '';
+
+UnknownJavaScriptObject returnUnknownJavaScriptObject() => throw '';
+
+ImplementationClass returnImpl() => throw '';
+
+main() {
+ eval(r'''
+ function JSClass() {
+ this.name = 'JSClass';
+ }
+ self.anonymousObj = {
+ name: 'AnonymousClass',
+ };
+ self.arrayBuffer = new ArrayBuffer();
+ ''');
+
+ // Instances of JS classes can be casted to JavaScriptObject and back.
+ var jsObj = JSClass();
+ expect(jsObj is JavaScriptObject, true);
+ runtimeIsAndAs<JavaScriptObject>(jsObj);
+ var javaScriptObject = jsObj as JavaScriptObject;
+ expect(javaScriptObject.className == 'JSClass', true);
+ expect(javaScriptObject is JSClass, true);
+ runtimeIsAndAs<JSClass>(javaScriptObject);
+
+ // Object literals can be casted to JavaScriptObject and back.
+ expect(anonymousObj is JavaScriptObject, true);
+ runtimeIsAndAs<JavaScriptObject>(anonymousObj);
+ javaScriptObject = anonymousObj as JavaScriptObject;
+ expect(javaScriptObject.className == 'AnonymousClass', true);
+ expect(javaScriptObject is AnonymousClass, true);
+ runtimeIsAndAs<AnonymousClass>(javaScriptObject);
+
+ // Dart objects that don't implement a JS type cannot be casted to or from
+ // JavaScriptObject.
+ var dartObj = DartClass();
+ expect(dartObj is JavaScriptObject, false);
+ runtimeIsAndAs<JavaScriptObject>(dartObj, false);
+ expect(javaScriptObject is DartClass, false);
+ runtimeIsAndAs<DartClass>(javaScriptObject, false);
+
+ // Native objects cannot be casted to or from JavaScriptObject.
+ expect(arrayBuffer is JavaScriptObject, false);
+ runtimeIsAndAs<JavaScriptObject>(arrayBuffer, false);
+ expect(javaScriptObject is ByteBuffer, false);
+ runtimeIsAndAs<ByteBuffer>(javaScriptObject, false);
+
+ // Dynamic native objects are intercepted and cannot be casted to
+ // JavaScriptObject.
+ runtimeIsAndAs<JavaScriptObject>(arrayBufferDynamic, false);
+
+ // Make sure `Object` methods work with JavaScriptObject like they do with JS
+ // interop objects.
+ expect(anonymousObj == javaScriptObject, true);
+ expect(javaScriptObject.hashCode, isNotNull);
+ expect(javaScriptObject.toString, isNotNull);
+ expect(javaScriptObject.noSuchMethod, isNotNull);
+ expect(javaScriptObject.runtimeType, isNotNull);
+
+ // Transitive is and as.
+ // JS type <: JavaScriptObject <: JSObject
+ expect(jsObj is JSObject, true);
+ runtimeIsAndAs<JSObject>(jsObj);
+ // JavaScriptObject <: JS type <: Dart interface
+ expect(javaScriptObject is InterfaceClass, true);
+ runtimeIsAndAs<InterfaceClass>(javaScriptObject);
+ // Dart implementation <: JS type <: JavaScriptObject
+ var impl = ImplementationClass();
+ expect(impl is JavaScriptObject, true);
+ runtimeIsAndAs<JavaScriptObject>(impl);
+ // Dart implementation <: JS type <: JavaScriptObject <: JSObject
+ expect(impl is JSObject, true);
+ runtimeIsAndAs<JSObject>(impl);
+
+ // Test that JavaScriptObject can be used in place of package:js types in
+ // function types, and vice versa.
+ expect(returnJavaScriptObject is JSClass Function(), true);
+ expect(returnJS is JavaScriptObject Function(), true);
+ expect(returnJavaScriptObject is AnonymousClass Function(), true);
+ expect(returnAnon is JavaScriptObject Function(), true);
+
+ // Transitive subtyping.
+ // UnknownJavaScriptObject <: JavaScriptObject <: JS type
+ expect(returnUnknownJavaScriptObject is JSClass Function(), true);
+ // JS type <: JavaScriptObject <: JSObject
+ expect(returnJS is JSObject Function(), true);
+ // JavaScriptObject <: JS type <: Dart interface
+ expect(returnJavaScriptObject is InterfaceClass Function(), true);
+ // Dart implementation <: JS type <: JavaScriptObject
+ expect(returnImpl is JavaScriptObject Function(), true);
+ // UnknownJavaScriptObject <: JavaScriptObject <: JS type <: Dart interface
+ expect(returnUnknownJavaScriptObject is InterfaceClass Function(), true);
+ // Dart implementation <: JS type <: JavaScriptObject <: JSObject
+ expect(returnImpl is JSObject Function(), true);
+
+ // Run above subtype checks but at runtime.
+ expect(confuse(returnJavaScriptObject) is JSClass Function(), true);
+ expect(confuse(returnJS) is JavaScriptObject Function(), true);
+ expect(confuse(returnJavaScriptObject) is AnonymousClass Function(), true);
+ expect(confuse(returnAnon) is JavaScriptObject Function(), true);
+
+ expect(confuse(returnUnknownJavaScriptObject) is JSClass Function(), true);
+ expect(confuse(returnJS) is JSObject Function(), true);
+ expect(confuse(returnJavaScriptObject) is InterfaceClass Function(), true);
+ expect(confuse(returnImpl) is JavaScriptObject Function(), true);
+ expect(confuse(returnUnknownJavaScriptObject) is InterfaceClass Function(),
+ true);
+ expect(confuse(returnImpl) is JSObject Function(), true);
+}
diff --git a/tests/web_2/regress/46589_test.dart b/tests/web_2/regress/46589_test.dart
new file mode 100644
index 0000000..c4070d5
--- /dev/null
+++ b/tests/web_2/regress/46589_test.dart
@@ -0,0 +1,16 @@
+// 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.
+
+import 'package:expect/expect.dart';
+
+typedef MyVoid = void;
+
+bool isVoid<X>() {
+ return X == MyVoid;
+}
+
+void main() {
+ Expect.isFalse(isVoid<int>());
+ Expect.isTrue(isVoid<void>());
+}
diff --git a/third_party/devtools/update.sh b/third_party/devtools/update.sh
index ae3aa49..90533c5 100755
--- a/third_party/devtools/update.sh
+++ b/third_party/devtools/update.sh
@@ -38,4 +38,3 @@
-install-mode copy \
-preserve-writable \
-tag git_revision:$1
-
diff --git a/tools/VERSION b/tools/VERSION
index 08a3fdb..c8fc427 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 14
PATCH 0
-PRERELEASE 301
-PRERELEASE_PATCH 2
\ No newline at end of file
+PRERELEASE 377
+PRERELEASE_PATCH 1
\ No newline at end of file
diff --git a/tools/bots/flutter/analyze_flutter_plugins.sh b/tools/bots/flutter/analyze_flutter_plugins.sh
index 9696c74..3616faa 100755
--- a/tools/bots/flutter/analyze_flutter_plugins.sh
+++ b/tools/bots/flutter/analyze_flutter_plugins.sh
@@ -36,4 +36,6 @@
(cd script/tool; dart analyze --fatal-infos)
# Invoke the repo's analysis script.
-./script/tool_runner.sh analyze --analysis-sdk $sdk
+./script/tool_runner.sh analyze \
+ --analysis-sdk $sdk \
+ --custom-analysis=script/configs/custom_analysis.yaml
diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json
index 0120f7e..6120112 100644
--- a/tools/bots/test_matrix.json
+++ b/tools/bots/test_matrix.json
@@ -1727,11 +1727,44 @@
},
"steps": [
{
- "name": "build dart",
+ "name": "build dart ia32",
"script": "tools/build.py",
"arguments": [
"--mode=all",
- "--arch=all",
+ "--arch=ia32",
+ "--no-clang",
+ "--no-goma",
+ "runtime"
+ ]
+ },
+ {
+ "name": "build dart x64",
+ "script": "tools/build.py",
+ "arguments": [
+ "--mode=all",
+ "--arch=x64",
+ "--no-clang",
+ "--no-goma",
+ "runtime"
+ ]
+ },
+ {
+ "name": "build dart simarm",
+ "script": "tools/build.py",
+ "arguments": [
+ "--mode=all",
+ "--arch=simarm",
+ "--no-clang",
+ "--no-goma",
+ "runtime"
+ ]
+ },
+ {
+ "name": "build dart simarm64",
+ "script": "tools/build.py",
+ "arguments": [
+ "--mode=all",
+ "--arch=simarm64",
"--no-clang",
"--no-goma",
"runtime"
diff --git a/tools/dom/docs/docs.json b/tools/dom/docs/docs.json
index f24f9ed..72cf73a 100644
--- a/tools/dom/docs/docs.json
+++ b/tools/dom/docs/docs.json
@@ -117,7 +117,9 @@
"/**",
" * An opaque canvas object representing a gradient.",
" *",
- " * Created by calling [createLinearGradient] or [createRadialGradient] on a",
+ " * Created by calling the methods",
+ " * [CanvasRenderingContext2D.createLinearGradient] or",
+ " * [CanvasRenderingContext2D.createRadialGradient] on a",
" * [CanvasRenderingContext2D] object.",
" *",
" * Example usage:",
@@ -164,7 +166,8 @@
"/**",
" * An opaque object representing a pattern of image, canvas, or video.",
" *",
- " * Created by calling [createPattern] on a [CanvasRenderingContext2D] object.",
+ " * Created by calling [CanvasRenderingContext2D.createPattern] on a",
+ " * [CanvasRenderingContext2D] object.",
" *",
" * Example usage:",
" *",
@@ -2553,7 +2556,7 @@
" * * [COMMENT_NODE] if this node is a [Comment].",
" * * [DOCUMENT_FRAGMENT_NODE] if this node is a [DocumentFragment].",
" * * [DOCUMENT_NODE] if this node is a [Document].",
- " * * [DOCUMENT_TYPE_NODE] if this node is a [DocumentType] node.",
+ " * * [DOCUMENT_TYPE_NODE] if this node is a [_DocumentType] node.",
" * * [ELEMENT_NODE] if this node is an [Element].",
" * * [ENTITY_NODE] if this node is an entity.",
" * * [ENTITY_REFERENCE_NODE] if this node is an entity reference.",
@@ -3171,7 +3174,7 @@
" * The message event handler receives a [MessageEvent] object",
" * as its sole argument.",
" * You can also define open, close, and error handlers,",
- " * as specified by [WebSocketEvents].",
+ " * as specified by [Event]s.",
" *",
" * For more information, see the",
" * [WebSockets](http://www.dartlang.org/docs/library-tour/#html-websockets)",
@@ -4355,7 +4358,8 @@
" * Length of time in milliseconds before a request is automatically",
" * terminated.",
" *",
- " * When the time has passed, a [TimeoutEvent] is dispatched.",
+ " * When the time has passed, a [HttpRequestEventTarget.timeoutEvent] is",
+ " * dispatched.",
" *",
" * If [timeout] is set to 0, then the request will not time out.",
" *",
@@ -4370,7 +4374,6 @@
"upload": [
"/**",
" * [EventTarget] that can hold listeners to track the progress of the request.",
- " * The events fired will be members of [HttpRequestUploadEvents].",
" */"
],
"withCredentials": [
@@ -5157,9 +5160,9 @@
"/**",
" * Get a Stream that fires events when AudioProcessingEvents occur.",
" * This particular stream is special in that it only allows one listener to a",
- " * given stream. Converting the returned Stream [asBroadcast] will likely ruin",
- " * the soft-real-time properties which which these events are fired and can",
- " * be processed.",
+ " * given stream. Converting the returned [Stream.asBroadcastStream] will",
+ " * likely ruin the soft-real-time properties which which these events are",
+ " * fired and can be processed.",
" */"
]
}
diff --git a/tools/dom/scripts/dartdomgenerator.py b/tools/dom/scripts/dartdomgenerator.py
index 6e529a4..944d36a 100755
--- a/tools/dom/scripts/dartdomgenerator.py
+++ b/tools/dom/scripts/dartdomgenerator.py
@@ -207,9 +207,9 @@
prefix_arg, 'cd', library_dir, ';', copy_dart_script, output_dir, library_filename
])
subprocess.call([command], shell=True)
- prebuilt_dartfmt = os.path.join(utils.CheckedInSdkPath(), 'bin', 'dartfmt')
+ dart_bin = os.path.join(utils.CheckedInSdkPath(), 'bin', 'dart')
sdk_file = os.path.join(library_dir, output_dir, library_filename)
- formatCommand = ' '.join([prebuilt_dartfmt, '-w', sdk_file])
+ formatCommand = ' '.join([dart_bin, 'format', sdk_file])
subprocess.call([formatCommand], shell=True)
diff --git a/tools/dom/src/CssRectangle.dart b/tools/dom/src/CssRectangle.dart
index d26aac7..6aa6393 100644
--- a/tools/dom/src/CssRectangle.dart
+++ b/tools/dom/src/CssRectangle.dart
@@ -182,8 +182,8 @@
*
* This is equivalent to the `height` function in jQuery and the calculated
* `height` CSS value, converted to a dimensionless num in pixels. Unlike
- * [getBoundingClientRect], `height` will return the same numerical width if
- * the element is hidden or not.
+ * [Element.getBoundingClientRect], `height` will return the same numerical
+ * height if the element is hidden or not.
*/
num get height;
@@ -192,8 +192,8 @@
*
* This is equivalent to the `width` function in jQuery and the calculated
* `width` CSS value, converted to a dimensionless num in pixels. Unlike
- * [getBoundingClientRect], `width` will return the same numerical width if
- * the element is hidden or not.
+ * [Element.getBoundingClientRect], `width` will return the same numerical
+ * width if the element is hidden or not.
*/
num get width;
diff --git a/tools/dom/src/EventStreamProvider.dart b/tools/dom/src/EventStreamProvider.dart
index feadc26..90b19aa 100644
--- a/tools/dom/src/EventStreamProvider.dart
+++ b/tools/dom/src/EventStreamProvider.dart
@@ -38,7 +38,7 @@
new _EventStream<T>(e, _eventType, useCapture);
/**
- * Gets an [ElementEventStream] for this event type, on the specified element.
+ * Gets a [Stream] for this event type, on the specified element.
*
* This will always return a broadcast stream so multiple listeners can be
* used simultaneously.
@@ -64,7 +64,7 @@
}
/**
- * Gets an [ElementEventStream] for this event type, on the list of elements.
+ * Gets a [Stream] for this event type, on the list of elements.
*
* This will always return a broadcast stream so multiple listeners can be
* used simultaneously.
diff --git a/tools/dom/templates/html/dart2js/html_dart2js.darttemplate b/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
index 0b19506..fd4069b 100644
--- a/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
+++ b/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
@@ -18,6 +18,7 @@
* For information on writing web apps with Dart, see https://dart.dev/web.
*
* {@category Web}
+ * {@canonicalFor dart:_internal.HttpStatus}
*/
library dart.dom.html;
diff --git a/tools/dom/templates/html/dart2js/indexed_db_dart2js.darttemplate b/tools/dom/templates/html/dart2js/indexed_db_dart2js.darttemplate
index dc05346..8373820 100644
--- a/tools/dom/templates/html/dart2js/indexed_db_dart2js.darttemplate
+++ b/tools/dom/templates/html/dart2js/indexed_db_dart2js.darttemplate
@@ -69,8 +69,6 @@
* basic mechanism that stores data as a [Map],
* and where both the keys and the values are strings.
*
- * * [dart:web_sql]—a database that can be queried with SQL.
- *
* MDN provides [API
* documentation](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API).
*
diff --git a/tools/dom/templates/html/impl/impl_CanvasRenderingContext2D.darttemplate b/tools/dom/templates/html/impl/impl_CanvasRenderingContext2D.darttemplate
index 2e9ba25..ec1f2e4 100644
--- a/tools/dom/templates/html/impl/impl_CanvasRenderingContext2D.darttemplate
+++ b/tools/dom/templates/html/impl/impl_CanvasRenderingContext2D.darttemplate
@@ -279,7 +279,7 @@
* options, such as typeface and size, and the current
* [CanvasRenderingContext2D.fillStyle] for style options such as color.
* The current [CanvasRenderingContext2D.textAlign] and
- * [CanvasRenderingContext2D.textBaseLine] properties are also applied to the
+ * [CanvasRenderingContext2D.textBaseline] properties are also applied to the
* drawn text.
*/
void fillText(String text, num x, num y, [num$NULLABLE maxWidth]) {
diff --git a/tools/dom/templates/html/impl/impl_Element.darttemplate b/tools/dom/templates/html/impl/impl_Element.darttemplate
index 4368af2..fadfc3b 100644
--- a/tools/dom/templates/html/impl/impl_Element.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Element.darttemplate
@@ -215,7 +215,7 @@
CssStyleDeclarationBase get style;
/**
- * Access dimensions and position of the Elements in this list.
+ * Access dimensions and position of the [Element]s in this list.
*
* Setting the height or width properties will set the height or width
* property for all elements in the list. This returns a rectangle with the
@@ -224,46 +224,48 @@
* property. Getting the height or width returns the height or width of the
* first Element in this list.
*
- * Unlike [getBoundingClientRect], the dimensions of this rectangle
+ * Unlike [Element.getBoundingClientRect], the dimensions of this rectangle
* will return the same numerical height if the element is hidden or not.
*/
CssRect get contentEdge;
/**
- * Access dimensions and position of the first Element's content + padding box
- * in this list.
+ * Access dimensions and position of the first [Element]'s content + padding
+ * box in this list.
*
* This returns a rectangle with the dimensions actually available for content
* in this element, in pixels, regardless of this element's box-sizing
- * property. Unlike [getBoundingClientRect], the dimensions of this rectangle
- * will return the same numerical height if the element is hidden or not. This
- * can be used to retrieve jQuery's `innerHeight` value for an element. This
- * is also a rectangle equalling the dimensions of clientHeight and
- * clientWidth.
+ * property. Unlike [Element.getBoundingClientRect], the dimensions of this
+ * rectangle will return the same numerical height if the element is hidden
+ * or not. This can be used to retrieve jQuery's `innerHeight` value for an
+ * element. This is also a rectangle equalling the dimensions of clientHeight
+ * and clientWidth.
*/
CssRect get paddingEdge;
/**
- * Access dimensions and position of the first Element's content + padding +
+ * Access dimensions and position of the first [Element]'s content + padding +
* border box in this list.
*
* This returns a rectangle with the dimensions actually available for content
* in this element, in pixels, regardless of this element's box-sizing
- * property. Unlike [getBoundingClientRect], the dimensions of this rectangle
- * will return the same numerical height if the element is hidden or not. This
- * can be used to retrieve jQuery's `outerHeight` value for an element.
+ * property. Unlike [Element.getBoundingClientRect], the dimensions of this
+ * rectangle will return the same numerical height if the element is hidden
+ * or not. This can be used to retrieve jQuery's `outerHeight` value for an
+ * element.
*/
CssRect get borderEdge;
/**
- * Access dimensions and position of the first Element's content + padding +
+ * Access dimensions and position of the first [Element]'s content + padding +
* border + margin box in this list.
*
* This returns a rectangle with the dimensions actually available for content
* in this element, in pixels, regardless of this element's box-sizing
- * property. Unlike [getBoundingClientRect], the dimensions of this rectangle
- * will return the same numerical height if the element is hidden or not. This
- * can be used to retrieve jQuery's `outerHeight` value for an element.
+ * property. Unlike [Element.getBoundingClientRect], the dimensions of this
+ * rectangle will return the same numerical height if the element is hidden
+ * or not. This can be used to retrieve jQuery's `outerHeight` value for an
+ * element.
*/
CssRect get marginEdge;
$!STREAM_GETTER_SIGNATURES
@@ -927,9 +929,9 @@
*
* The [frames] parameter is an Iterable<Map>, where the
* map entries specify CSS animation effects. The
- * [timing] paramter can be a double, representing the number of milliseconds
- * for the transition, or a Map with fields corresponding to those
- * of the [Timing] object.
+ * [timing] parameter can be a double, representing the number of
+ * milliseconds for the transition, or a Map with fields corresponding to
+ * those of the [timing] object.
*/
@SupportedBrowser(SupportedBrowser.CHROME, '36')
Animation animate(Iterable<Map<String, dynamic>> frames, [timing]) {
@@ -1081,11 +1083,13 @@
* * 'beforeEnd': As the last child of this element.
* * 'afterEnd': Immediately after this element.
*
+ * ```dart
* var html = '<div class="something">content</div>';
* // Inserts as the first child
* document.body.insertAdjacentHtml('afterBegin', html);
* var createdElement = document.body.children[0];
* print(createdElement.classes[0]); // Prints 'something'
+ * ```
*
* See also:
*
diff --git a/tools/dom/templates/html/impl/impl_HTMLInputElement.darttemplate b/tools/dom/templates/html/impl/impl_HTMLInputElement.darttemplate
index 19aa838..50f57db 100644
--- a/tools/dom/templates/html/impl/impl_HTMLInputElement.darttemplate
+++ b/tools/dom/templates/html/impl/impl_HTMLInputElement.darttemplate
@@ -463,7 +463,7 @@
/**
- * A control that when used with other [ReadioButtonInputElement] controls
+ * A control that when used with other [RadioButtonInputElement] controls
* forms a radio button group in which only one control can be checked at a
* time.
*
diff --git a/tools/dom/templates/html/impl/impl_Window.darttemplate b/tools/dom/templates/html/impl/impl_Window.darttemplate
index 98e07f0..15f8219 100644
--- a/tools/dom/templates/html/impl/impl_Window.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Window.darttemplate
@@ -157,8 +157,8 @@
/**
* Gets an instance of the Indexed DB factory to being using Indexed DB.
*
- * Use [indexed_db.IdbFactory.supported] to check if Indexed DB is supported on the
- * current platform.
+ * Use [dart:indexed_db.IdbFactory.supported] to check if Indexed DB is
+ * supported on the current platform.
*/
@SupportedBrowser(SupportedBrowser.CHROME, '23.0')
@SupportedBrowser(SupportedBrowser.FIREFOX, '15.0')
diff --git a/tools/dom/templates/html/impl/impl_XMLHttpRequest.darttemplate b/tools/dom/templates/html/impl/impl_XMLHttpRequest.darttemplate
index 44d7ea4..7e92f1d 100644
--- a/tools/dom/templates/html/impl/impl_XMLHttpRequest.darttemplate
+++ b/tools/dom/templates/html/impl/impl_XMLHttpRequest.darttemplate
@@ -148,7 +148,7 @@
* * Using credentials is only useful for cross-origin requests.
* * The `Access-Control-Allow-Origin` header of `url` cannot contain a wildcard (*).
* * The `Access-Control-Allow-Credentials` header of `url` must be set to true.
- * * If `Access-Control-Expose-Headers` has not been set to true, only a subset of all the response headers will be returned when calling [getAllRequestHeaders].
+ * * If `Access-Control-Expose-Headers` has not been set to true, only a subset of all the response headers will be returned when calling [getAllResponseHeaders].
*
* The following is equivalent to the [getString] sample above:
*
diff --git a/tools/generate_idefiles.py b/tools/generate_idefiles.py
index 7809c64..ac75696 100755
--- a/tools/generate_idefiles.py
+++ b/tools/generate_idefiles.py
@@ -23,7 +23,6 @@
def GenerateIdeFiles(options):
GenerateCompileCommands(options)
- GenerateAnalysisOptions(options)
def GenerateCompileCommands(options):
@@ -81,64 +80,6 @@
return 0
-def GenerateAnalysisOptions(options):
- """Generate analysis_optioms.yaml for the Dart analyzer.
-
- To prevent dartanalyzer from tripping on the non-Dart files when it is
- started from the root dart-sdk directory.
- https://github.com/dart-lang/sdk/issues/35562
-
- Args:
- options: supported options include: force, dir
- """
- contents = """analyzer:
- exclude:
- - benchmarks/**
- - benchmarks-internal/**
- - docs/newsletter/20171103/**
- - pkg/**
- - out/**
- - runtime/**
- - samples-dev/swarm/**
- - sdk/lib/**
- - tests/co19/**
- - tests/co19_2/**
- - tests/corelib/**
- - tests/corelib_2/**
- - tests/web/**
- - tests/web_2/**
- - tests/dartdevc/**
- - tests/dartdevc_2/**
- - tests/ffi/**
- - tests/ffi_2/**
- - tests/language/**
- - tests/language_2/**
- - tests/lib/**
- - tests/lib_2/**
- - tests/modular/**
- - tests/standalone/**
- - tests/standalone_2/**
- - third_party/observatory_pub_packages/**
- - third_party/pkg/**
- - third_party/pkg_tested/dart_style/**
- - third_party/tcmalloc/**
- - tools/apps/update_homebrew/**
- - tools/dart2js/**
- - tools/dom/**
- - tools/sdks/dart-sdk/lib/**
- - tools/status_clean.dart
- - xcodebuild/**"""
-
- fname = os.path.join(options.dir, "analysis_options.yaml")
-
- if os.path.isfile(fname) and not options.force:
- print(fname + " already exists, use --force to override")
- return
-
- with open(fname, "w") as f:
- f.write(contents)
-
-
def main(argv):
parser = argparse.ArgumentParser(
description="Python script to generate compile_commands.json and "
diff --git a/tools/generate_package_config.dart b/tools/generate_package_config.dart
index 7b9a07d..882c827 100644
--- a/tools/generate_package_config.dart
+++ b/tools/generate_package_config.dart
@@ -92,22 +92,20 @@
packages.sort((a, b) => a["name"].compareTo(b["name"]));
var configFile = File(p.join(repoRoot, '.dart_tool', 'package_config.json'));
+ var json =
+ jsonDecode(configFile.readAsStringSync()) as Map<dynamic, dynamic>;
+ var oldPackages = json['packages'] as List<dynamic>;
// Validate the packages entry only, to avoid spurious failures from changes
// in the dates embedded in the other entries.
- if (checkOnly) {
- var json =
- jsonDecode(configFile.readAsStringSync()) as Map<dynamic, dynamic>;
- var oldPackages = json['packages'] as List<dynamic>;
- if (jsonEncode(packages) == jsonEncode(oldPackages)) {
- print("Package config up to date");
- exit(0);
- } else {
- print("Package config out of date");
- print("Run `gclient sync -D && dart tools/generate_package_config.dart` "
- "to update.");
- exit(1);
- }
+ if (jsonEncode(packages) == jsonEncode(oldPackages)) {
+ print("Package config up to date");
+ exit(0);
+ } else if (checkOnly) {
+ print("Package config out of date");
+ print("Run `gclient sync -D && dart tools/generate_package_config.dart` "
+ "to update.");
+ exit(1);
}
var year = DateTime.now().year;
@@ -130,8 +128,8 @@
};
// TODO(rnystrom): Consider using package_config_v2 to generate this instead.
- var json = JsonEncoder.withIndent(' ').convert(config);
- configFile.writeAsStringSync('$json\n');
+ var jsonString = JsonEncoder.withIndent(' ').convert(config);
+ configFile.writeAsStringSync('$jsonString\n');
print('Generated .dart_tool/package_config.dart containing '
'${packages.length} packages.');
}
diff --git a/tools/make_version.py b/tools/make_version.py
index c99511b..bf2c9c5 100755
--- a/tools/make_version.py
+++ b/tools/make_version.py
@@ -23,7 +23,6 @@
'object.h',
'raw_object.h',
'snapshot.h',
- 'snapshot_ids.h',
'symbols.h',
# Source files.
'clustered_snapshot.cc',
@@ -32,7 +31,6 @@
'image_snapshot.cc',
'object.cc',
'raw_object.cc',
- 'raw_object_snapshot.cc',
'snapshot.cc',
'symbols.cc',
]
diff --git a/tools/spec_parser/Dart.g b/tools/spec_parser/Dart.g
index 5f79d24..e1d7db2 100644
--- a/tools/spec_parser/Dart.g
+++ b/tools/spec_parser/Dart.g
@@ -372,7 +372,9 @@
| EXTERNAL? operatorSignature
| STATIC (FINAL | CONST) type? staticFinalDeclarationList
| STATIC LATE FINAL type? initializedIdentifierList
- | (STATIC | COVARIANT) LATE? varOrType initializedIdentifierList
+ | STATIC LATE? varOrType initializedIdentifierList
+ | COVARIANT LATE FINAL type? identifierList
+ | COVARIANT LATE? varOrType initializedIdentifierList
| LATE? (FINAL type? | varOrType) initializedIdentifierList
| redirectingFactoryConstructorSignature
| constantConstructorSignature (redirection | initializers)?
diff --git a/tools/yaml2json.dart b/tools/yaml2json.dart
index 8ce4907..e8b6a07 100644
--- a/tools/yaml2json.dart
+++ b/tools/yaml2json.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'dart:io' show File, exit, stderr;
import 'dart:isolate' show RawReceivePort;
@@ -12,7 +10,7 @@
import 'package:yaml/yaml.dart' show loadYaml;
-main(List<String> arguments) async {
+main(List<String> arguments) {
var port = new RawReceivePort();
if (arguments.length != 2) {
stderr.writeln("Usage: yaml2json.dart input.yaml output.json");
@@ -20,7 +18,7 @@
}
Uri input = Uri.base.resolve(arguments[0]);
Uri output = Uri.base.resolve(arguments[1]);
- Map yaml = loadYaml(await new File.fromUri(input).readAsString());
+ Map yaml = loadYaml(new File.fromUri(input).readAsStringSync());
Map<String, dynamic> result = new Map<String, dynamic>();
result["comment:0"] = "NOTE: THIS FILE IS GENERATED. DO NOT EDIT.";
result["comment:1"] =
@@ -29,6 +27,6 @@
result[key] = yaml[key];
}
File file = new File.fromUri(output);
- await file.writeAsString(const JsonEncoder.withIndent(" ").convert(result));
+ file.writeAsStringSync(const JsonEncoder.withIndent(" ").convert(result));
port.close();
}
diff --git a/tools/yaml2json.py b/tools/yaml2json.py
deleted file mode 100755
index 251f657..0000000
--- a/tools/yaml2json.py
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (c) 2017, 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.
-
-import os
-import subprocess
-import sys
-
-import utils
-
-
-def Main():
- args = sys.argv[1:]
- yaml2json_dart = os.path.relpath(
- os.path.join(os.path.dirname(__file__), "yaml2json.dart"))
- command = [utils.CheckedInSdkExecutable(), yaml2json_dart] + args
-
- with utils.CoreDumpArchiver(args):
- exit_code = subprocess.call(command)
-
- utils.DiagnoseExitCode(exit_code, command)
- return exit_code
-
-
-if __name__ == '__main__':
- sys.exit(Main())
diff --git a/utils/application_snapshot.gni b/utils/application_snapshot.gni
index 317153a..6a2efbb 100644
--- a/utils/application_snapshot.gni
+++ b/utils/application_snapshot.gni
@@ -82,6 +82,9 @@
# Build the kernel file using the prebuilt VM to speed up the debug and
# simulator builds.
prebuilt_dart_action(target_name + "_dill") {
+ if (defined(invoker.pool)) {
+ pool = invoker.pool
+ }
deps = extra_deps + [
"$_dart_root/runtime/vm:kernel_platform_files($host_toolchain)",
"$_dart_root/runtime/vm:vm_platform",
@@ -131,6 +134,9 @@
# Create a snapshot from kernel built above.
dart_action(target_name) {
+ if (defined(invoker.pool)) {
+ pool = invoker.pool
+ }
deps = extra_deps + [ ":${target_name}_dill" ]
depfile = "$output.d"
diff --git a/utils/compile_platform.gni b/utils/compile_platform.gni
index 447ed64..37c3407 100644
--- a/utils/compile_platform.gni
+++ b/utils/compile_platform.gni
@@ -41,6 +41,9 @@
}
prebuilt_dart_action(target_name) {
+ if (defined(invoker.pool)) {
+ pool = invoker.pool
+ }
script = "$_dart_root/pkg/front_end/tool/_fasta/compile_platform.dart"
packages = "$_dart_root/.packages"